about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <github35764891676564198441@oli-obk.de>2024-12-15 05:35:37 +0000
committerGitHub <noreply@github.com>2024-12-15 05:35:37 +0000
commite999c48404b492659f90993e9fdd2544c675abce (patch)
tree57e9863e82b35af828fb9ea01e1067f656f8cf26
parentd5322f75df7ec605bbcca5d9ec329e32bb696f69 (diff)
parent581989d1c6de8ece197b1317e3093203d3203d66 (diff)
downloadrust-e999c48404b492659f90993e9fdd2544c675abce.tar.gz
rust-e999c48404b492659f90993e9fdd2544c675abce.zip
Merge pull request #4095 from rust-lang/rustup-2024-12-15
Automatic Rustup
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_ast/src/ast.rs31
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs18
-rw-r--r--compiler/rustc_ast/src/util/classify.rs6
-rw-r--r--compiler/rustc_ast/src/visit.rs10
-rw-r--r--compiler/rustc_ast_lowering/src/block.rs19
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs17
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs1
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs8
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs19
-rw-r--r--compiler/rustc_borrowck/src/borrow_set.rs50
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs4
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs93
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs69
-rw-r--r--compiler/rustc_borrowck/src/lib.rs59
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs10
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs10
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs7
-rw-r--r--compiler/rustc_codegen_gcc/messages.ftl2
-rw-r--r--compiler/rustc_codegen_gcc/src/errors.rs1
-rw-r--r--compiler/rustc_codegen_gcc/src/gcc_util.rs20
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs11
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs67
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs59
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs30
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs34
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs53
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs4
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs25
-rw-r--r--compiler/rustc_const_eval/src/check_consts/resolver.rs4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/fn_queries.rs30
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs37
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/stack.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs13
-rw-r--r--compiler/rustc_data_structures/src/jobserver.rs2
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs42
-rw-r--r--compiler/rustc_errors/src/emitter.rs15
-rw-r--r--compiler/rustc_expand/src/expand.rs32
-rw-r--r--compiler/rustc_expand/src/module.rs10
-rw-r--r--compiler/rustc_feature/src/removed.rs3
-rw-r--r--compiler/rustc_feature/src/unstable.rs5
-rw-r--r--compiler/rustc_hir/src/hir.rs43
-rw-r--r--compiler/rustc_hir/src/intravisit.rs11
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl12
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs216
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs45
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs52
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs249
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs33
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs28
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs34
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs45
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs34
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/gather_locals.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs30
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs2
-rw-r--r--compiler/rustc_interface/src/interface.rs8
-rw-r--r--compiler/rustc_interface/src/passes.rs12
-rw-r--r--compiler/rustc_interface/src/queries.rs12
-rw-r--r--compiler/rustc_interface/src/util.rs4
-rw-r--r--compiler/rustc_lint/messages.ftl4
-rw-r--r--compiler/rustc_lint/src/builtin.rs2
-rw-r--r--compiler/rustc_lint/src/context/diagnostics/check_cfg.rs68
-rw-r--r--compiler/rustc_lint/src/dangling.rs2
-rw-r--r--compiler/rustc_lint/src/if_let_rescope.rs1
-rw-r--r--compiler/rustc_lint/src/lints.rs44
-rw-r--r--compiler/rustc_metadata/src/dependency_format.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs16
-rw-r--r--compiler/rustc_middle/src/middle/dependency_format.rs3
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs3
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs12
-rw-r--r--compiler/rustc_middle/src/query/keys.rs11
-rw-r--r--compiler/rustc_middle/src/query/mod.rs7
-rw-r--r--compiler/rustc_middle/src/query/plumbing.rs10
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs23
-rw-r--r--compiler/rustc_middle/src/ty/context.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs25
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs43
-rw-r--r--compiler/rustc_middle/src/ty/util.rs2
-rw-r--r--compiler/rustc_middle/src/values.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs92
-rw-r--r--compiler/rustc_mir_build/src/build/matches/match_pair.rs5
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs10
-rw-r--r--compiler/rustc_mir_build/src/thir/util.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/cursor.rs10
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/direction.rs88
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs8
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/lattice.rs63
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs82
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/results.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/tests.rs48
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/visitor.rs21
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs12
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/initialized.rs102
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs44
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/mod.rs3
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs78
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/points.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/rustc_peek.rs3
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs4
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs12
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs32
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs13
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs3
-rw-r--r--compiler/rustc_mir_transform/src/strip_debuginfo.rs34
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs8
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs40
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs94
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs23
-rw-r--r--compiler/rustc_parse/src/parser/item.rs2
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs19
-rw-r--r--compiler/rustc_passes/src/input_stats.rs42
-rw-r--r--compiler/rustc_passes/src/liveness.rs3
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs1
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs4
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs6
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs6
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/ident.rs82
-rw-r--r--compiler/rustc_resolve/src/imports.rs8
-rw-r--r--compiler/rustc_resolve/src/late.rs29
-rw-r--r--compiler/rustc_resolve/src/lib.rs6
-rw-r--r--compiler/rustc_resolve/src/macros.rs2
-rw-r--r--compiler/rustc_session/src/config.rs16
-rw-r--r--compiler/rustc_session/src/config/cfg.rs2
-rw-r--r--compiler/rustc_session/src/options.rs14
-rw-r--r--compiler/rustc_session/src/session.rs10
-rw-r--r--compiler/rustc_smir/src/rustc_internal/internal.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/mir.rs7
-rw-r--r--compiler/rustc_span/src/hygiene.rs4
-rw-r--r--compiler/rustc_span/src/symbol.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs29
-rw-r--r--compiler/rustc_target/src/callconv/powerpc64.rs2
-rw-r--r--compiler/rustc_target/src/spec/base/linux_musl.rs3
-rw-r--r--compiler/rustc_target/src/spec/mod.rs12
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/target_features.rs778
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs115
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/effects.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs14
-rw-r--r--compiler/stable_mir/src/mir/body.rs8
-rw-r--r--compiler/stable_mir/src/mir/pretty.rs4
-rw-r--r--compiler/stable_mir/src/ty.rs11
-rw-r--r--compiler/stable_mir/src/visitor.rs1
-rw-r--r--library/core/src/error.rs4
-rw-r--r--library/core/src/fmt/rt.rs34
-rw-r--r--library/core/src/hint.rs92
-rw-r--r--library/core/src/iter/traits/collect.rs63
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/ptr/mod.rs9
-rw-r--r--library/core/src/unsafe_binder.rs25
-rw-r--r--library/std/src/lib.rs2
-rw-r--r--library/std/src/path.rs4
-rw-r--r--library/std/src/pipe.rs140
-rw-r--r--library/std/src/sys/pal/hermit/fs.rs6
-rw-r--r--library/std/src/sys/pal/hermit/mod.rs2
-rw-r--r--library/std/src/sys/pal/hermit/os.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs25
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs39
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs5
-rw-r--r--src/bootstrap/src/core/config/config.rs26
-rw-r--r--src/bootstrap/src/utils/cc_detect.rs10
-rw-r--r--src/ci/docker/host-x86_64/dist-various-2/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/test-various/Dockerfile4
-rw-r--r--src/doc/rustc/src/SUMMARY.md2
-rw-r--r--src/doc/rustc/src/platform-support.md6
-rw-r--r--src/doc/rustc/src/platform-support/solaris.md32
-rw-r--r--src/librustdoc/clean/mod.rs9
-rw-r--r--src/librustdoc/html/render/search_index.rs8
-rw-r--r--src/librustdoc/lib.rs4
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/duplicate_mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_nesting.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_float_methods.rs43
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs18
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs1
-rw-r--r--src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr3
-rw-r--r--src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr1
-rw-r--r--src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr1
-rw-r--r--src/tools/clippy/tests/ui/async_yields_async.stderr1
-rw-r--r--src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr1
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr6
-rw-r--r--src/tools/clippy/tests/ui/collapsible_else_if.stderr10
-rw-r--r--src/tools/clippy/tests/ui/copy_iterator.stderr1
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-360.stderr8
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr3
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.stderr1
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr3
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr3
-rw-r--r--src/tools/clippy/tests/ui/entry.stderr5
-rw-r--r--src/tools/clippy/tests/ui/enum_variants.stderr3
-rw-r--r--src/tools/clippy/tests/ui/fallible_impl_from.stderr3
-rw-r--r--src/tools/clippy/tests/ui/if_same_then_else2.stderr2
-rw-r--r--src/tools/clippy/tests/ui/infinite_loops.stderr13
-rw-r--r--src/tools/clippy/tests/ui/into_iter_without_iter.stderr8
-rw-r--r--src/tools/clippy/tests/ui/manual_find.stderr2
-rw-r--r--src/tools/clippy/tests/ui/manual_find_fixable.stderr36
-rw-r--r--src/tools/clippy/tests/ui/manual_flatten.stderr1
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else.stderr4
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or.stderr2
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.stderr3
-rw-r--r--src/tools/clippy/tests/ui/match_bool.stderr3
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr3
-rw-r--r--src/tools/clippy/tests/ui/missing_doc.stderr1
-rw-r--r--src/tools/clippy/tests/ui/missing_doc_crate_missing.stderr4
-rw-r--r--src/tools/clippy/tests/ui/missing_fields_in_debug.stderr3
-rw-r--r--src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr1
-rw-r--r--src/tools/clippy/tests/ui/needless_if.stderr1
-rw-r--r--src/tools/clippy/tests/ui/never_loop.stderr5
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.stderr3
-rw-r--r--src/tools/clippy/tests/ui/question_mark.stderr3
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.stderr3
-rw-r--r--src/tools/clippy/tests/ui/single_match.stderr5
-rw-r--r--src/tools/clippy/tests/ui/single_match_else.stderr6
-rw-r--r--src/tools/clippy/tests/ui/temporary_assignment.stderr3
-rw-r--r--src/tools/clippy/tests/ui/unit_cmp.stderr4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_wraps.stderr3
-rw-r--r--src/tools/clippy/tests/ui/unwrap_in_result.stderr1
-rw-r--r--src/tools/clippy/tests/ui/vec_init_then_push.stderr3
-rw-r--r--src/tools/clippy/tests/ui/while_let_loop.stderr2
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/helpers.rs5
-rw-r--r--src/tools/miri/src/machine.rs8
-rw-r--r--src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr3
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr1
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr1
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr1
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr1
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr1
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr1
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr1
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr1
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr1
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr1
-rw-r--r--src/tools/rustfmt/src/expr.rs3
-rw-r--r--src/tools/rustfmt/src/items.rs2
-rw-r--r--src/tools/rustfmt/src/modules.rs7
-rw-r--r--src/tools/rustfmt/src/types.rs25
-rw-r--r--src/tools/rustfmt/src/utils.rs1
-rw-r--r--src/tools/rustfmt/src/visitor.rs2
-rw-r--r--src/tools/rustfmt/tests/source/unsafe-binders.rs11
-rw-r--r--src/tools/rustfmt/tests/target/unsafe-binders.rs9
-rw-r--r--tests/codegen/mem-replace-big-type.rs5
-rw-r--r--tests/crashes/123861.rs5
-rw-r--r--tests/crashes/132765.rs12
-rw-r--r--tests/crashes/132766.rs9
-rw-r--r--tests/crashes/132882.rs13
-rw-r--r--tests/crashes/132981.rs7
-rw-r--r--tests/crashes/133063.rs8
-rw-r--r--tests/crashes/133066.rs12
-rw-r--r--tests/crashes/133199.rs11
-rw-r--r--tests/crashes/133275-1.rs13
-rw-r--r--tests/crashes/133275-2.rs15
-rw-r--r--tests/crashes/133426.rs12
-rw-r--r--tests/crashes/133597.rs11
-rw-r--r--tests/crashes/133639.rs33
-rw-r--r--tests/crashes/133808.rs15
-rw-r--r--tests/crashes/133868.rs13
-rw-r--r--tests/crashes/133965.rs9
-rw-r--r--tests/crashes/133966.rs3
-rw-r--r--tests/crashes/134005.rs5
-rw-r--r--tests/crashes/134061.rs4
-rw-r--r--tests/crashes/134217.rs9
-rw-r--r--tests/crashes/auxiliary/aux133199.rs13
-rw-r--r--tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir8
-rw-r--r--tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir8
-rw-r--r--tests/mir-opt/building/index_array_and_slice.index_array.built.after.mir31
-rw-r--r--tests/mir-opt/building/index_array_and_slice.index_const_generic_array.built.after.mir31
-rw-r--r--tests/mir-opt/building/index_array_and_slice.index_custom.built.after.mir34
-rw-r--r--tests/mir-opt/building/index_array_and_slice.index_mut_slice.built.after.mir34
-rw-r--r--tests/mir-opt/building/index_array_and_slice.index_slice.built.after.mir32
-rw-r--r--tests/mir-opt/building/index_array_and_slice.rs71
-rw-r--r--tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff11
-rw-r--r--tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff11
-rw-r--r--tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff11
-rw-r--r--tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff11
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff13
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff13
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff13
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff13
-rw-r--r--tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff11
-rw-r--r--tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff11
-rw-r--r--tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff11
-rw-r--r--tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff11
-rw-r--r--tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff11
-rw-r--r--tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff11
-rw-r--r--tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff11
-rw-r--r--tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff11
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff7
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff7
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff7
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff7
-rw-r--r--tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff12
-rw-r--r--tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff12
-rw-r--r--tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-abort.diff11
-rw-r--r--tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-unwind.diff11
-rw-r--r--tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-abort.diff11
-rw-r--r--tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff11
-rw-r--r--tests/mir-opt/dataflow-const-prop/array_index.rs3
-rw-r--r--tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-abort.diff11
-rw-r--r--tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-unwind.diff11
-rw-r--r--tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-abort.diff11
-rw-r--r--tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff11
-rw-r--r--tests/mir-opt/dataflow-const-prop/large_array_index.rs2
-rw-r--r--tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-abort.diff11
-rw-r--r--tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-unwind.diff11
-rw-r--r--tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-abort.diff11
-rw-r--r--tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff11
-rw-r--r--tests/mir-opt/dataflow-const-prop/repeat.rs3
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff77
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff77
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff77
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff77
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.rs34
-rw-r--r--tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff4
-rw-r--r--tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff4
-rw-r--r--tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-abort.diff72
-rw-r--r--tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-unwind.diff72
-rw-r--r--tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff48
-rw-r--r--tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff48
-rw-r--r--tests/mir-opt/gvn.rs20
-rw-r--r--tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff302
-rw-r--r--tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff302
-rw-r--r--tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff1
-rw-r--r--tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff1
-rw-r--r--tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff77
-rw-r--r--tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff77
-rw-r--r--tests/mir-opt/instsimplify/combine_array_len.rs15
-rw-r--r--tests/mir-opt/issue_72181.foo.built.after.mir9
-rw-r--r--tests/mir-opt/issue_72181.main.built.after.mir9
-rw-r--r--tests/mir-opt/issue_91633.foo.built.after.mir12
-rw-r--r--tests/mir-opt/issue_91633.fun.built.after.mir2
-rw-r--r--tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff20
-rw-r--r--tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff20
-rw-r--r--tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff43
-rw-r--r--tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff43
-rw-r--r--tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-abort.diff2
-rw-r--r--tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff2
-rw-r--r--tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir47
-rw-r--r--tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir47
-rw-r--r--tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff26
-rw-r--r--tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff26
-rw-r--r--tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff26
-rw-r--r--tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff26
-rw-r--r--tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff38
-rw-r--r--tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff38
-rw-r--r--tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff38
-rw-r--r--tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff38
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.rs2
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir30
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir30
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir79
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir79
-rw-r--r--tests/mir-opt/strip_debuginfo.rs39
-rw-r--r--tests/run-make/musl-default-linking/rmake.rs62
-rw-r--r--tests/rustdoc-js-std/osstring-to-string.js2
-rw-r--r--tests/rustdoc-js/reexport.js9
-rw-r--r--tests/rustdoc-js/reexport.rs9
-rw-r--r--tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr2
-rw-r--r--tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr7
-rw-r--r--tests/rustdoc-ui/lints/check-attr.stderr36
-rw-r--r--tests/rustdoc-ui/lints/check.stderr1
-rw-r--r--tests/rustdoc-ui/unescaped_backticks.stderr12
-rw-r--r--tests/ui/alias-uninit-value.rs19
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr6
-rw-r--r--tests/ui/allow-non-lint-warnings.rs8
-rw-r--r--tests/ui/artificial-block.rs5
-rw-r--r--tests/ui/as-precedence.rs10
-rw-r--r--tests/ui/associated-types/associated-types-eq-2.stderr6
-rw-r--r--tests/ui/associated-types/issue-59324.stderr4
-rw-r--r--tests/ui/associated-types/missing-associated-types.stderr4
-rw-r--r--tests/ui/async-await/async-block-control-flow-static-semantics.stderr1
-rw-r--r--tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr1
-rw-r--r--tests/ui/async-await/inference_var_self_argument.stderr4
-rw-r--r--tests/ui/async-await/issue-66312.stderr4
-rw-r--r--tests/ui/async-await/issue-84841.stderr3
-rw-r--r--tests/ui/async-await/issues/issue-72312.stderr5
-rw-r--r--tests/ui/async-await/track-caller/async-closure-gate.afn.stderr3
-rw-r--r--tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr3
-rw-r--r--tests/ui/attributes/collapse-debuginfo-invalid.stderr1
-rw-r--r--tests/ui/attributes/dump_def_parents.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-describe-lvalue.rs1
-rw-r--r--tests/ui/borrowck/borrowck-describe-lvalue.stderr25
-rw-r--r--tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr2
-rw-r--r--tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.rs8
-rw-r--r--tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.stderr9
-rw-r--r--tests/ui/check-cfg/auxiliary/cfg_macro.rs16
-rw-r--r--tests/ui/check-cfg/report-in-external-macros.cargo.stderr42
-rw-r--r--tests/ui/check-cfg/report-in-external-macros.rs11
-rw-r--r--tests/ui/check-cfg/report-in-external-macros.rustc.stderr41
-rw-r--r--tests/ui/check-cfg/report-in-external-macros.stderr14
-rw-r--r--tests/ui/check-cfg/target_feature.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/by_value.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr6
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr6
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-enums.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs6
-rw-r--r--tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr40
-rw-r--r--tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr6
-rw-r--r--tests/ui/closures/2229_closure_analysis/issue-118144.stderr5
-rw-r--r--tests/ui/closures/2229_closure_analysis/issue-87378.stderr6
-rw-r--r--tests/ui/closures/2229_closure_analysis/issue-88476.stderr16
-rw-r--r--tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr15
-rw-r--r--tests/ui/closures/2229_closure_analysis/move_closure.stderr48
-rw-r--r--tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr6
-rw-r--r--tests/ui/closures/2229_closure_analysis/nested-closure.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr6
-rw-r--r--tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr6
-rw-r--r--tests/ui/closures/2229_closure_analysis/repr_packed.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr6
-rw-r--r--tests/ui/closures/2229_closure_analysis/wild_patterns.stderr24
-rw-r--r--tests/ui/codegen/alias-uninit-value.rs26
-rw-r--r--tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg80
-rw-r--r--tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg80
-rw-r--r--tests/ui/coercion/coerce-loop-issue-122561.stderr3
-rw-r--r--tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr5
-rw-r--r--tests/ui/const-generics/issues/issue-67945-2.full.stderr3
-rw-r--r--tests/ui/const-generics/issues/issue-71202.stderr1
-rw-r--r--tests/ui/const-generics/nested-type.min.stderr1
-rw-r--r--tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr1
-rw-r--r--tests/ui/consts/const-eval/infinite_loop.no_ice.stderr1
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr5
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr15
-rw-r--r--tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr20
-rw-r--r--tests/ui/consts/issue-65348.rs4
-rw-r--r--tests/ui/coroutine/drop-tracking-parent-expression.stderr6
-rw-r--r--tests/ui/coroutine/issue-88653.stderr3
-rw-r--r--tests/ui/coroutine/match-bindings.stderr1
-rw-r--r--tests/ui/coroutine/parent-expression.stderr6
-rw-r--r--tests/ui/coroutine/too-live-local-in-immovable-gen.stderr3
-rw-r--r--tests/ui/coroutine/yield-in-initializer.stderr3
-rw-r--r--tests/ui/coverage-attr/name-value.stderr2
-rw-r--r--tests/ui/coverage-attr/word-only.stderr2
-rw-r--r--tests/ui/diagnostic-flags/allow-non-lint-warnings.rs27
-rw-r--r--tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr8
-rw-r--r--tests/ui/diagnostic-width/E0271.ascii.stderr1
-rw-r--r--tests/ui/diagnostic-width/E0271.unicode.stderr1
-rw-r--r--tests/ui/drop/lint-tail-expr-drop-order.stderr48
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds.rs4
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds.stderr4
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds2.rs4
-rw-r--r--tests/ui/dyn-compatibility/assoc_type_bounds2.stderr4
-rw-r--r--tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.rs15
-rw-r--r--tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.stderr12
-rw-r--r--tests/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr3
-rw-r--r--tests/ui/expr/if/if-let-arm-types.stderr3
-rw-r--r--tests/ui/extern/issue-116203.stderr3
-rw-r--r--tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.default.stderr (renamed from tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr)6
-rw-r--r--tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.feature.stderr36
-rw-r--r--tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs3
-rw-r--r--tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.stderr14
-rw-r--r--tests/ui/feature-gates/feature-gate-unsafe-binders.rs7
-rw-r--r--tests/ui/feature-gates/feature-gate-unsafe-binders.stderr13
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr10
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr6
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-derive.stderr2
-rw-r--r--tests/ui/for/for-else-err.stderr3
-rw-r--r--tests/ui/for/for-else-let-else-err.stderr3
-rw-r--r--tests/ui/generic-associated-types/collectivity-regression.stderr5
-rw-r--r--tests/ui/generics/overlapping-errors-span-issue-123861.rs8
-rw-r--r--tests/ui/generics/overlapping-errors-span-issue-123861.stderr52
-rw-r--r--tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.rs (renamed from tests/ui/anonymous-higher-ranked-lifetime.rs)6
-rw-r--r--tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.stderr (renamed from tests/ui/anonymous-higher-ranked-lifetime.stderr)44
-rw-r--r--tests/ui/impl-trait/in-bindings/bad-nesting.rs10
-rw-r--r--tests/ui/impl-trait/in-bindings/bad-nesting.stderr12
-rw-r--r--tests/ui/impl-trait/in-bindings/escaping-bound-var.rs14
-rw-r--r--tests/ui/impl-trait/in-bindings/escaping-bound-var.stderr8
-rw-r--r--tests/ui/impl-trait/in-bindings/lifetime-failure.rs12
-rw-r--r--tests/ui/impl-trait/in-bindings/lifetime-failure.stderr16
-rw-r--r--tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.rs10
-rw-r--r--tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.stderr16
-rw-r--r--tests/ui/impl-trait/in-bindings/nesting.rs7
-rw-r--r--tests/ui/impl-trait/in-bindings/simple.rs10
-rw-r--r--tests/ui/impl-trait/in-bindings/trait-failure.rs13
-rw-r--r--tests/ui/impl-trait/in-bindings/trait-failure.stderr24
-rw-r--r--tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr9
-rw-r--r--tests/ui/impl-trait/issues/issue-54600.stderr3
-rw-r--r--tests/ui/impl-trait/issues/issue-54840.stderr3
-rw-r--r--tests/ui/impl-trait/issues/issue-58504.stderr3
-rw-r--r--tests/ui/impl-trait/issues/issue-58956.stderr3
-rw-r--r--tests/ui/impl-trait/issues/issue-70971.stderr3
-rw-r--r--tests/ui/impl-trait/issues/issue-79099.stderr3
-rw-r--r--tests/ui/impl-trait/issues/issue-84919.stderr3
-rw-r--r--tests/ui/impl-trait/issues/issue-87295.stderr3
-rw-r--r--tests/ui/impl-trait/where-allowed.stderr3
-rw-r--r--tests/ui/issues/issue-18611.stderr3
-rw-r--r--tests/ui/issues/issue-28344.stderr4
-rw-r--r--tests/ui/issues/issue-51714.stderr20
-rw-r--r--tests/ui/issues/issue-56806.stderr4
-rw-r--r--tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.stderr36
-rw-r--r--tests/ui/let-else/let-else-deref-coercion.stderr10
-rw-r--r--tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr9
-rw-r--r--tests/ui/lifetimes/issue-97194.stderr5
-rw-r--r--tests/ui/lint/lints-in-foreign-macros.stderr1
-rw-r--r--tests/ui/lint/non-local-defs/consts.stderr1
-rw-r--r--tests/ui/lint/non-local-defs/weird-exprs.stderr5
-rw-r--r--tests/ui/loops/dont-suggest-break-thru-item.stderr6
-rw-r--r--tests/ui/loops/loop-else-err.stderr3
-rw-r--r--tests/ui/loops/loop-else-let-else-err.stderr3
-rw-r--r--tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr3
-rw-r--r--tests/ui/match/match-incompat-type-semi.stderr3
-rw-r--r--tests/ui/match/match-type-err-first-arm.stderr9
-rw-r--r--tests/ui/never_type/diverging-place-match.stderr3
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr5
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr5
-rw-r--r--tests/ui/nll/snocat-regression.stderr5
-rw-r--r--tests/ui/or-patterns/missing-bindings.stderr1
-rw-r--r--tests/ui/parser/as-precedence.rs18
-rw-r--r--tests/ui/parser/brace-in-let-chain.rs4
-rw-r--r--tests/ui/parser/brace-in-let-chain.stderr30
-rw-r--r--tests/ui/parser/circular_modules_main.stderr19
-rw-r--r--tests/ui/parser/diff-markers/unclosed-delims-in-macro.rs6
-rw-r--r--tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr27
-rw-r--r--tests/ui/parser/diff-markers/unclosed-delims.rs14
-rw-r--r--tests/ui/parser/diff-markers/unclosed-delims.stderr27
-rw-r--r--tests/ui/parser/fn-arg-doc-comment.stderr8
-rw-r--r--tests/ui/privacy/effective_visibilities.stderr1
-rw-r--r--tests/ui/privacy/effective_visibilities_invariants.stderr1
-rw-r--r--tests/ui/privacy/issue-113860-1.stderr1
-rw-r--r--tests/ui/privacy/issue-113860-2.stderr1
-rw-r--r--tests/ui/privacy/issue-113860.stderr1
-rw-r--r--tests/ui/raw-ref-op/amp-raw-without-mut-const-is-a-normal-borrow.rs30
-rw-r--r--tests/ui/raw-ref-op/never-place-isnt-diverging.stderr3
-rw-r--r--tests/ui/reachable/artificial-block.rs30
-rw-r--r--tests/ui/resolve/parse-error-resolve.rs7
-rw-r--r--tests/ui/resolve/parse-error-resolve.stderr22
-rw-r--r--tests/ui/resolve/parse_error.rs5
-rw-r--r--tests/ui/resolve/parse_error.stderr13
-rw-r--r--tests/ui/return/issue-86188-return-not-in-fn-body.stderr6
-rw-r--r--tests/ui/return/return-match-array-const.stderr13
-rw-r--r--tests/ui/return/tail-expr-as-potential-return.stderr9
-rw-r--r--tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr4
-rw-r--r--tests/ui/self/arbitrary-self-opaque.stderr4
-rw-r--r--tests/ui/self/arbitrary_self_types_nonnull.rs13
-rw-r--r--tests/ui/self/arbitrary_self_types_nonnull.stderr23
-rw-r--r--tests/ui/self/arbitrary_self_types_weak.rs13
-rw-r--r--tests/ui/self/arbitrary_self_types_weak.stderr23
-rw-r--r--tests/ui/span/issue-27522.stderr4
-rw-r--r--tests/ui/specialization/min_specialization/issue-79224.stderr5
-rw-r--r--tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr3
-rw-r--r--tests/ui/stability-attribute/stability-attribute-trait-impl.stderr1
-rw-r--r--tests/ui/stable-mir-print/async-closure.rs12
-rw-r--r--tests/ui/stable-mir-print/async-closure.stdout90
-rw-r--r--tests/ui/stable-mir-print/operands.stdout294
-rw-r--r--tests/ui/static/issue-24446.stderr10
-rw-r--r--tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr4
-rw-r--r--tests/ui/suggestions/if-then-neeing-semi.stderr17
-rw-r--r--tests/ui/suggestions/match-prev-arm-needing-semi.stderr14
-rw-r--r--tests/ui/suggestions/suggest-deref-in-match-issue-132784.rs84
-rw-r--r--tests/ui/suggestions/suggest-deref-in-match-issue-132784.stderr259
-rw-r--r--tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr4
-rw-r--r--tests/ui/symbol-names/types.legacy.stderr20
-rw-r--r--tests/ui/symbol-names/types.rs11
-rw-r--r--tests/ui/symbol-names/types.v0.stderr20
-rw-r--r--tests/ui/symbol-names/types.verbose-legacy.stderr20
-rw-r--r--tests/ui/target-feature/allowed-softfloat-target-feature-attribute.rs11
-rw-r--r--tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs9
-rw-r--r--tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.stderr6
-rw-r--r--tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.rs11
-rw-r--r--tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.stderr8
-rw-r--r--tests/ui/target-feature/forbidden-hardfloat-target-feature-cfg.rs14
-rw-r--r--tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs10
-rw-r--r--tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.stderr7
-rw-r--r--tests/ui/target-feature/forbidden-target-feature-attribute.rs1
-rw-r--r--tests/ui/target-feature/forbidden-target-feature-attribute.stderr2
-rw-r--r--tests/ui/target-feature/forbidden-target-feature-cfg.rs1
-rw-r--r--tests/ui/target-feature/forbidden-target-feature-flag-disable.rs1
-rw-r--r--tests/ui/target-feature/forbidden-target-feature-flag.rs1
-rw-r--r--tests/ui/target-feature/gate.rs1
-rw-r--r--tests/ui/target-feature/gate.stderr2
-rw-r--r--tests/ui/traits/const-traits/ice-120503-async-const-method.stderr8
-rw-r--r--tests/ui/traits/issue-78372.stderr4
-rw-r--r--tests/ui/transmutability/alignment/align-fail.stderr1
-rw-r--r--tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr20
-rw-r--r--tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr1
-rw-r--r--tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr1
-rw-r--r--tests/ui/transmutability/references/unit-to-u8.stderr1
-rw-r--r--tests/ui/transmutability/uninhabited.stderr5
-rw-r--r--tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr5
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr3
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr6
-rw-r--r--tests/ui/typeck/issue-100285.stderr1
-rw-r--r--tests/ui/typeck/issue-104513-ice.stderr3
-rw-r--r--tests/ui/typeck/rhs-ty-hint-134162.e2018.stderr11
-rw-r--r--tests/ui/typeck/rhs-ty-hint-134162.e2021.stderr11
-rw-r--r--tests/ui/typeck/rhs-ty-hint-134162.e2024.stderr11
-rw-r--r--tests/ui/typeck/rhs-ty-hint-134162.rs18
-rw-r--r--tests/ui/ufcs/ufcs-explicit-self-bad.stderr12
-rw-r--r--tests/ui/unsafe-binders/expr.rs13
-rw-r--r--tests/ui/unsafe-binders/expr.stderr29
-rw-r--r--tests/ui/unsafe-binders/lifetime-resolution.rs19
-rw-r--r--tests/ui/unsafe-binders/lifetime-resolution.stderr65
-rw-r--r--tests/ui/unsafe-binders/simple.rs7
-rw-r--r--tests/ui/unsafe-binders/simple.stderr17
-rw-r--r--tests/ui/while/while-else-err.stderr3
-rw-r--r--tests/ui/while/while-else-let-else-err.stderr3
669 files changed, 7061 insertions, 4608 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 38b009bfc70..923d4017c0c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3507,7 +3507,6 @@ dependencies = [
  "cc",
  "either",
  "itertools",
- "jobserver",
  "libc",
  "object 0.36.5",
  "pathdiff",
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 650525a2f52..f0099fa8adc 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1382,6 +1382,7 @@ impl Expr {
             | ExprKind::Tup(_)
             | ExprKind::Type(..)
             | ExprKind::Underscore
+            | ExprKind::UnsafeBinderCast(..)
             | ExprKind::While(..)
             | ExprKind::Err(_)
             | ExprKind::Dummy => ExprPrecedence::Unambiguous,
@@ -1509,7 +1510,13 @@ pub enum ExprKind {
     /// `'label: for await? pat in iter { block }`
     ///
     /// This is desugared to a combination of `loop` and `match` expressions.
-    ForLoop { pat: P<Pat>, iter: P<Expr>, body: P<Block>, label: Option<Label>, kind: ForLoopKind },
+    ForLoop {
+        pat: P<Pat>,
+        iter: P<Expr>,
+        body: P<Block>,
+        label: Option<Label>,
+        kind: ForLoopKind,
+    },
     /// Conditionless loop (can be exited with `break`, `continue`, or `return`).
     ///
     /// `'label: loop { block }`
@@ -1614,6 +1621,8 @@ pub enum ExprKind {
     /// A `format_args!()` expression.
     FormatArgs(P<FormatArgs>),
 
+    UnsafeBinderCast(UnsafeBinderCastKind, P<Expr>, Option<P<Ty>>),
+
     /// Placeholder for an expression that wasn't syntactically well formed in some way.
     Err(ErrorGuaranteed),
 
@@ -1652,6 +1661,16 @@ impl GenBlockKind {
     }
 }
 
+/// Whether we're unwrapping or wrapping an unsafe binder
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub enum UnsafeBinderCastKind {
+    // e.g. `&i32` -> `unsafe<'a> &'a i32`
+    Wrap,
+    // e.g. `unsafe<'a> &'a i32` -> `&i32`
+    Unwrap,
+}
+
 /// The explicit `Self` type in a "qualified path". The actual
 /// path, including the trait and the associated item, is stored
 /// separately. `position` represents the index of the associated
@@ -2223,6 +2242,12 @@ pub struct BareFnTy {
     pub decl_span: Span,
 }
 
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub struct UnsafeBinderTy {
+    pub generic_params: ThinVec<GenericParam>,
+    pub inner_ty: P<Ty>,
+}
+
 /// The various kinds of type recognized by the compiler.
 //
 // Adding a new variant? Please update `test_ty` in `tests/ui/macros/stringify.rs`.
@@ -2242,6 +2267,8 @@ pub enum TyKind {
     PinnedRef(Option<Lifetime>, MutTy),
     /// A bare function (e.g., `fn(usize) -> bool`).
     BareFn(P<BareFnTy>),
+    /// An unsafe existential lifetime binder (e.g., `unsafe<'a> &'a ()`).
+    UnsafeBinder(P<UnsafeBinderTy>),
     /// The never type (`!`).
     Never,
     /// A tuple (`(A, B, C, D,...)`).
@@ -2877,7 +2904,7 @@ pub enum ModKind {
     /// or with definition outlined to a separate file `mod foo;` and already loaded from it.
     /// The inner span is from the first token past `{` to the last token until `}`,
     /// or from the first to the last token in the loaded file.
-    Loaded(ThinVec<P<Item>>, Inline, ModSpans),
+    Loaded(ThinVec<P<Item>>, Inline, ModSpans, Result<(), ErrorGuaranteed>),
     /// Module with definition outlined to a separate file `mod foo;` but not yet loaded from it.
     Unloaded,
 }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 2c09059fe19..b44e2d9cace 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -558,6 +558,11 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
             vis.visit_fn_decl(decl);
             vis.visit_span(decl_span);
         }
+        TyKind::UnsafeBinder(binder) => {
+            let UnsafeBinderTy { generic_params, inner_ty } = binder.deref_mut();
+            generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
+            vis.visit_ty(inner_ty);
+        }
         TyKind::Tup(tys) => visit_thin_vec(tys, |ty| vis.visit_ty(ty)),
         TyKind::Paren(ty) => vis.visit_ty(ty),
         TyKind::Pat(ty, pat) => {
@@ -1212,7 +1217,12 @@ impl WalkItemKind for ItemKind {
             ItemKind::Mod(safety, mod_kind) => {
                 visit_safety(vis, safety);
                 match mod_kind {
-                    ModKind::Loaded(items, _inline, ModSpans { inner_span, inject_use_span }) => {
+                    ModKind::Loaded(
+                        items,
+                        _inline,
+                        ModSpans { inner_span, inject_use_span },
+                        _,
+                    ) => {
                         items.flat_map_in_place(|item| vis.flat_map_item(item));
                         vis.visit_span(inner_span);
                         vis.visit_span(inject_use_span);
@@ -1775,6 +1785,12 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
         ExprKind::TryBlock(body) => vis.visit_block(body),
         ExprKind::Lit(_token) => {}
         ExprKind::IncludedBytes(_bytes) => {}
+        ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
+            vis.visit_expr(expr);
+            if let Some(ty) = ty {
+                vis.visit_ty(ty);
+            }
+        }
         ExprKind::Err(_guar) => {}
         ExprKind::Dummy => {}
     }
diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs
index ae1ca36a3ba..64f2a98b8a6 100644
--- a/compiler/rustc_ast/src/util/classify.rs
+++ b/compiler/rustc_ast/src/util/classify.rs
@@ -152,6 +152,7 @@ pub fn leading_labeled_expr(mut expr: &ast::Expr) -> bool {
             | Underscore
             | Yeet(..)
             | Yield(..)
+            | UnsafeBinderCast(..)
             | Err(..)
             | Dummy => return false,
         }
@@ -232,6 +233,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
             | Paren(_)
             | Try(_)
             | Yeet(None)
+            | UnsafeBinderCast(..)
             | Err(_)
             | Dummy => break None,
         }
@@ -253,6 +255,10 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
                 ty = &mut_ty.ty;
             }
 
+            ast::TyKind::UnsafeBinder(binder) => {
+                ty = &binder.inner_ty;
+            }
+
             ast::TyKind::BareFn(fn_ty) => match &fn_ty.decl.output {
                 ast::FnRetTy::Default(_) => break None,
                 ast::FnRetTy::Ty(ret) => ty = ret,
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index a7f7c37693a..22db4438e31 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -380,7 +380,7 @@ impl WalkItemKind for ItemKind {
                 try_visit!(visitor.visit_fn(kind, span, id));
             }
             ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
-                ModKind::Loaded(items, _inline, _inner_span) => {
+                ModKind::Loaded(items, _inline, _inner_span, _) => {
                     walk_list!(visitor, visit_item, items);
                 }
                 ModKind::Unloaded => {}
@@ -522,6 +522,10 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
             walk_list!(visitor, visit_generic_param, generic_params);
             try_visit!(visitor.visit_fn_decl(decl));
         }
+        TyKind::UnsafeBinder(binder) => {
+            walk_list!(visitor, visit_generic_param, &binder.generic_params);
+            try_visit!(visitor.visit_ty(&binder.inner_ty));
+        }
         TyKind::Path(maybe_qself, path) => {
             try_visit!(visitor.visit_qself(maybe_qself));
             try_visit!(visitor.visit_path(path, *id));
@@ -1226,6 +1230,10 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
         ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)),
         ExprKind::Lit(_token) => {}
         ExprKind::IncludedBytes(_bytes) => {}
+        ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
+            try_visit!(visitor.visit_expr(expr));
+            visit_opt!(visitor, visit_ty, ty);
+        }
         ExprKind::Err(_guar) => {}
         ExprKind::Dummy => {}
     }
diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs
index 20d3ce65fac..88ce6f80e10 100644
--- a/compiler/rustc_ast_lowering/src/block.rs
+++ b/compiler/rustc_ast_lowering/src/block.rs
@@ -1,5 +1,6 @@
 use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind};
 use rustc_hir as hir;
+use rustc_span::sym;
 use smallvec::SmallVec;
 
 use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
@@ -82,11 +83,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         (self.arena.alloc_from_iter(stmts), expr)
     }
 
+    /// Return an `ImplTraitContext` that allows impl trait in bindings if
+    /// the feature gate is enabled, or issues a feature error if it is not.
+    fn impl_trait_in_bindings_ctxt(&self, position: ImplTraitPosition) -> ImplTraitContext {
+        if self.tcx.features().impl_trait_in_bindings() {
+            ImplTraitContext::InBinding
+        } else {
+            ImplTraitContext::FeatureGated(position, sym::impl_trait_in_bindings)
+        }
+    }
+
     fn lower_local(&mut self, l: &Local) -> &'hir hir::LetStmt<'hir> {
-        let ty = l
-            .ty
-            .as_ref()
-            .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable)));
+        // Let statements are allowed to have impl trait in bindings.
+        let ty = l.ty.as_ref().map(|t| {
+            self.lower_ty(t, self.impl_trait_in_bindings_ctxt(ImplTraitPosition::Variable))
+        });
         let init = l.kind.init().map(|init| self.lower_expr(init));
         let hir_id = self.lower_node_id(l.id);
         let pat = self.lower_pat(&l.pat);
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 2ad0ff3200e..32905806343 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -379,6 +379,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
                 ExprKind::Err(guar) => hir::ExprKind::Err(*guar),
 
+                ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast(
+                    *kind,
+                    self.lower_expr(expr),
+                    ty.as_ref().map(|ty| {
+                        self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast))
+                    }),
+                ),
+
                 ExprKind::Dummy => {
                     span_bug!(e.span, "lowered ExprKind::Dummy")
                 }
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 7d6c41992eb..d63131eacb5 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -238,7 +238,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 })
             }
             ItemKind::Mod(_, mod_kind) => match mod_kind {
-                ModKind::Loaded(items, _, spans) => {
+                ModKind::Loaded(items, _, spans, _) => {
                     hir::ItemKind::Mod(self.lower_mod(items, spans))
                 }
                 ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index bac3f974cca..e4600b0f636 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -260,6 +260,13 @@ enum ImplTraitContext {
     /// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.
     ///
     OpaqueTy { origin: hir::OpaqueTyOrigin<LocalDefId> },
+
+    /// Treat `impl Trait` as a "trait ascription", which is like a type
+    /// variable but that also enforces that a set of trait goals hold.
+    ///
+    /// This is useful to guide inference for unnameable types.
+    InBinding,
+
     /// `impl Trait` is unstably accepted in this position.
     FeatureGated(ImplTraitPosition, Symbol),
     /// `impl Trait` is not accepted in this position.
@@ -1228,6 +1235,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     param_names: self.lower_fn_params_to_names(&f.decl),
                 }))
             }
+            TyKind::UnsafeBinder(f) => {
+                let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
+                hir::TyKind::UnsafeBinder(self.arena.alloc(hir::UnsafeBinderTy {
+                    generic_params,
+                    inner_ty: self.lower_ty(&f.inner_ty, itctx),
+                }))
+            }
             TyKind::Never => hir::TyKind::Never,
             TyKind::Tup(tys) => hir::TyKind::Tup(
                 self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))),
@@ -1320,6 +1334,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         }
                         path
                     }
+                    ImplTraitContext::InBinding => {
+                        hir::TyKind::TraitAscription(self.lower_param_bounds(bounds, itctx))
+                    }
                     ImplTraitContext::FeatureGated(position, feature) => {
                         let guar = self
                             .tcx
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 64e91c91e2c..290c2e52970 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1029,7 +1029,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" });
                 }
                 // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
-                if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _))
+                if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _))
                     && !attr::contains_name(&item.attrs, sym::path)
                 {
                     self.check_mod_file_item_asciionly(item.ident);
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 61a710517ea..c10b3296497 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -560,6 +560,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     gate_all!(return_type_notation, "return type notation is experimental");
     gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
     gate_all!(unsafe_fields, "`unsafe` fields are experimental");
+    gate_all!(unsafe_binders, "unsafe binder types are experimental");
 
     if !visitor.features.never_patterns() {
         if let Some(spans) = spans.get(&sym::never_patterns) {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 49e4a559e73..04ffa2cffe3 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1198,6 +1198,14 @@ impl<'a> State<'a> {
             ast::TyKind::BareFn(f) => {
                 self.print_ty_fn(f.ext, f.safety, &f.decl, None, &f.generic_params);
             }
+            ast::TyKind::UnsafeBinder(f) => {
+                self.ibox(INDENT_UNIT);
+                self.word("unsafe");
+                self.print_generic_params(&f.generic_params);
+                self.nbsp();
+                self.print_type(&f.inner_ty);
+                self.end();
+            }
             ast::TyKind::Path(None, path) => {
                 self.print_path(path, false, 0);
             }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index c239cb249c3..dce76fb1e77 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -772,6 +772,25 @@ impl<'a> State<'a> {
                 self.word_nbsp("try");
                 self.print_block_with_attrs(blk, attrs)
             }
+            ast::ExprKind::UnsafeBinderCast(kind, expr, ty) => {
+                self.word("builtin # ");
+                match kind {
+                    ast::UnsafeBinderCastKind::Wrap => self.word("wrap_binder"),
+                    ast::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder"),
+                }
+                self.popen();
+                self.ibox(0);
+                self.print_expr(expr, FixupContext::default());
+
+                if let Some(ty) = ty {
+                    self.word(",");
+                    self.space();
+                    self.print_type(ty);
+                }
+
+                self.end();
+                self.pclose();
+            }
             ast::ExprKind::Err(_) => {
                 self.popen();
                 self.word("/*ERROR*/");
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index 16b3d901956..ff838fbbb88 100644
--- a/compiler/rustc_borrowck/src/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -34,6 +34,25 @@ pub struct BorrowSet<'tcx> {
     pub(crate) locals_state_at_exit: LocalsStateAtExit,
 }
 
+// These methods are public to support borrowck consumers.
+impl<'tcx> BorrowSet<'tcx> {
+    pub fn location_map(&self) -> &FxIndexMap<Location, BorrowData<'tcx>> {
+        &self.location_map
+    }
+
+    pub fn activation_map(&self) -> &FxIndexMap<Location, Vec<BorrowIndex>> {
+        &self.activation_map
+    }
+
+    pub fn local_map(&self) -> &FxIndexMap<mir::Local, FxIndexSet<BorrowIndex>> {
+        &self.local_map
+    }
+
+    pub fn locals_state_at_exit(&self) -> &LocalsStateAtExit {
+        &self.locals_state_at_exit
+    }
+}
+
 impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> {
     type Output = BorrowData<'tcx>;
 
@@ -45,7 +64,7 @@ impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> {
 /// Location where a two-phase borrow is activated, if a borrow
 /// is in fact a two-phase borrow.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub(crate) enum TwoPhaseActivation {
+pub enum TwoPhaseActivation {
     NotTwoPhase,
     NotActivated,
     ActivatedAt(Location),
@@ -68,6 +87,33 @@ pub struct BorrowData<'tcx> {
     pub(crate) assigned_place: mir::Place<'tcx>,
 }
 
+// These methods are public to support borrowck consumers.
+impl<'tcx> BorrowData<'tcx> {
+    pub fn reserve_location(&self) -> Location {
+        self.reserve_location
+    }
+
+    pub fn activation_location(&self) -> TwoPhaseActivation {
+        self.activation_location
+    }
+
+    pub fn kind(&self) -> mir::BorrowKind {
+        self.kind
+    }
+
+    pub fn region(&self) -> RegionVid {
+        self.region
+    }
+
+    pub fn borrowed_place(&self) -> mir::Place<'tcx> {
+        self.borrowed_place
+    }
+
+    pub fn assigned_place(&self) -> mir::Place<'tcx> {
+        self.assigned_place
+    }
+}
+
 impl<'tcx> fmt::Display for BorrowData<'tcx> {
     fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result {
         let kind = match self.kind {
@@ -120,7 +166,7 @@ impl LocalsStateAtExit {
 }
 
 impl<'tcx> BorrowSet<'tcx> {
-    pub(crate) fn build(
+    pub fn build(
         tcx: TyCtxt<'tcx>,
         body: &Body<'tcx>,
         locals_are_invalidated_at_exit: bool,
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index 7ace38c3e85..74de766ba23 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -5,15 +5,15 @@ use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::mir::{Body, Promoted};
 use rustc_middle::ty::TyCtxt;
 
+pub use super::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation};
 pub use super::constraints::OutlivesConstraint;
 pub use super::dataflow::{BorrowIndex, Borrows, calculate_borrows_out_of_scope_at_location};
-pub use super::facts::{AllFacts as PoloniusInput, RustcFacts};
+pub use super::facts::{AllFacts as PoloniusInput, PoloniusRegionVid, RustcFacts};
 pub use super::location::{LocationTable, RichLocation};
 pub use super::nll::PoloniusOutput;
 pub use super::place_ext::PlaceExt;
 pub use super::places_conflict::{PlaceConflictBias, places_conflict};
 pub use super::region_infer::RegionInferenceContext;
-use crate::borrow_set::BorrowSet;
 
 /// Options determining the output behavior of [`get_body_with_borrowck_facts`].
 ///
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 452038bc328..dc4eab766c9 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -8,7 +8,10 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::{RegionVid, TyCtxt};
 use rustc_mir_dataflow::fmt::DebugWithContext;
-use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
+use rustc_mir_dataflow::impls::{
+    EverInitializedPlaces, EverInitializedPlacesDomain, MaybeUninitializedPlaces,
+    MaybeUninitializedPlacesDomain,
+};
 use rustc_mir_dataflow::{Analysis, GenKill, JoinSemiLattice, SwitchIntEdgeEffects};
 use tracing::debug;
 
@@ -24,7 +27,7 @@ pub(crate) struct Borrowck<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> {
-    type Domain = BorrowckDomain<'a, 'tcx>;
+    type Domain = BorrowckDomain;
 
     const NAME: &'static str = "borrowck";
 
@@ -41,48 +44,48 @@ impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> {
         unreachable!();
     }
 
-    fn apply_before_statement_effect(
+    fn apply_early_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         stmt: &mir::Statement<'tcx>,
         loc: Location,
     ) {
-        self.borrows.apply_before_statement_effect(&mut state.borrows, stmt, loc);
-        self.uninits.apply_before_statement_effect(&mut state.uninits, stmt, loc);
-        self.ever_inits.apply_before_statement_effect(&mut state.ever_inits, stmt, loc);
+        self.borrows.apply_early_statement_effect(&mut state.borrows, stmt, loc);
+        self.uninits.apply_early_statement_effect(&mut state.uninits, stmt, loc);
+        self.ever_inits.apply_early_statement_effect(&mut state.ever_inits, stmt, loc);
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         stmt: &mir::Statement<'tcx>,
         loc: Location,
     ) {
-        self.borrows.apply_statement_effect(&mut state.borrows, stmt, loc);
-        self.uninits.apply_statement_effect(&mut state.uninits, stmt, loc);
-        self.ever_inits.apply_statement_effect(&mut state.ever_inits, stmt, loc);
+        self.borrows.apply_primary_statement_effect(&mut state.borrows, stmt, loc);
+        self.uninits.apply_primary_statement_effect(&mut state.uninits, stmt, loc);
+        self.ever_inits.apply_primary_statement_effect(&mut state.ever_inits, stmt, loc);
     }
 
-    fn apply_before_terminator_effect(
+    fn apply_early_terminator_effect(
         &mut self,
         state: &mut Self::Domain,
         term: &mir::Terminator<'tcx>,
         loc: Location,
     ) {
-        self.borrows.apply_before_terminator_effect(&mut state.borrows, term, loc);
-        self.uninits.apply_before_terminator_effect(&mut state.uninits, term, loc);
-        self.ever_inits.apply_before_terminator_effect(&mut state.ever_inits, term, loc);
+        self.borrows.apply_early_terminator_effect(&mut state.borrows, term, loc);
+        self.uninits.apply_early_terminator_effect(&mut state.uninits, term, loc);
+        self.ever_inits.apply_early_terminator_effect(&mut state.ever_inits, term, loc);
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
         term: &'mir mir::Terminator<'tcx>,
         loc: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
-        self.borrows.apply_terminator_effect(&mut state.borrows, term, loc);
-        self.uninits.apply_terminator_effect(&mut state.uninits, term, loc);
-        self.ever_inits.apply_terminator_effect(&mut state.ever_inits, term, loc);
+        self.borrows.apply_primary_terminator_effect(&mut state.borrows, term, loc);
+        self.uninits.apply_primary_terminator_effect(&mut state.uninits, term, loc);
+        self.ever_inits.apply_primary_terminator_effect(&mut state.ever_inits, term, loc);
 
         // This return value doesn't matter. It's only used by `iterate_to_fixpoint`, which this
         // analysis doesn't use.
@@ -110,14 +113,14 @@ impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> {
     }
 }
 
-impl JoinSemiLattice for BorrowckDomain<'_, '_> {
+impl JoinSemiLattice for BorrowckDomain {
     fn join(&mut self, _other: &Self) -> bool {
         // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use.
         unreachable!();
     }
 }
 
-impl<'tcx, C> DebugWithContext<C> for BorrowckDomain<'_, 'tcx>
+impl<'tcx, C> DebugWithContext<C> for BorrowckDomain
 where
     C: rustc_mir_dataflow::move_paths::HasMoveData<'tcx>,
 {
@@ -160,10 +163,10 @@ where
 
 /// The transient state of the dataflow analyses used by the borrow checker.
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub(crate) struct BorrowckDomain<'a, 'tcx> {
-    pub(crate) borrows: <Borrows<'a, 'tcx> as Analysis<'tcx>>::Domain,
-    pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
-    pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
+pub(crate) struct BorrowckDomain {
+    pub(crate) borrows: BorrowsDomain,
+    pub(crate) uninits: MaybeUninitializedPlacesDomain,
+    pub(crate) ever_inits: EverInitializedPlacesDomain,
 }
 
 rustc_index::newtype_index! {
@@ -503,7 +506,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
     /// That means they went out of a nonlexical scope
     fn kill_loans_out_of_scope_at_location(
         &self,
-        trans: &mut <Self as Analysis<'tcx>>::Domain,
+        state: &mut <Self as Analysis<'tcx>>::Domain,
         location: Location,
     ) {
         // NOTE: The state associated with a given `location`
@@ -518,14 +521,14 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
         // region, then setting that gen-bit will override any
         // potential kill introduced here.
         if let Some(indices) = self.borrows_out_of_scope_at_location.get(&location) {
-            trans.kill_all(indices.iter().copied());
+            state.kill_all(indices.iter().copied());
         }
     }
 
     /// Kill any borrows that conflict with `place`.
     fn kill_borrows_on_place(
         &self,
-        trans: &mut <Self as Analysis<'tcx>>::Domain,
+        state: &mut <Self as Analysis<'tcx>>::Domain,
         place: Place<'tcx>,
     ) {
         debug!("kill_borrows_on_place: place={:?}", place);
@@ -543,7 +546,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
         // `places_conflict` for every borrow.
         if place.projection.is_empty() {
             if !self.body.local_decls[place.local].is_ref_to_static() {
-                trans.kill_all(other_borrows_of_local);
+                state.kill_all(other_borrows_of_local);
             }
             return;
         }
@@ -562,10 +565,12 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
             )
         });
 
-        trans.kill_all(definitely_conflicting_borrows);
+        state.kill_all(definitely_conflicting_borrows);
     }
 }
 
+type BorrowsDomain = BitSet<BorrowIndex>;
+
 /// Forward dataflow computation of the set of borrows that are in scope at a particular location.
 /// - we gen the introduced loans
 /// - we kill loans on locals going out of (regular) scope
@@ -574,7 +579,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
 /// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of
 ///   `a.b.c` when `a` is overwritten.
 impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
-    type Domain = BitSet<BorrowIndex>;
+    type Domain = BorrowsDomain;
 
     const NAME: &'static str = "borrows";
 
@@ -588,18 +593,18 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
         // function execution, so this method has no effect.
     }
 
-    fn apply_before_statement_effect(
+    fn apply_early_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
-        self.kill_loans_out_of_scope_at_location(trans, location);
+        self.kill_loans_out_of_scope_at_location(state, location);
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         stmt: &mir::Statement<'tcx>,
         location: Location,
     ) {
@@ -617,18 +622,18 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
                         panic!("could not find BorrowIndex for location {location:?}");
                     });
 
-                    trans.gen_(index);
+                    state.gen_(index);
                 }
 
                 // Make sure there are no remaining borrows for variables
                 // that are assigned over.
-                self.kill_borrows_on_place(trans, *lhs);
+                self.kill_borrows_on_place(state, *lhs);
             }
 
             mir::StatementKind::StorageDead(local) => {
                 // Make sure there are no remaining borrows for locals that
                 // are gone out of scope.
-                self.kill_borrows_on_place(trans, Place::from(*local));
+                self.kill_borrows_on_place(state, Place::from(*local));
             }
 
             mir::StatementKind::FakeRead(..)
@@ -646,18 +651,18 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
         }
     }
 
-    fn apply_before_terminator_effect(
+    fn apply_early_terminator_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _terminator: &mir::Terminator<'tcx>,
         location: Location,
     ) {
-        self.kill_loans_out_of_scope_at_location(trans, location);
+        self.kill_loans_out_of_scope_at_location(state, location);
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
         _location: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
@@ -666,7 +671,7 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
                 if let mir::InlineAsmOperand::Out { place: Some(place), .. }
                 | mir::InlineAsmOperand::InOut { out_place: Some(place), .. } = *op
                 {
-                    self.kill_borrows_on_place(trans, place);
+                    self.kill_borrows_on_place(state, place);
                 }
             }
         }
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index c5ebf3c547e..4fb7b22f289 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -1100,12 +1100,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         }
         let decl_span = local_decl.source_info.span;
 
-        let label = match *local_decl.local_info() {
+        let amp_mut_sugg = match *local_decl.local_info() {
             LocalInfo::User(mir::BindingForm::ImplicitSelf(_)) => {
                 let suggestion = suggest_ampmut_self(self.infcx.tcx, decl_span);
                 let additional =
                     local_trait.map(|span| (span, suggest_ampmut_self(self.infcx.tcx, span)));
-                Some((true, decl_span, suggestion, additional))
+                Some(AmpMutSugg { has_sugg: true, span: decl_span, suggestion, additional })
             }
 
             LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
@@ -1150,7 +1150,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                         None
                     }
                     None => {
-                        let (has_sugg, decl_span, sugg) = if name != kw::SelfLower {
+                        if name != kw::SelfLower {
                             suggest_ampmut(
                                 self.infcx.tcx,
                                 local_decl.ty,
@@ -1165,7 +1165,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                                     ..
                                 })) => {
                                     let sugg = suggest_ampmut_self(self.infcx.tcx, decl_span);
-                                    (true, decl_span, sugg)
+                                    Some(AmpMutSugg {
+                                        has_sugg: true,
+                                        span: decl_span,
+                                        suggestion: sugg,
+                                        additional: None,
+                                    })
                                 }
                                 // explicit self (eg `self: &'a Self`)
                                 _ => suggest_ampmut(
@@ -1176,8 +1181,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                                     opt_ty_info,
                                 ),
                             }
-                        };
-                        Some((has_sugg, decl_span, sugg, None))
+                        }
                     }
                 }
             }
@@ -1187,15 +1191,24 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 ..
             })) => {
                 let pattern_span: Span = local_decl.source_info.span;
-                suggest_ref_mut(self.infcx.tcx, pattern_span)
-                    .map(|span| (true, span, "mut ".to_owned(), None))
+                suggest_ref_mut(self.infcx.tcx, pattern_span).map(|span| AmpMutSugg {
+                    has_sugg: true,
+                    span,
+                    suggestion: "mut ".to_owned(),
+                    additional: None,
+                })
             }
 
             _ => unreachable!(),
         };
 
-        match label {
-            Some((true, err_help_span, suggested_code, additional)) => {
+        match amp_mut_sugg {
+            Some(AmpMutSugg {
+                has_sugg: true,
+                span: err_help_span,
+                suggestion: suggested_code,
+                additional,
+            }) => {
                 let mut sugg = vec![(err_help_span, suggested_code)];
                 if let Some(s) = additional {
                     sugg.push(s);
@@ -1217,7 +1230,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                     );
                 }
             }
-            Some((false, err_label_span, message, _)) => {
+            Some(AmpMutSugg {
+                has_sugg: false, span: err_label_span, suggestion: message, ..
+            }) => {
                 let def_id = self.body.source.def_id();
                 let hir_id = if let Some(local_def_id) = def_id.as_local()
                     && let Some(body) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
@@ -1422,6 +1437,13 @@ fn suggest_ampmut_self<'tcx>(tcx: TyCtxt<'tcx>, span: Span) -> String {
     }
 }
 
+struct AmpMutSugg {
+    has_sugg: bool,
+    span: Span,
+    suggestion: String,
+    additional: Option<(Span, String)>,
+}
+
 // When we want to suggest a user change a local variable to be a `&mut`, there
 // are three potential "obvious" things to highlight:
 //
@@ -1443,7 +1465,7 @@ fn suggest_ampmut<'tcx>(
     decl_span: Span,
     opt_assignment_rhs_span: Option<Span>,
     opt_ty_info: Option<Span>,
-) -> (bool, Span, String) {
+) -> Option<AmpMutSugg> {
     // if there is a RHS and it starts with a `&` from it, then check if it is
     // mutable, and if not, put suggest putting `mut ` to make it mutable.
     // we don't have to worry about lifetime annotations here because they are
@@ -1456,6 +1478,11 @@ fn suggest_ampmut<'tcx>(
         && let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span)
         && let Some(stripped) = src.strip_prefix('&')
     {
+        let is_raw_ref = stripped.trim_start().starts_with("raw ");
+        // We don't support raw refs yet
+        if is_raw_ref {
+            return None;
+        }
         let is_mut = if let Some(rest) = stripped.trim_start().strip_prefix("mut") {
             match rest.chars().next() {
                 // e.g. `&mut x`
@@ -1479,7 +1506,12 @@ fn suggest_ampmut<'tcx>(
 
             // FIXME(Ezrashaw): returning is bad because we still might want to
             // update the annotated type, see #106857.
-            return (true, span, "mut ".to_owned());
+            return Some(AmpMutSugg {
+                has_sugg: true,
+                span,
+                suggestion: "mut ".to_owned(),
+                additional: None,
+            });
         }
     }
 
@@ -1504,18 +1536,23 @@ fn suggest_ampmut<'tcx>(
         && let Some(ws_pos) = src.find(char::is_whitespace)
     {
         let span = span.with_lo(span.lo() + BytePos(ws_pos as u32)).shrink_to_lo();
-        (true, span, " mut".to_owned())
+        Some(AmpMutSugg { has_sugg: true, span, suggestion: " mut".to_owned(), additional: None })
     // if there is already a binding, we modify it to be `mut`
     } else if binding_exists {
         // shrink the span to just after the `&` in `&variable`
         let span = span.with_lo(span.lo() + BytePos(1)).shrink_to_lo();
-        (true, span, "mut ".to_owned())
+        Some(AmpMutSugg { has_sugg: true, span, suggestion: "mut ".to_owned(), additional: None })
     } else {
         // otherwise, suggest that the user annotates the binding; we provide the
         // type of the local.
         let ty = decl_ty.builtin_deref(true).unwrap();
 
-        (false, span, format!("{}mut {}", if decl_ty.is_ref() { "&" } else { "*" }, ty))
+        Some(AmpMutSugg {
+            has_sugg: false,
+            span,
+            suggestion: format!("{}mut {}", if decl_ty.is_ref() { "&" } else { "*" }, ty),
+            additional: None,
+        })
     }
 }
 
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index d7db92da18f..18b7984e90d 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -43,7 +43,7 @@ use rustc_mir_dataflow::impls::{
 use rustc_mir_dataflow::move_paths::{
     InitIndex, InitLocation, LookupResult, MoveData, MoveOutIndex, MovePathIndex,
 };
-use rustc_mir_dataflow::{Analysis, EntrySets, Results, ResultsVisitor, visit_results};
+use rustc_mir_dataflow::{Analysis, EntryStates, Results, ResultsVisitor, visit_results};
 use rustc_session::lint::builtin::UNUSED_MUT;
 use rustc_span::{Span, Symbol};
 use smallvec::SmallVec;
@@ -426,14 +426,14 @@ fn get_flow_results<'a, 'tcx>(
         ever_inits: ever_inits.analysis,
     };
 
-    assert_eq!(borrows.entry_sets.len(), uninits.entry_sets.len());
-    assert_eq!(borrows.entry_sets.len(), ever_inits.entry_sets.len());
-    let entry_sets: EntrySets<'_, Borrowck<'_, '_>> =
-        itertools::izip!(borrows.entry_sets, uninits.entry_sets, ever_inits.entry_sets)
+    assert_eq!(borrows.entry_states.len(), uninits.entry_states.len());
+    assert_eq!(borrows.entry_states.len(), ever_inits.entry_states.len());
+    let entry_states: EntryStates<'_, Borrowck<'_, '_>> =
+        itertools::izip!(borrows.entry_states, uninits.entry_states, ever_inits.entry_states)
             .map(|(borrows, uninits, ever_inits)| BorrowckDomain { borrows, uninits, ever_inits })
             .collect();
 
-    Results { analysis, entry_sets }
+    Results { analysis, entry_states }
 }
 
 pub(crate) struct BorrowckInferCtxt<'tcx> {
@@ -600,10 +600,10 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
 // 3. assignments do not affect things loaned out as immutable
 // 4. moves do not affect things loaned out in any way
 impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, '_, 'tcx> {
-    fn visit_statement_before_primary_effect(
+    fn visit_after_early_statement_effect(
         &mut self,
         _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
         stmt: &'a Statement<'tcx>,
         location: Location,
     ) {
@@ -674,10 +674,10 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
         }
     }
 
-    fn visit_terminator_before_primary_effect(
+    fn visit_after_early_terminator_effect(
         &mut self,
         _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
         term: &'a Terminator<'tcx>,
         loc: Location,
     ) {
@@ -787,10 +787,10 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
         }
     }
 
-    fn visit_terminator_after_primary_effect(
+    fn visit_after_primary_terminator_effect(
         &mut self,
         _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
         term: &'a Terminator<'tcx>,
         loc: Location,
     ) {
@@ -983,7 +983,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         place_span: (Place<'tcx>, Span),
         kind: (AccessDepth, ReadOrWrite),
         is_local_mutation_allowed: LocalMutationIsAllowed,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         let (sd, rw) = kind;
 
@@ -1032,7 +1032,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         place_span: (Place<'tcx>, Span),
         sd: AccessDepth,
         rw: ReadOrWrite,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) -> bool {
         let mut error_reported = false;
 
@@ -1172,7 +1172,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         location: Location,
         place_span: (Place<'tcx>, Span),
         kind: AccessDepth,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         // Write of P[i] or *P requires P init'd.
         self.check_if_assigned_path_is_moved(location, place_span, state);
@@ -1190,7 +1190,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         &mut self,
         location: Location,
         (rvalue, span): (&'a Rvalue<'tcx>, Span),
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         match rvalue {
             &Rvalue::Ref(_ /*rgn*/, bk, place) => {
@@ -1448,7 +1448,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         &mut self,
         location: Location,
         (operand, span): (&'a Operand<'tcx>, Span),
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         match *operand {
             Operand::Copy(place) => {
@@ -1568,12 +1568,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         }
     }
 
-    fn check_activations(
-        &mut self,
-        location: Location,
-        span: Span,
-        state: &BorrowckDomain<'a, 'tcx>,
-    ) {
+    fn check_activations(&mut self, location: Location, span: Span, state: &BorrowckDomain) {
         // Two-phase borrow support: For each activation that is newly
         // generated at this statement, check if it interferes with
         // another borrow.
@@ -1731,7 +1726,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         location: Location,
         desired_action: InitializationRequiringAction,
         place_span: (PlaceRef<'tcx>, Span),
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         let maybe_uninits = &state.uninits;
 
@@ -1836,7 +1831,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         location: Location,
         desired_action: InitializationRequiringAction,
         place_span: (PlaceRef<'tcx>, Span),
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         let maybe_uninits = &state.uninits;
 
@@ -1935,7 +1930,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         &mut self,
         location: Location,
         (place, span): (Place<'tcx>, Span),
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
     ) {
         debug!("check_if_assigned_path_is_moved place: {:?}", place);
 
@@ -2001,7 +1996,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
             location: Location,
             base: PlaceRef<'tcx>,
             span: Span,
-            state: &BorrowckDomain<'a, 'tcx>,
+            state: &BorrowckDomain,
         ) {
             // rust-lang/rust#21232: Until Rust allows reads from the
             // initialized parts of partially initialized structs, we
@@ -2092,7 +2087,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         (place, span): (Place<'tcx>, Span),
         kind: ReadOrWrite,
         is_local_mutation_allowed: LocalMutationIsAllowed,
-        state: &BorrowckDomain<'a, 'tcx>,
+        state: &BorrowckDomain,
         location: Location,
     ) -> bool {
         debug!(
@@ -2206,18 +2201,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
         }
     }
 
-    fn is_local_ever_initialized(
-        &self,
-        local: Local,
-        state: &BorrowckDomain<'a, 'tcx>,
-    ) -> Option<InitIndex> {
+    fn is_local_ever_initialized(&self, local: Local, state: &BorrowckDomain) -> Option<InitIndex> {
         let mpi = self.move_data.rev_lookup.find_local(local)?;
         let ii = &self.move_data.init_path_map[mpi];
         ii.into_iter().find(|&&index| state.ever_inits.contains(index)).copied()
     }
 
     /// Adds the place into the used mutable variables set
-    fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, state: &BorrowckDomain<'a, 'tcx>) {
+    fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, state: &BorrowckDomain) {
         match root_place {
             RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
                 // If the local may have been initialized, and it is now currently being
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 585d0eabf5b..3903c45fda5 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -275,7 +275,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         user_ty: ty::UserType<'tcx>,
         span: Span,
     ) {
-        let ty::UserType::Ty(user_ty) = user_ty else { bug!() };
+        let ty::UserTypeKind::Ty(user_ty) = user_ty.kind else { bug!() };
 
         // A fast path for a common case with closure input/output types.
         if let ty::Infer(_) = user_ty.kind() {
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index bbe2b55d8c4..1f2ec168f03 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -110,7 +110,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         ) {
             self.ascribe_user_type_skip_wf(
                 arg_decl.ty,
-                ty::UserType::Ty(user_ty),
+                ty::UserType::new(ty::UserTypeKind::Ty(user_ty)),
                 arg_decl.source_info.span,
             );
         }
@@ -119,7 +119,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let output_decl = &body.local_decls[RETURN_PLACE];
         self.ascribe_user_type_skip_wf(
             output_decl.ty,
-            ty::UserType::Ty(user_provided_sig.output()),
+            ty::UserType::new(ty::UserTypeKind::Ty(user_provided_sig.output())),
             output_decl.source_info.span,
         );
     }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 89e683b8ae3..90d327b0ad2 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -31,7 +31,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{
     self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
     Dynamic, GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserArgs,
-    UserType, UserTypeAnnotationIndex,
+    UserTypeAnnotationIndex,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_mir_dataflow::ResultsCursor;
@@ -370,7 +370,10 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                 } else {
                     self.cx.ascribe_user_type(
                         constant.const_.ty(),
-                        UserType::TypeOf(uv.def, UserArgs { args: uv.args, user_self_ty: None }),
+                        ty::UserType::new(ty::UserTypeKind::TypeOf(uv.def, UserArgs {
+                            args: uv.args,
+                            user_self_ty: None,
+                        })),
                         locations.span(self.cx.body),
                     );
                 }
@@ -991,9 +994,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         for user_annotation in self.user_type_annotations {
             let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
             let annotation = self.instantiate_canonical(span, user_ty);
-            if let ty::UserType::TypeOf(def, args) = annotation
+            if let ty::UserTypeKind::TypeOf(def, args) = annotation.kind
                 && let DefKind::InlineConst = tcx.def_kind(def)
             {
+                assert!(annotation.bounds.is_empty());
                 self.check_inline_const(inferred_ty, def.expect_local(), args, span);
             } else {
                 self.ascribe_user_type(inferred_ty, annotation, span);
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index 70fa4d00c0f..eb07975d8af 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -323,7 +323,8 @@ impl<'cx, 'a> Context<'cx, 'a> {
             | ExprKind::While(_, _, _)
             | ExprKind::Yeet(_)
             | ExprKind::Become(_)
-            | ExprKind::Yield(_) => {}
+            | ExprKind::Yield(_)
+            | ExprKind::UnsafeBinderCast(..) => {}
         }
     }
 
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index b2048c534a4..e7ff65e08f9 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -141,8 +141,10 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
 
         // We don't want to recurse into anything other than mods, since
         // mods or tests inside of functions will break things
-        if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. })) =
-            item.kind
+        if let ast::ItemKind::Mod(
+            _,
+            ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. }, _),
+        ) = item.kind
         {
             let prev_tests = mem::take(&mut self.tests);
             walk_item_kind(
diff --git a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs
index 2093b49ff31..b5a81fc11d5 100644
--- a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs
+++ b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs
@@ -1,8 +1,7 @@
 use std::sync::{Arc, Condvar, Mutex};
 
-use jobserver::HelperThread;
+use rustc_data_structures::jobserver::{self, HelperThread};
 use rustc_errors::DiagCtxtHandle;
-use rustc_session::Session;
 
 // FIXME don't panic when a worker thread panics
 
@@ -14,14 +13,13 @@ pub(super) struct ConcurrencyLimiter {
 }
 
 impl ConcurrencyLimiter {
-    pub(super) fn new(sess: &Session, pending_jobs: usize) -> Self {
+    pub(super) fn new(pending_jobs: usize) -> Self {
         let state = Arc::new(Mutex::new(state::ConcurrencyLimiterState::new(pending_jobs)));
         let available_token_condvar = Arc::new(Condvar::new());
 
         let state_helper = state.clone();
         let available_token_condvar_helper = available_token_condvar.clone();
-        let helper_thread = sess
-            .jobserver
+        let helper_thread = jobserver::client()
             .clone()
             .into_helper_thread(move |token| {
                 let mut state = state_helper.lock().unwrap();
@@ -113,7 +111,7 @@ impl Drop for ConcurrencyLimiterToken {
 }
 
 mod state {
-    use jobserver::Acquired;
+    use rustc_data_structures::jobserver::Acquired;
 
     #[derive(Debug)]
     pub(super) struct ConcurrencyLimiterState {
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 5bbcfc2cda7..4fc30b69123 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -679,7 +679,7 @@ pub(crate) fn run_aot(
             metadata_module: None,
             metadata,
             crate_info: CrateInfo::new(tcx, target_cpu),
-            concurrency_limiter: ConcurrencyLimiter::new(tcx.sess, 0),
+            concurrency_limiter: ConcurrencyLimiter::new(0),
         });
     };
 
@@ -711,7 +711,7 @@ pub(crate) fn run_aot(
             CguReuse::PreLto | CguReuse::PostLto => false,
         });
 
-    let concurrency_limiter = IntoDynSyncSend(ConcurrencyLimiter::new(tcx.sess, todo_cgus.len()));
+    let concurrency_limiter = IntoDynSyncSend(ConcurrencyLimiter::new(todo_cgus.len()));
 
     let modules = tcx.sess.time("codegen mono items", || {
         let mut modules: Vec<_> = par_map(todo_cgus, |(_, cgu)| {
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index d68948966ea..4be4291021d 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -287,12 +287,7 @@ fn dep_symbol_lookup_fn(
 
     let mut dylib_paths = Vec::new();
 
-    let data = &crate_info
-        .dependency_formats
-        .iter()
-        .find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable)
-        .unwrap()
-        .1;
+    let data = &crate_info.dependency_formats[&rustc_session::config::CrateType::Executable].1;
     // `used_crates` is in reverse postorder in terms of dependencies. Reverse the order here to
     // get a postorder which ensures that all dependencies of a dylib are loaded before the dylib
     // itself. This helps the dynamic linker to find dylibs not in the regular dynamic library
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 9f552b3feb9..c38ef82e5b8 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -12,7 +12,6 @@
 #![warn(unused_lifetimes)]
 // tidy-alphabetical-end
 
-extern crate jobserver;
 #[macro_use]
 extern crate rustc_middle;
 extern crate rustc_abi;
@@ -175,7 +174,11 @@ impl CodegenBackend for CraneliftCodegenBackend {
         }
     }
 
-    fn target_features(&self, sess: &Session, _allow_unstable: bool) -> Vec<rustc_span::Symbol> {
+    fn target_features_cfg(
+        &self,
+        sess: &Session,
+        _allow_unstable: bool,
+    ) -> Vec<rustc_span::Symbol> {
         // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
         if sess.target.arch == "x86_64" && sess.target.os != "none" {
             // x86_64 mandates SSE2 support
diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl
index 26ddc5732dd..85fa17a6ba5 100644
--- a/compiler/rustc_codegen_gcc/messages.ftl
+++ b/compiler/rustc_codegen_gcc/messages.ftl
@@ -9,7 +9,7 @@ codegen_gcc_lto_not_supported =
     LTO is not supported. You may get a linker error.
 
 codegen_gcc_forbidden_ctarget_feature =
-    target feature `{$feature}` cannot be toggled with `-Ctarget-feature`
+    target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason}
 
 codegen_gcc_unwinding_inline_asm =
     GCC backend does not support unwinding from inline asm
diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs
index 7a586b5b04c..56849cc8610 100644
--- a/compiler/rustc_codegen_gcc/src/errors.rs
+++ b/compiler/rustc_codegen_gcc/src/errors.rs
@@ -28,6 +28,7 @@ pub(crate) struct UnstableCTargetFeature<'a> {
 #[diag(codegen_gcc_forbidden_ctarget_feature)]
 pub(crate) struct ForbiddenCTargetFeature<'a> {
     pub feature: &'a str,
+    pub reason: &'a str,
 }
 
 #[derive(Subdiagnostic)]
diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs
index 65279c9495a..88e5eefd7a1 100644
--- a/compiler/rustc_codegen_gcc/src/gcc_util.rs
+++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs
@@ -5,7 +5,7 @@ use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::bug;
 use rustc_session::Session;
-use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability};
+use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
 use smallvec::{SmallVec, smallvec};
 
 use crate::errors::{
@@ -94,13 +94,17 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
                         };
                         sess.dcx().emit_warn(unknown_feature);
                     }
-                    Some((_, Stability::Stable, _)) => {}
-                    Some((_, Stability::Unstable(_), _)) => {
-                        // An unstable feature. Warn about using it.
-                        sess.dcx().emit_warn(UnstableCTargetFeature { feature });
-                    }
-                    Some((_, Stability::Forbidden { .. }, _)) => {
-                        sess.dcx().emit_err(ForbiddenCTargetFeature { feature });
+                    Some((_, stability, _)) => {
+                        if let Err(reason) =
+                            stability.compute_toggleability(&sess.target).allow_toggle()
+                        {
+                            sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason });
+                        } else if stability.requires_nightly().is_some() {
+                            // An unstable feature. Warn about using it. (It makes little sense
+                            // to hard-error here since we just warn about fully unknown
+                            // features above).
+                            sess.dcx().emit_warn(UnstableCTargetFeature { feature });
+                        }
                     }
                 }
 
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 452e92bffa2..764e84be1fe 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -260,8 +260,8 @@ impl CodegenBackend for GccCodegenBackend {
             .join(sess)
     }
 
-    fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
-        target_features(sess, allow_unstable, &self.target_info)
+    fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
+        target_features_cfg(sess, allow_unstable, &self.target_info)
     }
 }
 
@@ -472,7 +472,8 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
     }
 }
 
-pub fn target_features(
+/// Returns the features that should be set in `cfg(target_feature)`.
+fn target_features_cfg(
     sess: &Session,
     allow_unstable: bool,
     target_info: &LockedTargetInfo,
@@ -481,9 +482,9 @@ pub fn target_features(
     sess.target
         .rust_target_features()
         .iter()
-        .filter(|(_, gate, _)| gate.is_supported())
+        .filter(|(_, gate, _)| gate.in_cfg())
         .filter_map(|&(feature, gate, _)| {
-            if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
+            if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() {
                 Some(feature)
             } else {
                 None
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index a573a37beb3..4f2af732527 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -75,10 +75,10 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
 
     // Encode all filenames referenced by coverage mappings in this CGU.
     let filenames_buffer = global_file_table.make_filenames_buffer(tcx);
-
-    let filenames_size = filenames_buffer.len();
-    let filenames_val = cx.const_bytes(&filenames_buffer);
-    let filenames_ref = llvm_cov::hash_bytes(&filenames_buffer);
+    // The `llvm-cov` tool uses this hash to associate each covfun record with
+    // its corresponding filenames table, since the final binary will typically
+    // contain multiple covmap records from different compilation units.
+    let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer);
 
     let mut unused_function_names = Vec::new();
 
@@ -101,7 +101,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
     for covfun in &covfun_records {
         unused_function_names.extend(covfun.mangled_function_name_if_unused());
 
-        covfun::generate_covfun_record(cx, filenames_ref, covfun)
+        covfun::generate_covfun_record(cx, filenames_hash, covfun)
     }
 
     // For unused functions, we need to take their mangled names and store them
@@ -126,7 +126,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
     // Generate the coverage map header, which contains the filenames used by
     // this CGU's coverage mappings, and store it in a well-known global.
     // (This is skipped if we returned early due to having no covfun records.)
-    generate_covmap_record(cx, covmap_version, filenames_size, filenames_val);
+    generate_covmap_record(cx, covmap_version, &filenames_buffer);
 }
 
 /// Maps "global" (per-CGU) file ID numbers to their underlying filenames.
@@ -225,38 +225,35 @@ fn span_file_name(tcx: TyCtxt<'_>, span: Span) -> Symbol {
 /// Generates the contents of the covmap record for this CGU, which mostly
 /// consists of a header and a list of filenames. The record is then stored
 /// as a global variable in the `__llvm_covmap` section.
-fn generate_covmap_record<'ll>(
-    cx: &CodegenCx<'ll, '_>,
-    version: u32,
-    filenames_size: usize,
-    filenames_val: &'ll llvm::Value,
-) {
-    debug!("cov map: filenames_size = {}, 0-based version = {}", filenames_size, version);
-
-    // Create the coverage data header (Note, fields 0 and 2 are now always zero,
-    // as of `llvm::coverage::CovMapVersion::Version4`.)
-    let zero_was_n_records_val = cx.const_u32(0);
-    let filenames_size_val = cx.const_u32(filenames_size as u32);
-    let zero_was_coverage_size_val = cx.const_u32(0);
-    let version_val = cx.const_u32(version);
-    let cov_data_header_val = cx.const_struct(
-        &[zero_was_n_records_val, filenames_size_val, zero_was_coverage_size_val, version_val],
-        /*packed=*/ false,
+fn generate_covmap_record<'ll>(cx: &CodegenCx<'ll, '_>, version: u32, filenames_buffer: &[u8]) {
+    // A covmap record consists of four target-endian u32 values, followed by
+    // the encoded filenames table. Two of the header fields are unused in
+    // modern versions of the LLVM coverage mapping format, and are always 0.
+    // <https://llvm.org/docs/CoverageMappingFormat.html#llvm-ir-representation>
+    // See also `src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp`.
+    let covmap_header = cx.const_struct(
+        &[
+            cx.const_u32(0), // (unused)
+            cx.const_u32(filenames_buffer.len() as u32),
+            cx.const_u32(0), // (unused)
+            cx.const_u32(version),
+        ],
+        /* packed */ false,
     );
-
-    // Create the complete LLVM coverage data value to add to the LLVM IR
-    let covmap_data =
-        cx.const_struct(&[cov_data_header_val, filenames_val], /*packed=*/ false);
-
-    let llglobal = llvm::add_global(cx.llmod, cx.val_ty(covmap_data), &llvm_cov::covmap_var_name());
-    llvm::set_initializer(llglobal, covmap_data);
-    llvm::set_global_constant(llglobal, true);
-    llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
-    llvm::set_section(llglobal, &llvm_cov::covmap_section_name(cx.llmod));
+    let covmap_record = cx
+        .const_struct(&[covmap_header, cx.const_bytes(filenames_buffer)], /* packed */ false);
+
+    let covmap_global =
+        llvm::add_global(cx.llmod, cx.val_ty(covmap_record), &llvm_cov::covmap_var_name());
+    llvm::set_initializer(covmap_global, covmap_record);
+    llvm::set_global_constant(covmap_global, true);
+    llvm::set_linkage(covmap_global, llvm::Linkage::PrivateLinkage);
+    llvm::set_section(covmap_global, &llvm_cov::covmap_section_name(cx.llmod));
     // LLVM's coverage mapping format specifies 8-byte alignment for items in this section.
     // <https://llvm.org/docs/CoverageMappingFormat.html>
-    llvm::set_alignment(llglobal, Align::EIGHT);
-    cx.add_used_global(llglobal);
+    llvm::set_alignment(covmap_global, Align::EIGHT);
+
+    cx.add_used_global(covmap_global);
 }
 
 /// Each CGU will normally only emit coverage metadata for the functions that it actually generates.
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
index 530e6827f55..33e7a0f2f20 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
@@ -136,7 +136,7 @@ fn fill_region_tables<'tcx>(
 /// as a global variable in the `__llvm_covfun` section.
 pub(crate) fn generate_covfun_record<'tcx>(
     cx: &CodegenCx<'_, 'tcx>,
-    filenames_ref: u64,
+    filenames_hash: u64,
     covfun: &CovfunRecord<'tcx>,
 ) {
     let &CovfunRecord {
@@ -155,46 +155,45 @@ pub(crate) fn generate_covfun_record<'tcx>(
         regions,
     );
 
-    // Concatenate the encoded coverage mappings
-    let coverage_mapping_size = coverage_mapping_buffer.len();
-    let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer);
-
+    // A covfun record consists of four target-endian integers, followed by the
+    // encoded mapping data in bytes. Note that the length field is 32 bits.
+    // <https://llvm.org/docs/CoverageMappingFormat.html#llvm-ir-representation>
+    // See also `src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp` and
+    // `COVMAP_V3` in `src/llvm-project/llvm/include/llvm/ProfileData/InstrProfData.inc`.
     let func_name_hash = llvm_cov::hash_bytes(mangled_function_name.as_bytes());
-    let func_name_hash_val = cx.const_u64(func_name_hash);
-    let coverage_mapping_size_val = cx.const_u32(coverage_mapping_size as u32);
-    let source_hash_val = cx.const_u64(source_hash);
-    let filenames_ref_val = cx.const_u64(filenames_ref);
-    let func_record_val = cx.const_struct(
+    let covfun_record = cx.const_struct(
         &[
-            func_name_hash_val,
-            coverage_mapping_size_val,
-            source_hash_val,
-            filenames_ref_val,
-            coverage_mapping_val,
+            cx.const_u64(func_name_hash),
+            cx.const_u32(coverage_mapping_buffer.len() as u32),
+            cx.const_u64(source_hash),
+            cx.const_u64(filenames_hash),
+            cx.const_bytes(&coverage_mapping_buffer),
         ],
-        /*packed=*/ true,
+        // This struct needs to be packed, so that the 32-bit length field
+        // doesn't have unexpected padding.
+        true,
     );
 
     // Choose a variable name to hold this function's covfun data.
     // Functions that are used have a suffix ("u") to distinguish them from
     // unused copies of the same function (from different CGUs), so that if a
     // linker sees both it won't discard the used copy's data.
-    let func_record_var_name =
-        CString::new(format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" }))
-            .unwrap();
-    debug!("function record var name: {:?}", func_record_var_name);
-
-    let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name);
-    llvm::set_initializer(llglobal, func_record_val);
-    llvm::set_global_constant(llglobal, true);
-    llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
-    llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
-    llvm::set_section(llglobal, cx.covfun_section_name());
+    let u = if is_used { "u" } else { "" };
+    let covfun_var_name = CString::new(format!("__covrec_{func_name_hash:X}{u}")).unwrap();
+    debug!("function record var name: {covfun_var_name:?}");
+
+    let covfun_global = llvm::add_global(cx.llmod, cx.val_ty(covfun_record), &covfun_var_name);
+    llvm::set_initializer(covfun_global, covfun_record);
+    llvm::set_global_constant(covfun_global, true);
+    llvm::set_linkage(covfun_global, llvm::Linkage::LinkOnceODRLinkage);
+    llvm::set_visibility(covfun_global, llvm::Visibility::Hidden);
+    llvm::set_section(covfun_global, cx.covfun_section_name());
     // LLVM's coverage mapping format specifies 8-byte alignment for items in this section.
     // <https://llvm.org/docs/CoverageMappingFormat.html>
-    llvm::set_alignment(llglobal, Align::EIGHT);
+    llvm::set_alignment(covfun_global, Align::EIGHT);
     if cx.target_spec().supports_comdat() {
-        llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name);
+        llvm::set_comdat(cx.llmod, covfun_global, &covfun_var_name);
     }
-    cx.add_used_global(llglobal);
+
+    cx.add_used_global(covfun_global);
 }
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 5235891a18d..af8562db054 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -27,7 +27,7 @@ use std::mem::ManuallyDrop;
 use back::owned_target_machine::OwnedTargetMachine;
 use back::write::{create_informational_target_machine, create_target_machine};
 use errors::ParseTargetMachineConfig;
-pub use llvm_util::target_features;
+pub use llvm_util::target_features_cfg;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
 use rustc_codegen_ssa::back::write::{
@@ -330,8 +330,8 @@ impl CodegenBackend for LlvmCodegenBackend {
         llvm_util::print_version();
     }
 
-    fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
-        target_features(sess, allow_unstable)
+    fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
+        target_features_cfg(sess, allow_unstable)
     }
 
     fn codegen_crate<'tcx>(
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 07eb89e6041..bfec7d708cf 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -17,7 +17,7 @@ use rustc_session::Session;
 use rustc_session::config::{PrintKind, PrintRequest};
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
-use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES, Stability};
+use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
 
 use crate::back::write::create_informational_target_machine;
 use crate::errors::{
@@ -300,7 +300,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
 /// Must express features in the way Rust understands them.
 ///
 /// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled outside codegen.
-pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
+pub fn target_features_cfg(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
     let mut features: FxHashSet<Symbol> = Default::default();
 
     // Add base features for the target.
@@ -316,7 +316,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
         sess.target
             .rust_target_features()
             .iter()
-            .filter(|(_, gate, _)| gate.is_supported())
+            .filter(|(_, gate, _)| gate.in_cfg())
             .filter(|(feature, _, _)| {
                 // skip checking special features, as LLVM may not understand them
                 if RUSTC_SPECIAL_FEATURES.contains(feature) {
@@ -372,9 +372,9 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
     sess.target
         .rust_target_features()
         .iter()
-        .filter(|(_, gate, _)| gate.is_supported())
+        .filter(|(_, gate, _)| gate.in_cfg())
         .filter_map(|&(feature, gate, _)| {
-            if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
+            if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() {
                 Some(feature)
             } else {
                 None
@@ -493,7 +493,7 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine, out: &mut Str
         .rust_target_features()
         .iter()
         .filter_map(|(feature, gate, _implied)| {
-            if !gate.is_supported() {
+            if !gate.in_cfg() {
                 // Only list (experimentally) supported features.
                 return None;
             }
@@ -716,13 +716,17 @@ pub(crate) fn global_llvm_features(
                             };
                             sess.dcx().emit_warn(unknown_feature);
                         }
-                        Some((_, Stability::Stable, _)) => {}
-                        Some((_, Stability::Unstable(_), _)) => {
-                            // An unstable feature. Warn about using it.
-                            sess.dcx().emit_warn(UnstableCTargetFeature { feature });
-                        }
-                        Some((_, Stability::Forbidden { reason }, _)) => {
-                            sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason });
+                        Some((_, stability, _)) => {
+                            if let Err(reason) =
+                                stability.compute_toggleability(&sess.target).allow_toggle()
+                            {
+                                sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason });
+                            } else if stability.requires_nightly().is_some() {
+                                // An unstable feature. Warn about using it. It makes little sense
+                                // to hard-error here since we just warn about fully unknown
+                                // features above.
+                                sess.dcx().emit_warn(UnstableCTargetFeature { feature });
+                            }
                         }
                     }
 
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index c81e36dfc8d..450a95ae20c 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -11,7 +11,6 @@ bitflags = "2.4.1"
 cc = "1.1.23"
 either = "1.5.0"
 itertools = "0.12"
-jobserver = "0.1.28"
 pathdiff = "0.2.0"
 regex = "1.4"
 rustc_abi = { path = "../rustc_abi" }
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index b030ea3f6df..cfd40a575b1 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -236,7 +236,13 @@ pub fn each_linked_rlib(
 ) -> Result<(), errors::LinkRlibError> {
     let crates = info.used_crates.iter();
 
-    let fmts = if crate_type.is_none() {
+    let fmts = if let Some(crate_type) = crate_type {
+        let Some(fmts) = info.dependency_formats.get(&crate_type) else {
+            return Err(errors::LinkRlibError::MissingFormat);
+        };
+
+        fmts
+    } else {
         for combination in info.dependency_formats.iter().combinations(2) {
             let (ty1, list1) = &combination[0];
             let (ty2, list2) = &combination[1];
@@ -252,18 +258,7 @@ pub fn each_linked_rlib(
         if info.dependency_formats.is_empty() {
             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
+        info.dependency_formats.first().unwrap().1
     };
 
     for &cnum in crates {
@@ -624,8 +619,7 @@ fn link_staticlib(
     let fmts = codegen_results
         .crate_info
         .dependency_formats
-        .iter()
-        .find_map(|&(ty, ref list)| if ty == CrateType::Staticlib { Some(list) } else { None })
+        .get(&CrateType::Staticlib)
         .expect("no dependency formats for staticlib");
 
     let mut all_rust_dylibs = vec![];
@@ -2355,11 +2349,10 @@ fn linker_with_args(
     // they are used within inlined functions or instantiated generic functions. We do this *after*
     // handling the raw-dylib symbols in the current crate to make sure that those are chosen first
     // by the linker.
-    let (_, dependency_linkage) = codegen_results
+    let dependency_linkage = codegen_results
         .crate_info
         .dependency_formats
-        .iter()
-        .find(|(ty, _)| *ty == crate_type)
+        .get(&crate_type)
         .expect("failed to find crate type in dependency format list");
 
     // We sort the libraries below
@@ -2738,11 +2731,10 @@ fn add_upstream_rust_crates(
     // Linking to a rlib involves just passing it to the linker (the linker
     // will slurp up the object files inside), and linking to a dynamic library
     // involves just passing the right -l flag.
-    let (_, data) = codegen_results
+    let data = codegen_results
         .crate_info
         .dependency_formats
-        .iter()
-        .find(|(ty, _)| *ty == crate_type)
+        .get(&crate_type)
         .expect("failed to find crate type in dependency format list");
 
     if sess.target.is_like_aix {
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 4c5eb98e890..301b22f2be4 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -1749,7 +1749,7 @@ fn for_each_exported_symbols_include_dep<'tcx>(
     }
 
     let formats = tcx.dependency_formats(());
-    let deps = formats.iter().find_map(|(t, list)| (*t == crate_type).then_some(list)).unwrap();
+    let deps = &formats[&crate_type];
 
     for (index, dep_format) in deps.iter().enumerate() {
         let cnum = CrateNum::new(index + 1);
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 501f7517919..683defcafee 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -6,9 +6,9 @@ use std::sync::Arc;
 use std::sync::mpsc::{Receiver, Sender, channel};
 use std::{fs, io, mem, str, thread};
 
-use jobserver::{Acquired, Client};
 use rustc_ast::attr;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
+use rustc_data_structures::jobserver::{self, Acquired};
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
 use rustc_errors::emitter::Emitter;
@@ -456,7 +456,6 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
     metadata_module: Option<CompiledModule>,
 ) -> OngoingCodegen<B> {
     let (coordinator_send, coordinator_receive) = channel();
-    let sess = tcx.sess;
 
     let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
     let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins);
@@ -477,7 +476,6 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
         shared_emitter,
         codegen_worker_send,
         coordinator_receive,
-        sess.jobserver.clone(),
         Arc::new(regular_config),
         Arc::new(metadata_config),
         Arc::new(allocator_config),
@@ -1093,7 +1091,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
     shared_emitter: SharedEmitter,
     codegen_worker_send: Sender<CguMessage>,
     coordinator_receive: Receiver<Box<dyn Any + Send>>,
-    jobserver: Client,
     regular_config: Arc<ModuleConfig>,
     metadata_config: Arc<ModuleConfig>,
     allocator_config: Arc<ModuleConfig>,
@@ -1145,7 +1142,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
     // get tokens on `coordinator_receive` which will
     // get managed in the main loop below.
     let coordinator_send2 = coordinator_send.clone();
-    let helper = jobserver
+    let helper = jobserver::client()
         .into_helper_thread(move |token| {
             drop(coordinator_send2.send(Box::new(Message::Token::<B>(token))));
         })
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index eee7cc75400..fa600ec7166 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
 use rustc_span::Span;
 use rustc_span::symbol::{Symbol, sym};
-use rustc_target::target_features::{self, Stability};
+use rustc_target::target_features;
 
 use crate::errors;
 
@@ -20,7 +20,7 @@ use crate::errors;
 pub(crate) fn from_target_feature_attr(
     tcx: TyCtxt<'_>,
     attr: &ast::Attribute,
-    rust_target_features: &UnordMap<String, target_features::Stability>,
+    rust_target_features: &UnordMap<String, target_features::StabilityComputed>,
     target_features: &mut Vec<TargetFeature>,
 ) {
     let Some(list) = attr.meta_item_list() else { return };
@@ -63,32 +63,24 @@ pub(crate) fn from_target_feature_attr(
                 return None;
             };
 
-            // Only allow target features whose feature gates have been enabled.
-            let allowed = match stability {
-                Stability::Forbidden { .. } => false,
-                Stability::Stable => true,
-                Stability::Unstable(name) => rust_features.enabled(*name),
-            };
-            if !allowed {
-                match stability {
-                    Stability::Stable => unreachable!(),
-                    &Stability::Unstable(lang_feature_name) => {
-                        feature_err(
-                            &tcx.sess,
-                            lang_feature_name,
-                            item.span(),
-                            format!("the target feature `{feature}` is currently unstable"),
-                        )
-                        .emit();
-                    }
-                    Stability::Forbidden { reason } => {
-                        tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
-                            span: item.span(),
-                            feature,
-                            reason,
-                        });
-                    }
-                }
+            // Only allow target features whose feature gates have been enabled
+            // and which are permitted to be toggled.
+            if let Err(reason) = stability.allow_toggle() {
+                tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
+                    span: item.span(),
+                    feature,
+                    reason,
+                });
+            } else if let Some(nightly_feature) = stability.requires_nightly()
+                && !rust_features.enabled(nightly_feature)
+            {
+                feature_err(
+                    &tcx.sess,
+                    nightly_feature,
+                    item.span(),
+                    format!("the target feature `{feature}` is currently unstable"),
+                )
+                .emit();
             }
             Some(Symbol::intern(feature))
         }));
@@ -156,18 +148,19 @@ pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
         rust_target_features: |tcx, cnum| {
             assert_eq!(cnum, LOCAL_CRATE);
+            let target = &tcx.sess.target;
             if tcx.sess.opts.actually_rustdoc {
                 // rustdoc needs to be able to document functions that use all the features, so
                 // whitelist them all
                 rustc_target::target_features::all_rust_features()
-                    .map(|(a, b)| (a.to_string(), b))
+                    .map(|(a, b)| (a.to_string(), b.compute_toggleability(target)))
                     .collect()
             } else {
                 tcx.sess
                     .target
                     .rust_target_features()
                     .iter()
-                    .map(|&(a, b, _)| (a.to_string(), b))
+                    .map(|&(a, b, _)| (a.to_string(), b.compute_toggleability(target)))
                     .collect()
             }
         },
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index 5b4a51fc301..4b17db2c49e 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -45,7 +45,9 @@ pub trait CodegenBackend {
 
     fn print(&self, _req: &PrintRequest, _out: &mut String, _sess: &Session) {}
 
-    fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> {
+    /// Returns the features that should be set in `cfg(target_features)`.
+    /// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen.
+    fn target_features_cfg(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> {
         vec![]
     }
 
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index 916929b6c0b..16610ebfca2 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -573,12 +573,27 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
             ) => {}
             Rvalue::ShallowInitBox(_, _) => {}
 
-            Rvalue::UnaryOp(_, operand) => {
+            Rvalue::UnaryOp(op, operand) => {
                 let ty = operand.ty(self.body, self.tcx);
-                if is_int_bool_float_or_char(ty) {
-                    // Int, bool, float, and char operations are fine.
-                } else {
-                    span_bug!(self.span, "non-primitive type in `Rvalue::UnaryOp`: {:?}", ty);
+                match op {
+                    UnOp::Not | UnOp::Neg => {
+                        if is_int_bool_float_or_char(ty) {
+                            // Int, bool, float, and char operations are fine.
+                        } else {
+                            span_bug!(
+                                self.span,
+                                "non-primitive type in `Rvalue::UnaryOp{op:?}`: {ty:?}",
+                            );
+                        }
+                    }
+                    UnOp::PtrMetadata => {
+                        if !ty.is_ref() && !ty.is_unsafe_ptr() {
+                            span_bug!(
+                                self.span,
+                                "non-pointer type in `Rvalue::UnaryOp({op:?})`: {ty:?}",
+                            );
+                        }
+                    }
                 }
             }
 
diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs
index 0f9a460ca1b..763c37a41af 100644
--- a/compiler/rustc_const_eval/src/check_consts/resolver.rs
+++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs
@@ -329,7 +329,7 @@ where
         self.transfer_function(state).initialize_state();
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         statement: &mir::Statement<'tcx>,
@@ -338,7 +338,7 @@ where
         self.transfer_function(state).visit_statement(statement, location);
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index beff0cd99fc..f5396c62433 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -4,27 +4,29 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 
-pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+fn parent_impl_constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
     let parent_id = tcx.local_parent(def_id);
-    matches!(tcx.def_kind(parent_id), DefKind::Impl { .. })
-        && tcx.constness(parent_id) == hir::Constness::Const
+    if matches!(tcx.def_kind(parent_id), DefKind::Impl { .. })
+        && let Some(header) = tcx.impl_trait_header(parent_id)
+    {
+        header.constness
+    } else {
+        hir::Constness::NotConst
+    }
 }
 
-/// Checks whether an item is considered to be `const`. If it is a constructor, anonymous const,
-/// const block, const item or associated const, it is const. If it is a trait impl/function,
+/// Checks whether an item is considered to be `const`. If it is a constructor, it is const.
+/// If it is an assoc method or function,
 /// return if it has a `const` modifier. If it is an intrinsic, report whether said intrinsic
-/// has a `rustc_const_{un,}stable` attribute. Otherwise, return `Constness::NotConst`.
+/// has a `rustc_const_{un,}stable` attribute. Otherwise, panic.
 fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
     let node = tcx.hir_node_by_def_id(def_id);
 
     match node {
-        hir::Node::Ctor(_)
-        | hir::Node::AnonConst(_)
-        | hir::Node::ConstBlock(_)
+        hir::Node::Ctor(hir::VariantData::Tuple(..))
         | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => {
             hir::Constness::Const
         }
-        hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
         hir::Node::ForeignItem(_) => {
             // Foreign items cannot be evaluated at compile-time.
             hir::Constness::NotConst
@@ -38,10 +40,12 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
 
                 // If the function itself is not annotated with `const`, it may still be a `const fn`
                 // if it resides in a const trait impl.
-                let is_const = is_parent_const_impl_raw(tcx, def_id);
-                if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
+                parent_impl_constness(tcx, def_id)
             } else {
-                hir::Constness::NotConst
+                tcx.dcx().span_bug(
+                    tcx.def_span(def_id),
+                    format!("should not be requesting the constness of items that can't be const: {node:#?}: {:?}", tcx.def_kind(def_id))
+                )
             }
         }
     }
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 56325eaa1be..23683851799 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -249,10 +249,9 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
         } else if self.tcx.is_lang_item(def_id, LangItem::PanicFmt) {
             // For panic_fmt, call const_panic_fmt instead.
             let const_def_id = self.tcx.require_lang_item(LangItem::ConstPanicFmt, None);
-            // FIXME(@lcnr): why does this use an empty env if we've got a `param_env` right here.
             let new_instance = ty::Instance::expect_resolve(
                 *self.tcx,
-                ty::TypingEnv::fully_monomorphized(),
+                self.typing_env(),
                 const_def_id,
                 instance.args,
                 self.cur_span(),
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index a180d5da941..9ac2a024ccf 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -540,10 +540,14 @@ pub trait Machine<'tcx>: Sized {
         interp_ok(ReturnAction::Normal)
     }
 
-    /// Called immediately after an "immediate" local variable is read
+    /// Called immediately after an "immediate" local variable is read in a given frame
     /// (i.e., this is called for reads that do not end up accessing addressable memory).
     #[inline(always)]
-    fn after_local_read(_ecx: &InterpCx<'tcx, Self>, _local: mir::Local) -> InterpResult<'tcx> {
+    fn after_local_read(
+        _ecx: &InterpCx<'tcx, Self>,
+        _frame: &Frame<'tcx, Self::Provenance, Self::FrameExtra>,
+        _local: mir::Local,
+    ) -> InterpResult<'tcx> {
         interp_ok(())
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 0157e6c2125..b861ffb6110 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -15,9 +15,9 @@ use rustc_middle::{bug, mir, span_bug, ty};
 use tracing::trace;
 
 use super::{
-    CtfeProvenance, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, OffsetMode,
-    PlaceTy, Pointer, Projectable, Provenance, Scalar, alloc_range, err_ub, from_known_layout,
-    interp_ok, mir_assign_valid_types, throw_ub,
+    CtfeProvenance, Frame, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta,
+    OffsetMode, PlaceTy, Pointer, Projectable, Provenance, Scalar, alloc_range, err_ub,
+    from_known_layout, interp_ok, mir_assign_valid_types, throw_ub,
 };
 
 /// An `Immediate` represents a single immediate self-contained Rust value.
@@ -297,6 +297,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
 
     #[inline]
     pub fn from_bool(b: bool, tcx: TyCtxt<'tcx>) -> Self {
+        // Can use any typing env, since `bool` is always monomorphic.
         let layout = tcx
             .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(tcx.types.bool))
             .unwrap();
@@ -305,17 +306,18 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
 
     #[inline]
     pub fn from_ordering(c: std::cmp::Ordering, tcx: TyCtxt<'tcx>) -> Self {
+        // Can use any typing env, since `Ordering` is always monomorphic.
         let ty = tcx.ty_ordering_enum(None);
         let layout =
             tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)).unwrap();
         Self::from_scalar(Scalar::from_i8(c as i8), layout)
     }
 
-    pub fn from_pair(a: Self, b: Self, tcx: TyCtxt<'tcx>) -> Self {
-        let layout = tcx
+    pub fn from_pair(a: Self, b: Self, cx: &(impl HasTypingEnv<'tcx> + HasTyCtxt<'tcx>)) -> Self {
+        let layout = cx
+            .tcx()
             .layout_of(
-                ty::TypingEnv::fully_monomorphized()
-                    .as_query_input(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])),
+                cx.typing_env().as_query_input(Ty::new_tup(cx.tcx(), &[a.layout.ty, b.layout.ty])),
             )
             .unwrap();
         Self::from_scalar_pair(a.to_scalar(), b.to_scalar(), layout)
@@ -706,23 +708,32 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         interp_ok(str)
     }
 
-    /// Read from a local of the current frame.
+    /// Read from a local of the current frame. Convenience method for [`InterpCx::local_at_frame_to_op`].
+    pub fn local_to_op(
+        &self,
+        local: mir::Local,
+        layout: Option<TyAndLayout<'tcx>>,
+    ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
+        self.local_at_frame_to_op(self.frame(), local, layout)
+    }
+
+    /// Read from a local of a given frame.
     /// Will not access memory, instead an indirect `Operand` is returned.
     ///
-    /// This is public because it is used by [priroda](https://github.com/oli-obk/priroda) to get an
-    /// OpTy from a local.
-    pub fn local_to_op(
+    /// This is public because it is used by [Aquascope](https://github.com/cognitive-engineering-lab/aquascope/)
+    /// to get an OpTy from a local.
+    pub fn local_at_frame_to_op(
         &self,
+        frame: &Frame<'tcx, M::Provenance, M::FrameExtra>,
         local: mir::Local,
         layout: Option<TyAndLayout<'tcx>>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
-        let frame = self.frame();
         let layout = self.layout_of_local(frame, local, layout)?;
         let op = *frame.locals[local].access()?;
         if matches!(op, Operand::Immediate(_)) {
             assert!(!layout.is_unsized());
         }
-        M::after_local_read(self, local)?;
+        M::after_local_read(self, frame, local)?;
         interp_ok(OpTy { op, layout })
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 1fa5dcbd24f..8b7b78c7129 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -222,7 +222,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let res = ImmTy::from_scalar_int(result, left.layout);
                 return interp_ok(if with_overflow {
                     let overflow = ImmTy::from_bool(overflow, *self.tcx);
-                    ImmTy::from_pair(res, overflow, *self.tcx)
+                    ImmTy::from_pair(res, overflow, self)
                 } else {
                     res
                 });
@@ -279,7 +279,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let res = ImmTy::from_scalar_int(result, left.layout);
                 if with_overflow {
                     let overflow = ImmTy::from_bool(overflow, *self.tcx);
-                    ImmTy::from_pair(res, overflow, *self.tcx)
+                    ImmTy::from_pair(res, overflow, self)
                 } else {
                     res
                 }
diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs
index a9ebf386617..6512675530a 100644
--- a/compiler/rustc_const_eval/src/interpret/stack.rs
+++ b/compiler/rustc_const_eval/src/interpret/stack.rs
@@ -584,8 +584,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         interp_ok(())
     }
 
+    /// This is public because it is used by [Aquascope](https://github.com/cognitive-engineering-lab/aquascope/)
+    /// to analyze all the locals in a stack frame.
     #[inline(always)]
-    pub(super) fn layout_of_local(
+    pub fn layout_of_local(
         &self,
         frame: &Frame<'tcx, M::Provenance, M::FrameExtra>,
         local: mir::Local,
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index b61865be667..a26c2eca107 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -9,6 +9,7 @@ use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::{bug, mir, span_bug};
 use rustc_span::source_map::Spanned;
+use rustc_span::{DesugaringKind, Span};
 use rustc_target::callconv::FnAbi;
 use tracing::{info, instrument, trace};
 
@@ -80,7 +81,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         use rustc_middle::mir::StatementKind::*;
 
         match &stmt.kind {
-            Assign(box (place, rvalue)) => self.eval_rvalue_into_place(rvalue, *place)?,
+            Assign(box (place, rvalue)) => {
+                self.eval_rvalue_into_place(rvalue, *place, stmt.source_info.span)?
+            }
 
             SetDiscriminant { place, variant_index } => {
                 let dest = self.eval_place(**place)?;
@@ -159,6 +162,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         &mut self,
         rvalue: &mir::Rvalue<'tcx>,
         place: mir::Place<'tcx>,
+        span: Span,
     ) -> InterpResult<'tcx> {
         let dest = self.eval_place(place)?;
         // FIXME: ensure some kind of non-aliasing between LHS and RHS?
@@ -250,8 +254,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let src = self.eval_place(place)?;
                 let place = self.force_allocation(&src)?;
                 let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
-                if !place_base_raw {
+                if !place_base_raw
+                    && span.desugaring_kind() != Some(DesugaringKind::IndexBoundsCheckReborrow)
+                {
                     // If this was not already raw, it needs retagging.
+                    // As a special hack, we exclude the desugared `PtrMetadata(&raw const *_n)`
+                    // from indexing. (Really we should not do any retag on `&raw` but that does not
+                    // currently work with Stacked Borrows.)
                     val = M::retag_ptr_value(self, mir::RetagKind::Raw, &val)?;
                 }
                 self.write_immediate(*val, &dest)?;
diff --git a/compiler/rustc_data_structures/src/jobserver.rs b/compiler/rustc_data_structures/src/jobserver.rs
index d09f7efc8ff..1204f2d692d 100644
--- a/compiler/rustc_data_structures/src/jobserver.rs
+++ b/compiler/rustc_data_structures/src/jobserver.rs
@@ -1,6 +1,6 @@
 use std::sync::{LazyLock, OnceLock};
 
-pub use jobserver_crate::Client;
+pub use jobserver_crate::{Acquired, Client, HelperThread};
 use jobserver_crate::{FromEnv, FromEnvErrorKind};
 
 // We can only call `from_env_ext` once per process
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 2e01c385a66..b80736f41ad 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -45,7 +45,7 @@ use rustc_errors::registry::Registry;
 use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, FatalError, PResult, markdown};
 use rustc_feature::find_gated_cfg;
 use rustc_interface::util::{self, get_codegen_backend};
-use rustc_interface::{Linker, Queries, interface, passes};
+use rustc_interface::{Linker, interface, passes};
 use rustc_lint::unerased_lint_store;
 use rustc_metadata::creader::MetadataLoader;
 use rustc_metadata::locator;
@@ -158,13 +158,10 @@ pub trait Callbacks {
     /// Called after parsing the crate root. Submodules are not yet parsed when
     /// this callback is called. Return value instructs the compiler whether to
     /// continue the compilation afterwards (defaults to `Compilation::Continue`)
-    #[deprecated = "This callback will likely be removed or stop giving access \
-                    to the TyCtxt in the future. Use either the after_expansion \
-                    or the after_analysis callback instead."]
-    fn after_crate_root_parsing<'tcx>(
+    fn after_crate_root_parsing(
         &mut self,
         _compiler: &interface::Compiler,
-        _queries: &'tcx Queries<'tcx>,
+        _queries: &ast::Crate,
     ) -> Compilation {
         Compilation::Continue
     }
@@ -173,7 +170,7 @@ pub trait Callbacks {
     fn after_expansion<'tcx>(
         &mut self,
         _compiler: &interface::Compiler,
-        _queries: &'tcx Queries<'tcx>,
+        _tcx: TyCtxt<'tcx>,
     ) -> Compilation {
         Compilation::Continue
     }
@@ -350,6 +347,8 @@ fn run_compiler(
 
     callbacks.config(&mut config);
 
+    let registered_lints = config.register_lints.is_some();
+
     interface::run_compiler(config, |compiler| {
         let sess = &compiler.sess;
         let codegen_backend = &*compiler.codegen_backend;
@@ -365,7 +364,7 @@ fn run_compiler(
         // `--help`/`-Zhelp`/`-Chelp`. This is the earliest it can run, because
         // it must happen after lints are registered, during session creation.
         if sess.opts.describe_lints {
-            describe_lints(sess);
+            describe_lints(sess, registered_lints);
             return early_exit();
         }
 
@@ -416,8 +415,9 @@ fn run_compiler(
                 return early_exit();
             }
 
-            #[allow(deprecated)]
-            if callbacks.after_crate_root_parsing(compiler, queries) == Compilation::Stop {
+            if callbacks.after_crate_root_parsing(compiler, &*queries.parse().borrow())
+                == Compilation::Stop
+            {
                 return early_exit();
             }
 
@@ -425,18 +425,18 @@ fn run_compiler(
                 return early_exit();
             }
 
-            // Make sure name resolution and macro expansion is run.
-            queries.global_ctxt().enter(|tcx| tcx.resolver_for_lowering());
+            queries.global_ctxt().enter(|tcx| {
+                // Make sure name resolution and macro expansion is run.
+                let _ = tcx.resolver_for_lowering();
 
-            if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir {
-                queries.global_ctxt().enter(|tcxt| dump_feature_usage_metrics(tcxt, metrics_dir));
-            }
+                if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir {
+                    dump_feature_usage_metrics(tcx, metrics_dir);
+                }
 
-            if callbacks.after_expansion(compiler, queries) == Compilation::Stop {
-                return early_exit();
-            }
+                if callbacks.after_expansion(compiler, tcx) == Compilation::Stop {
+                    return early_exit();
+                }
 
-            queries.global_ctxt().enter(|tcx| {
                 passes::write_dep_info(tcx);
 
                 if sess.opts.output_types.contains_key(&OutputType::DepInfo)
@@ -982,7 +982,7 @@ the command line flag directly.
 }
 
 /// Write to stdout lint command options, together with a list of all available lints
-pub fn describe_lints(sess: &Session) {
+pub fn describe_lints(sess: &Session, registered_lints: bool) {
     safe_println!(
         "
 Available lint options:
@@ -1086,7 +1086,7 @@ Available lint options:
 
     print_lint_groups(builtin_groups, true);
 
-    match (sess.registered_lints, loaded.len(), loaded_groups.len()) {
+    match (registered_lints, loaded.len(), loaded_groups.len()) {
         (false, 0, _) | (false, _, 0) => {
             safe_println!("Lint tools like Clippy can load additional lints and lint groups.");
         }
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 1b6c6edcc61..ac2f91cdeb3 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -3048,11 +3048,19 @@ impl FileWithAnnotatedLines {
                 // working correctly.
                 let middle = min(ann.line_start + 4, ann.line_end);
                 // We'll show up to 4 lines past the beginning of the multispan start.
-                // We will *not* include the tail of lines that are only whitespace.
+                // We will *not* include the tail of lines that are only whitespace, a comment or
+                // a bare delimiter.
+                let filter = |s: &str| {
+                    let s = s.trim();
+                    // Consider comments as empty, but don't consider docstrings to be empty.
+                    !(s.starts_with("//") && !(s.starts_with("///") || s.starts_with("//!")))
+                        // Consider lines with nothing but whitespace, a single delimiter as empty.
+                        && !["", "{", "}", "(", ")", "[", "]"].contains(&s)
+                };
                 let until = (ann.line_start..middle)
                     .rev()
                     .filter_map(|line| file.get_line(line - 1).map(|s| (line + 1, s)))
-                    .find(|(_, s)| !s.trim().is_empty())
+                    .find(|(_, s)| filter(s))
                     .map(|(line, _)| line)
                     .unwrap_or(ann.line_start);
                 for line in ann.line_start + 1..until {
@@ -3060,7 +3068,8 @@ impl FileWithAnnotatedLines {
                     add_annotation_to_file(&mut output, Lrc::clone(&file), line, ann.as_line());
                 }
                 let line_end = ann.line_end - 1;
-                if middle < line_end {
+                let end_is_empty = file.get_line(line_end - 1).map_or(false, |s| !filter(&s));
+                if middle < line_end && !end_is_empty {
                     add_annotation_to_file(&mut output, Lrc::clone(&file), line_end, ann.as_line());
                 }
             } else {
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 6a6496f9827..690e080fbfc 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -723,7 +723,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                                     item_inner.kind,
                                     ItemKind::Mod(
                                         _,
-                                        ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _),
+                                        ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _, _),
                                     )
                                 ) =>
                         {
@@ -889,7 +889,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             fn visit_item(&mut self, item: &'ast ast::Item) {
                 match &item.kind {
                     ItemKind::Mod(_, mod_kind)
-                        if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) =>
+                        if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) =>
                     {
                         feature_err(
                             self.sess,
@@ -1195,7 +1195,7 @@ impl InvocationCollectorNode for P<ast::Item> {
 
         let ecx = &mut collector.cx;
         let (file_path, dir_path, dir_ownership) = match mod_kind {
-            ModKind::Loaded(_, inline, _) => {
+            ModKind::Loaded(_, inline, _, _) => {
                 // Inline `mod foo { ... }`, but we still need to push directories.
                 let (dir_path, dir_ownership) = mod_dir_path(
                     ecx.sess,
@@ -1217,15 +1217,21 @@ impl InvocationCollectorNode for P<ast::Item> {
             ModKind::Unloaded => {
                 // We have an outline `mod foo;` so we need to parse the file.
                 let old_attrs_len = attrs.len();
-                let ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership } =
-                    parse_external_mod(
-                        ecx.sess,
-                        ident,
-                        span,
-                        &ecx.current_expansion.module,
-                        ecx.current_expansion.dir_ownership,
-                        &mut attrs,
-                    );
+                let ParsedExternalMod {
+                    items,
+                    spans,
+                    file_path,
+                    dir_path,
+                    dir_ownership,
+                    had_parse_error,
+                } = parse_external_mod(
+                    ecx.sess,
+                    ident,
+                    span,
+                    &ecx.current_expansion.module,
+                    ecx.current_expansion.dir_ownership,
+                    &mut attrs,
+                );
 
                 if let Some(lint_store) = ecx.lint_store {
                     lint_store.pre_expansion_lint(
@@ -1239,7 +1245,7 @@ impl InvocationCollectorNode for P<ast::Item> {
                     );
                 }
 
-                *mod_kind = ModKind::Loaded(items, Inline::No, spans);
+                *mod_kind = ModKind::Loaded(items, Inline::No, spans, had_parse_error);
                 node.attrs = attrs;
                 if node.attrs.len() > old_attrs_len {
                     // If we loaded an out-of-line module and added some inner attributes,
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index 614f52bbd28..85ea42e78ad 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -37,6 +37,7 @@ pub(crate) struct ParsedExternalMod {
     pub file_path: PathBuf,
     pub dir_path: PathBuf,
     pub dir_ownership: DirOwnership,
+    pub had_parse_error: Result<(), ErrorGuaranteed>,
 }
 
 pub enum ModError<'a> {
@@ -74,14 +75,17 @@ pub(crate) fn parse_external_mod(
         attrs.extend(inner_attrs);
         (items, inner_span, mp.file_path)
     };
+
     // (1) ...instead, we return a dummy module.
-    let (items, spans, file_path) =
-        result.map_err(|err| err.report(sess, span)).unwrap_or_default();
+    let ((items, spans, file_path), had_parse_error) = match result {
+        Err(err) => (Default::default(), Err(err.report(sess, span))),
+        Ok(result) => (result, Ok(())),
+    };
 
     // Extract the directory path for submodules of the module.
     let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
 
-    ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership }
+    ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership, had_parse_error }
 }
 
 pub(crate) fn mod_dir_path(
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 8b4f441dafe..e25840ba5fc 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -126,9 +126,6 @@ declare_features! (
             better implied higher-ranked implied bounds support"
         )
     ),
-    /// Allows `impl Trait` in bindings (`let`, `const`, `static`).
-    (removed, impl_trait_in_bindings, "1.55.0", Some(63065),
-     Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")),
     (removed, import_shadowing, "1.0.0", None, None),
     /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`).
     (removed, in_band_lifetimes, "1.23.0", Some(44524),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 3c9115be7f5..45c63b03fe9 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -342,6 +342,7 @@ declare_features! (
     (unstable, sse4a_target_feature, "1.27.0", Some(44839)),
     (unstable, tbm_target_feature, "1.27.0", Some(44839)),
     (unstable, wasm_target_feature, "1.30.0", Some(44839)),
+    (unstable, x87_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)),
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
     // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
@@ -516,6 +517,8 @@ declare_features! (
     (unstable, if_let_guard, "1.47.0", Some(51114)),
     /// Allows `impl Trait` to be used inside associated types (RFC 2515).
     (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)),
+    /// Allows `impl Trait` in bindings (`let`).
+    (unstable, impl_trait_in_bindings, "1.64.0", Some(63065)),
     /// Allows `impl Trait` as output type in `Fn` traits in return position of functions.
     (unstable, impl_trait_in_fn_trait_return, "1.64.0", Some(99697)),
     /// Allows associated types in inherent impls.
@@ -635,6 +638,8 @@ declare_features! (
     /// Allows creation of instances of a struct by moving fields that have
     /// not changed from prior instances of the same struct (RFC #2528)
     (unstable, type_changing_struct_update, "1.58.0", Some(86555)),
+    /// Allows using `unsafe<'a> &'a T` unsafe binder types.
+    (incomplete, unsafe_binders, "CURRENT_RUSTC_VERSION", Some(130516)),
     /// Allows declaring fields `unsafe`.
     (incomplete, unsafe_fields, "CURRENT_RUSTC_VERSION", Some(132922)),
     /// Allows const generic parameters to be defined with types that
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 4800a479ff4..2e795d84559 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -8,7 +8,7 @@ use rustc_ast::{
 };
 pub use rustc_ast::{
     BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, ByRef, CaptureBy,
-    ImplPolarity, IsAuto, Movability, Mutability, UnOp,
+    ImplPolarity, IsAuto, Movability, Mutability, UnOp, UnsafeBinderCastKind,
 };
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::sorted_map::SortedMap;
@@ -1740,6 +1740,7 @@ impl Expr<'_> {
             | ExprKind::Struct(..)
             | ExprKind::Tup(_)
             | ExprKind::Type(..)
+            | ExprKind::UnsafeBinderCast(..)
             | ExprKind::Err(_) => ExprPrecedence::Unambiguous,
 
             ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
@@ -1769,6 +1770,9 @@ impl Expr<'_> {
             // https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md#type-ascription-and-temporaries
             ExprKind::Type(ref e, _) => e.is_place_expr(allow_projections_from),
 
+            // Unsafe binder cast preserves place-ness of the sub-expression.
+            ExprKind::UnsafeBinderCast(_, e, _) => e.is_place_expr(allow_projections_from),
+
             ExprKind::Unary(UnOp::Deref, _) => true,
 
             ExprKind::Field(ref base, _) | ExprKind::Index(ref base, _, _) => {
@@ -1850,7 +1854,8 @@ impl Expr<'_> {
             | ExprKind::Field(base, _)
             | ExprKind::Index(base, _, _)
             | ExprKind::AddrOf(.., base)
-            | ExprKind::Cast(base, _) => {
+            | ExprKind::Cast(base, _)
+            | ExprKind::UnsafeBinderCast(_, base, _) => {
                 // This isn't exactly true for `Index` and all `Unary`, but we are using this
                 // method exclusively for diagnostics and there's a *cultural* pressure against
                 // them being used only for its side-effects.
@@ -2020,6 +2025,22 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
     }
 }
 
+/// Checks if the specified expression needs parentheses for prefix
+/// or postfix suggestions to be valid.
+/// For example, `a + b` requires parentheses to suggest `&(a + b)`,
+/// but just `a` does not.
+/// Similarly, `(a + b).c()` also requires parentheses.
+/// This should not be used for other types of suggestions.
+pub fn expr_needs_parens(expr: &Expr<'_>) -> bool {
+    match expr.kind {
+        // parenthesize if needed (Issue #46756)
+        ExprKind::Cast(_, _) | ExprKind::Binary(_, _, _) => true,
+        // parenthesize borrows of range literals (Issue #54505)
+        _ if is_range_literal(expr) => true,
+        _ => false,
+    }
+}
+
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum ExprKind<'hir> {
     /// Allow anonymous constants from an inline `const` block
@@ -2144,6 +2165,10 @@ pub enum ExprKind<'hir> {
     /// A suspension point for coroutines (i.e., `yield <expr>`).
     Yield(&'hir Expr<'hir>, YieldSource),
 
+    /// Operators which can be used to interconvert `unsafe` binder types.
+    /// e.g. `unsafe<'a> &'a i32` <=> `&i32`.
+    UnsafeBinderCast(UnsafeBinderCastKind, &'hir Expr<'hir>, Option<&'hir Ty<'hir>>),
+
     /// A placeholder for an expression that wasn't syntactically well formed in some way.
     Err(rustc_span::ErrorGuaranteed),
 }
@@ -2781,6 +2806,12 @@ pub struct BareFnTy<'hir> {
 }
 
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
+pub struct UnsafeBinderTy<'hir> {
+    pub generic_params: &'hir [GenericParam<'hir>],
+    pub inner_ty: &'hir Ty<'hir>,
+}
+
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct OpaqueTy<'hir> {
     pub hir_id: HirId,
     pub def_id: LocalDefId,
@@ -2878,6 +2909,8 @@ pub enum TyKind<'hir> {
     Ref(&'hir Lifetime, MutTy<'hir>),
     /// A bare function (e.g., `fn(usize) -> bool`).
     BareFn(&'hir BareFnTy<'hir>),
+    /// An unsafe binder type (e.g. `unsafe<'a> Foo<'a>`).
+    UnsafeBinder(&'hir UnsafeBinderTy<'hir>),
     /// The never type (`!`).
     Never,
     /// A tuple (`(A, B, C, D, ...)`).
@@ -2889,6 +2922,8 @@ pub enum TyKind<'hir> {
     Path(QPath<'hir>),
     /// An opaque type definition itself. This is only used for `impl Trait`.
     OpaqueDef(&'hir OpaqueTy<'hir>),
+    /// A trait ascription type, which is `impl Trait` within a local binding.
+    TraitAscription(GenericBounds<'hir>),
     /// A trait object type `Bound1 + Bound2 + Bound3`
     /// where `Bound` is a trait or a lifetime.
     TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax),
@@ -4042,9 +4077,7 @@ impl<'hir> Node<'hir> {
                 _ => None,
             },
             Node::TraitItem(ti) => match ti.kind {
-                TraitItemKind::Fn(ref sig, TraitFn::Provided(_)) => {
-                    Some(FnKind::Method(ti.ident, sig))
-                }
+                TraitItemKind::Fn(ref sig, _) => Some(FnKind::Method(ti.ident, sig)),
                 _ => None,
             },
             Node::ImplItem(ii) => match ii.kind {
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 8dbfefffee4..6d481f7536a 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -857,6 +857,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
         ExprKind::Yield(ref subexpression, _) => {
             try_visit!(visitor.visit_expr(subexpression));
         }
+        ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
+            try_visit!(visitor.visit_expr(expr));
+            visit_opt!(visitor, visit_ty, ty);
+        }
         ExprKind::Lit(_) | ExprKind::Err(_) => {}
     }
     V::Result::output()
@@ -886,12 +890,19 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
             walk_list!(visitor, visit_generic_param, function_declaration.generic_params);
             try_visit!(visitor.visit_fn_decl(function_declaration.decl));
         }
+        TyKind::UnsafeBinder(ref unsafe_binder) => {
+            walk_list!(visitor, visit_generic_param, unsafe_binder.generic_params);
+            try_visit!(visitor.visit_ty(unsafe_binder.inner_ty));
+        }
         TyKind::Path(ref qpath) => {
             try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span));
         }
         TyKind::OpaqueDef(opaque) => {
             try_visit!(visitor.visit_opaque_ty(opaque));
         }
+        TyKind::TraitAscription(bounds) => {
+            walk_list!(visitor, visit_param_bound, bounds);
+        }
         TyKind::Array(ref ty, ref length) => {
             try_visit!(visitor.visit_ty(ty));
             try_visit!(visitor.visit_const_arg(length));
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 25feb95d5df..0c3ed9b5c60 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -246,6 +246,18 @@ hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty
 hir_analysis_invalid_receiver_ty_help =
     consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
+hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types =
+    consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+hir_analysis_invalid_receiver_ty_help_nonnull_note =
+    `NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver`
+
+hir_analysis_invalid_receiver_ty_help_weak_note =
+    `Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver`
+
+hir_analysis_invalid_receiver_ty_no_arbitrary_self_types = invalid `self` parameter type: `{$receiver_ty}`
+    .note = type of `self` must be `Self` or a type that dereferences to it
+
 hir_analysis_invalid_union_field =
     field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
     .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 57264d0bd2a..95ad8225f61 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -44,6 +44,7 @@ use {rustc_ast as ast, rustc_hir as hir};
 use crate::autoderef::Autoderef;
 use crate::collect::CollectItemTypesVisitor;
 use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params};
+use crate::errors::InvalidReceiverTyHint;
 use crate::{errors, fluent_generated as fluent};
 
 pub(super) struct WfCheckingCtxt<'a, 'tcx> {
@@ -1748,8 +1749,25 @@ fn check_method_receiver<'tcx>(
             // Report error; would not have worked with `arbitrary_self_types[_pointers]`.
             {
                 match receiver_validity_err {
+                    ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => {
+                        let hint = match receiver_ty
+                            .builtin_deref(false)
+                            .unwrap_or(receiver_ty)
+                            .ty_adt_def()
+                            .and_then(|adt_def| tcx.get_diagnostic_name(adt_def.did()))
+                        {
+                            Some(sym::RcWeak | sym::ArcWeak) => Some(InvalidReceiverTyHint::Weak),
+                            Some(sym::NonNull) => Some(InvalidReceiverTyHint::NonNull),
+                            _ => None,
+                        };
+
+                        tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty, hint })
+                    }
                     ReceiverValidityError::DoesNotDeref => {
-                        tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
+                        tcx.dcx().emit_err(errors::InvalidReceiverTyNoArbitrarySelfTypes {
+                            span,
+                            receiver_ty,
+                        })
                     }
                     ReceiverValidityError::MethodGenericParamUsed => {
                         tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty })
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 96d2714252a..8c9da78a659 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -29,7 +29,7 @@ use rustc_errors::{
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor, walk_generics};
-use rustc_hir::{self as hir, GenericParamKind, Node};
+use rustc_hir::{self as hir, GenericParamKind, HirId, Node};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::hir::nested_filter;
@@ -201,12 +201,13 @@ pub(crate) fn placeholder_type_error_diag<'cx, 'tcx>(
         placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
 
     if let Some(generics) = generics {
-        if let Some(arg) = params.iter().find(|arg| {
-            matches!(arg.name, hir::ParamName::Plain(Ident { name: kw::Underscore, .. }))
+        if let Some(span) = params.iter().find_map(|arg| match arg.name {
+            hir::ParamName::Plain(Ident { name: kw::Underscore, span }) => Some(span),
+            _ => None,
         }) {
             // Account for `_` already present in cases like `struct S<_>(_);` and suggest
             // `struct S<T>(T);` instead of `struct S<_, T>(T);`.
-            sugg.push((arg.span, (*type_name).to_string()));
+            sugg.push((span, (*type_name).to_string()));
         } else if let Some(span) = generics.span_for_param_suggestion() {
             // Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`.
             sugg.push((span, format!(", {type_name}")));
@@ -436,6 +437,15 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
         ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant")
     }
 
+    fn register_trait_ascription_bounds(
+        &self,
+        _: Vec<(ty::Clause<'tcx>, Span)>,
+        _: HirId,
+        span: Span,
+    ) {
+        self.dcx().span_delayed_bug(span, "trait ascription type not allowed here");
+    }
+
     fn probe_ty_param_bounds(
         &self,
         span: Span,
@@ -1330,7 +1340,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
             ..
         })
         | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => {
-            infer_return_ty_for_fn_sig(sig, generics, def_id, &icx)
+            lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
         }
 
         ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
@@ -1347,7 +1357,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
                     None,
                 )
             } else {
-                infer_return_ty_for_fn_sig(sig, generics, def_id, &icx)
+                lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
             }
         }
 
@@ -1397,99 +1407,108 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
     ty::EarlyBinder::bind(output)
 }
 
-fn infer_return_ty_for_fn_sig<'tcx>(
-    sig: &hir::FnSig<'tcx>,
-    generics: &hir::Generics<'_>,
+fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
+    icx: &ItemCtxt<'tcx>,
+    sig: &'tcx hir::FnSig<'tcx>,
+    generics: &'tcx hir::Generics<'tcx>,
     def_id: LocalDefId,
+) -> ty::PolyFnSig<'tcx> {
+    if let Some(infer_ret_ty) = sig.decl.output.get_infer_ret_ty() {
+        return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
+    }
+
+    icx.lowerer().lower_fn_ty(
+        icx.tcx().local_def_id_to_hir_id(def_id),
+        sig.header.safety,
+        sig.header.abi,
+        sig.decl,
+        Some(generics),
+        None,
+    )
+}
+
+fn recover_infer_ret_ty<'tcx>(
     icx: &ItemCtxt<'tcx>,
+    infer_ret_ty: &'tcx hir::Ty<'tcx>,
+    generics: &'tcx hir::Generics<'tcx>,
+    def_id: LocalDefId,
 ) -> ty::PolyFnSig<'tcx> {
     let tcx = icx.tcx;
     let hir_id = tcx.local_def_id_to_hir_id(def_id);
 
-    match sig.decl.output.get_infer_ret_ty() {
-        Some(ty) => {
-            let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
-            // Typeck doesn't expect erased regions to be returned from `type_of`.
-            // This is a heuristic approach. If the scope has region parameters,
-            // we should change fn_sig's lifetime from `ReErased` to `ReError`,
-            // otherwise to `ReStatic`.
-            let has_region_params = generics.params.iter().any(|param| match param.kind {
-                GenericParamKind::Lifetime { .. } => true,
-                _ => false,
-            });
-            let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r {
-                ty::ReErased => {
-                    if has_region_params {
-                        ty::Region::new_error_with_message(
-                            tcx,
-                            DUMMY_SP,
-                            "erased region is not allowed here in return type",
-                        )
-                    } else {
-                        tcx.lifetimes.re_static
-                    }
-                }
-                _ => r,
-            });
+    let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
 
-            let mut visitor = HirPlaceholderCollector::default();
-            visitor.visit_ty(ty);
-
-            let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type");
-            let ret_ty = fn_sig.output();
-            // Don't leak types into signatures unless they're nameable!
-            // For example, if a function returns itself, we don't want that
-            // recursive function definition to leak out into the fn sig.
-            let mut recovered_ret_ty = None;
-
-            if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
-                diag.span_suggestion(
-                    ty.span,
-                    "replace with the correct return type",
-                    suggestable_ret_ty,
-                    Applicability::MachineApplicable,
-                );
-                recovered_ret_ty = Some(suggestable_ret_ty);
-            } else if let Some(sugg) = suggest_impl_trait(
-                &tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
-                tcx.param_env(def_id),
-                ret_ty,
-            ) {
-                diag.span_suggestion(
-                    ty.span,
-                    "replace with an appropriate return type",
-                    sugg,
-                    Applicability::MachineApplicable,
-                );
-            } else if ret_ty.is_closure() {
-                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",
-                );
+    // Typeck doesn't expect erased regions to be returned from `type_of`.
+    // This is a heuristic approach. If the scope has region parameters,
+    // we should change fn_sig's lifetime from `ReErased` to `ReError`,
+    // otherwise to `ReStatic`.
+    let has_region_params = generics.params.iter().any(|param| match param.kind {
+        GenericParamKind::Lifetime { .. } => true,
+        _ => false,
+    });
+    let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r {
+        ty::ReErased => {
+            if has_region_params {
+                ty::Region::new_error_with_message(
+                    tcx,
+                    DUMMY_SP,
+                    "erased region is not allowed here in return type",
+                )
+            } else {
+                tcx.lifetimes.re_static
             }
-
-            let guar = diag.emit();
-            ty::Binder::dummy(tcx.mk_fn_sig(
-                fn_sig.inputs().iter().copied(),
-                recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
-                fn_sig.c_variadic,
-                fn_sig.safety,
-                fn_sig.abi,
-            ))
         }
-        None => icx.lowerer().lower_fn_ty(
-            hir_id,
-            sig.header.safety,
-            sig.header.abi,
-            sig.decl,
-            Some(generics),
-            None,
-        ),
+        _ => r,
+    });
+
+    let mut visitor = HirPlaceholderCollector::default();
+    visitor.visit_ty(infer_ret_ty);
+
+    let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type");
+    let ret_ty = fn_sig.output();
+
+    // Don't leak types into signatures unless they're nameable!
+    // For example, if a function returns itself, we don't want that
+    // recursive function definition to leak out into the fn sig.
+    let mut recovered_ret_ty = None;
+    if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
+        diag.span_suggestion(
+            infer_ret_ty.span,
+            "replace with the correct return type",
+            suggestable_ret_ty,
+            Applicability::MachineApplicable,
+        );
+        recovered_ret_ty = Some(suggestable_ret_ty);
+    } else if let Some(sugg) = suggest_impl_trait(
+        &tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
+        tcx.param_env(def_id),
+        ret_ty,
+    ) {
+        diag.span_suggestion(
+            infer_ret_ty.span,
+            "replace with an appropriate return type",
+            sugg,
+            Applicability::MachineApplicable,
+        );
+    } else if ret_ty.is_closure() {
+        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",
+        );
+    }
+    let guar = diag.emit();
+    ty::Binder::dummy(tcx.mk_fn_sig(
+        fn_sig.inputs().iter().copied(),
+        recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
+        fn_sig.c_variadic,
+        fn_sig.safety,
+        fn_sig.abi,
+    ))
 }
 
 pub fn suggest_impl_trait<'tcx>(
@@ -1611,7 +1630,7 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
     impl_.of_trait.as_ref().map(|ast_trait_ref| {
         let selfty = tcx.type_of(def_id).instantiate_identity();
 
-        check_impl_constness(tcx, tcx.is_const_trait_impl(def_id.to_def_id()), ast_trait_ref);
+        check_impl_constness(tcx, impl_.constness, ast_trait_ref);
 
         let trait_ref = icx.lowerer().lower_impl_trait_ref(ast_trait_ref, selfty);
 
@@ -1619,22 +1638,23 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
             trait_ref: ty::EarlyBinder::bind(trait_ref),
             safety: impl_.safety,
             polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
+            constness: impl_.constness,
         }
     })
 }
 
 fn check_impl_constness(
     tcx: TyCtxt<'_>,
-    is_const: bool,
+    constness: hir::Constness,
     hir_trait_ref: &hir::TraitRef<'_>,
-) -> Option<ErrorGuaranteed> {
-    if !is_const {
-        return None;
+) {
+    if let hir::Constness::NotConst = constness {
+        return;
     }
 
-    let trait_def_id = hir_trait_ref.trait_def_id()?;
+    let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
     if tcx.is_const_trait(trait_def_id) {
-        return None;
+        return;
     }
 
     let trait_name = tcx.item_name(trait_def_id).to_string();
@@ -1650,14 +1670,14 @@ fn check_impl_constness(
             ),
             (false, _) | (_, false) => (None, ""),
         };
-    Some(tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
+    tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
         trait_ref_span: hir_trait_ref.path.span,
         trait_name,
         local_trait_span,
         suggestion_pre,
         marking: (),
         adding: (),
-    }))
+    });
 }
 
 fn polarity_of_impl(
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 1d9114b0ef3..f52d4f42eca 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -470,6 +470,12 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
                     self.outer_index.shift_out(1);
                     res
                 }
+                hir::TyKind::UnsafeBinder(_) => {
+                    self.outer_index.shift_in(1);
+                    let res = intravisit::walk_ty(self, ty);
+                    self.outer_index.shift_out(1);
+                    res
+                }
                 _ => intravisit::walk_ty(self, ty),
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 74f381d2661..0f797bcdae4 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -781,6 +781,36 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                     intravisit::walk_ty(this, ty);
                 });
             }
+            hir::TyKind::UnsafeBinder(binder) => {
+                let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
+                    binder
+                        .generic_params
+                        .iter()
+                        .enumerate()
+                        .map(|(late_bound_idx, param)| {
+                            (
+                                (param.def_id, ResolvedArg::late(late_bound_idx as u32, param)),
+                                late_arg_as_bound_arg(self.tcx, param),
+                            )
+                        })
+                        .unzip();
+
+                deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
+
+                self.record_late_bound_vars(ty.hir_id, binders);
+                let scope = Scope::Binder {
+                    hir_id: ty.hir_id,
+                    bound_vars,
+                    s: self.scope,
+                    scope_type: BinderScopeType::Normal,
+                    where_bound_origin: None,
+                };
+                self.with(scope, |this| {
+                    // a bare fn has no bounds, so everything
+                    // contained within is scoped within its binder.
+                    intravisit::walk_ty(this, ty);
+                });
+            }
             hir::TyKind::TraitObject(bounds, lifetime, _) => {
                 debug!(?bounds, ?lifetime, "TraitObject");
                 let scope = Scope::TraitRefBoundary { s: self.scope };
@@ -822,6 +852,21 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                 };
                 self.with(scope, |this| this.visit_ty(mt.ty));
             }
+            hir::TyKind::TraitAscription(bounds) => {
+                let scope = Scope::TraitRefBoundary { s: self.scope };
+                self.with(scope, |this| {
+                    let scope = Scope::LateBoundary {
+                        s: this.scope,
+                        what: "`impl Trait` in binding",
+                        deny_late_regions: true,
+                    };
+                    this.with(scope, |this| {
+                        for bound in bounds {
+                            this.visit_param_bound(bound);
+                        }
+                    })
+                });
+            }
             _ => intravisit::walk_ty(self, ty),
         }
     }
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 7f62ccc91f0..d46f60b16f5 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1655,6 +1655,24 @@ pub(crate) struct NonConstRange {
     pub span: Span,
 }
 
+#[derive(Subdiagnostic)]
+pub(crate) enum InvalidReceiverTyHint {
+    #[note(hir_analysis_invalid_receiver_ty_help_weak_note)]
+    Weak,
+    #[note(hir_analysis_invalid_receiver_ty_help_nonnull_note)]
+    NonNull,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_invalid_receiver_ty_no_arbitrary_self_types, code = E0307)]
+#[note]
+#[help(hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types)]
+pub(crate) struct InvalidReceiverTyNoArbitrarySelfTypes<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub receiver_ty: Ty<'tcx>,
+}
+
 #[derive(Diagnostic)]
 #[diag(hir_analysis_invalid_receiver_ty, code = E0307)]
 #[note]
@@ -1663,6 +1681,8 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
     #[primary_span]
     pub span: Span,
     pub receiver_ty: Ty<'tcx>,
+    #[subdiagnostic]
+    pub hint: Option<InvalidReceiverTyHint>,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
index d3c86989440..71a5727ed6c 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
@@ -1,9 +1,8 @@
-use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
+use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_errors::codes::*;
 use rustc_errors::struct_span_code_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::DefId;
 use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
 use rustc_middle::span_bug;
 use rustc_middle::ty::fold::BottomUpFolder;
@@ -11,7 +10,7 @@ use rustc_middle::ty::{
     self, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable,
     TypeVisitableExt, Upcast,
 };
-use rustc_span::{ErrorGuaranteed, Span};
+use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
 use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
 use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations};
 use rustc_type_ir::elaborate::ClauseWithSupertraitSpan;
@@ -128,8 +127,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             }
         }
 
-        let mut associated_types: FxIndexMap<Span, FxIndexSet<DefId>> = FxIndexMap::default();
+        let mut needed_associated_types = FxIndexSet::default();
 
+        let principal_span = regular_traits.first().map_or(DUMMY_SP, |info| info.bottom().1);
         let regular_traits_refs_spans = trait_bounds
             .into_iter()
             .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
@@ -145,13 +145,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 let bound_predicate = pred.kind();
                 match bound_predicate.skip_binder() {
                     ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
-                        let pred = bound_predicate.rebind(pred);
-                        associated_types.entry(original_span).or_default().extend(
-                            tcx.associated_items(pred.def_id())
+                        // FIXME(negative_bounds): Handle this correctly...
+                        let trait_ref =
+                            tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
+                        needed_associated_types.extend(
+                            tcx.associated_items(trait_ref.def_id())
                                 .in_definition_order()
                                 .filter(|item| item.kind == ty::AssocKind::Type)
                                 .filter(|item| !item.is_impl_trait_in_trait())
-                                .map(|item| item.def_id),
+                                // If the associated type has a `where Self: Sized` bound,
+                                // we do not need to constrain the associated type.
+                                .filter(|item| !tcx.generics_require_sized_self(item.def_id))
+                                .map(|item| (item.def_id, trait_ref)),
                         );
                     }
                     ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
@@ -201,26 +206,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         // So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
         // types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
         // corresponding `Projection` clause
-        for def_ids in associated_types.values_mut() {
-            for (projection_bound, span) in &projection_bounds {
-                let def_id = projection_bound.item_def_id();
-                def_ids.swap_remove(&def_id);
-                if tcx.generics_require_sized_self(def_id) {
-                    tcx.emit_node_span_lint(
-                        UNUSED_ASSOCIATED_TYPE_BOUNDS,
-                        hir_id,
-                        *span,
-                        crate::errors::UnusedAssociatedTypeBounds { span: *span },
-                    );
-                }
+        for (projection_bound, span) in &projection_bounds {
+            let def_id = projection_bound.item_def_id();
+            let trait_ref = tcx.anonymize_bound_vars(
+                projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)),
+            );
+            needed_associated_types.swap_remove(&(def_id, trait_ref));
+            if tcx.generics_require_sized_self(def_id) {
+                tcx.emit_node_span_lint(
+                    UNUSED_ASSOCIATED_TYPE_BOUNDS,
+                    hir_id,
+                    *span,
+                    crate::errors::UnusedAssociatedTypeBounds { span: *span },
+                );
             }
-            // If the associated type has a `where Self: Sized` bound, we do not need to constrain the associated
-            // type in the `dyn Trait`.
-            def_ids.retain(|def_id| !tcx.generics_require_sized_self(def_id));
         }
 
         if let Err(guar) = self.check_for_required_assoc_tys(
-            associated_types,
+            principal_span,
+            needed_associated_types,
             potential_assoc_types,
             hir_trait_bounds,
         ) {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 2e227ead14a..00c1f9b332b 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -9,7 +9,6 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_middle::bug;
-use rustc_middle::query::Key;
 use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
 use rustc_middle::ty::{
     self, AdtDef, Binder, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeVisitableExt,
@@ -722,51 +721,42 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     /// emit a generic note suggesting using a `where` clause to constraint instead.
     pub(crate) fn check_for_required_assoc_tys(
         &self,
-        associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
+        principal_span: Span,
+        missing_assoc_types: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>,
         potential_assoc_types: Vec<usize>,
         trait_bounds: &[hir::PolyTraitRef<'_>],
     ) -> Result<(), ErrorGuaranteed> {
-        if associated_types.values().all(|v| v.is_empty()) {
+        if missing_assoc_types.is_empty() {
             return Ok(());
         }
 
         let tcx = self.tcx();
-        // FIXME: Marked `mut` so that we can replace the spans further below with a more
-        // appropriate one, but this should be handled earlier in the span assignment.
-        let associated_types: FxIndexMap<Span, Vec<_>> = associated_types
+        // FIXME: This logic needs some more care w.r.t handling of conflicts
+        let missing_assoc_types: Vec<_> = missing_assoc_types
             .into_iter()
-            .map(|(span, def_ids)| {
-                (span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect())
-            })
+            .map(|(def_id, trait_ref)| (tcx.associated_item(def_id), trait_ref))
             .collect();
-        let mut names: FxIndexMap<String, Vec<Symbol>> = Default::default();
+        let mut names: FxIndexMap<_, Vec<Symbol>> = Default::default();
         let mut names_len = 0;
 
         // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
         // `issue-22560.rs`.
-        let mut trait_bound_spans: Vec<Span> = vec![];
         let mut dyn_compatibility_violations = Ok(());
-        for (span, items) in &associated_types {
-            if !items.is_empty() {
-                trait_bound_spans.push(*span);
-            }
-            for assoc_item in items {
-                let trait_def_id = assoc_item.container_id(tcx);
-                names.entry(tcx.def_path_str(trait_def_id)).or_default().push(assoc_item.name);
-                names_len += 1;
-
-                let violations =
-                    dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, *assoc_item);
-                if !violations.is_empty() {
-                    dyn_compatibility_violations = Err(report_dyn_incompatibility(
-                        tcx,
-                        *span,
-                        None,
-                        trait_def_id,
-                        &violations,
-                    )
-                    .emit());
-                }
+        for (assoc_item, trait_ref) in &missing_assoc_types {
+            names.entry(trait_ref).or_default().push(assoc_item.name);
+            names_len += 1;
+
+            let violations =
+                dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), *assoc_item);
+            if !violations.is_empty() {
+                dyn_compatibility_violations = Err(report_dyn_incompatibility(
+                    tcx,
+                    principal_span,
+                    None,
+                    trait_ref.def_id(),
+                    &violations,
+                )
+                .emit());
             }
         }
 
@@ -814,6 +804,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             .into_iter()
             .map(|(trait_, mut assocs)| {
                 assocs.sort();
+                let trait_ = trait_.print_trait_sugared();
                 format!("{} in `{trait_}`", match &assocs[..] {
                     [] => String::new(),
                     [only] => format!("`{only}`"),
@@ -827,10 +818,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         names.sort();
         let names = names.join(", ");
 
-        trait_bound_spans.sort();
         let mut err = struct_span_code_err!(
             self.dcx(),
-            trait_bound_spans,
+            principal_span,
             E0191,
             "the value of the associated type{} {} must be specified",
             pluralize!(names_len),
@@ -840,81 +830,83 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let mut types_count = 0;
         let mut where_constraints = vec![];
         let mut already_has_generics_args_suggestion = false;
-        for (span, assoc_items) in &associated_types {
-            let mut names: UnordMap<_, usize> = Default::default();
-            for item in assoc_items {
-                types_count += 1;
-                *names.entry(item.name).or_insert(0) += 1;
-            }
-            let mut dupes = false;
-            let mut shadows = false;
-            for item in assoc_items {
-                let prefix = if names[&item.name] > 1 {
-                    let trait_def_id = item.container_id(tcx);
-                    dupes = true;
-                    format!("{}::", tcx.def_path_str(trait_def_id))
-                } else if bound_names.get(&item.name).is_some_and(|x| x != &item) {
-                    let trait_def_id = item.container_id(tcx);
-                    shadows = true;
-                    format!("{}::", tcx.def_path_str(trait_def_id))
-                } else {
-                    String::new()
-                };
 
-                let mut is_shadowed = false;
-
-                if let Some(assoc_item) = bound_names.get(&item.name)
-                    && assoc_item != &item
-                {
-                    is_shadowed = true;
+        let mut names: UnordMap<_, usize> = Default::default();
+        for (item, _) in &missing_assoc_types {
+            types_count += 1;
+            *names.entry(item.name).or_insert(0) += 1;
+        }
+        let mut dupes = false;
+        let mut shadows = false;
+        for (item, trait_ref) in &missing_assoc_types {
+            let prefix = if names[&item.name] > 1 {
+                let trait_def_id = trait_ref.def_id();
+                dupes = true;
+                format!("{}::", tcx.def_path_str(trait_def_id))
+            } else if bound_names.get(&item.name).is_some_and(|x| *x != item) {
+                let trait_def_id = trait_ref.def_id();
+                shadows = true;
+                format!("{}::", tcx.def_path_str(trait_def_id))
+            } else {
+                String::new()
+            };
 
-                    let rename_message =
-                        if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" };
-                    err.span_label(
-                        tcx.def_span(assoc_item.def_id),
-                        format!("`{}{}` shadowed here{}", prefix, item.name, rename_message),
-                    );
-                }
+            let mut is_shadowed = false;
 
-                let rename_message = if is_shadowed { ", consider renaming it" } else { "" };
+            if let Some(assoc_item) = bound_names.get(&item.name)
+                && *assoc_item != item
+            {
+                is_shadowed = true;
 
-                if let Some(sp) = tcx.hir().span_if_local(item.def_id) {
-                    err.span_label(
-                        sp,
-                        format!("`{}{}` defined here{}", prefix, item.name, rename_message),
-                    );
-                }
+                let rename_message =
+                    if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" };
+                err.span_label(
+                    tcx.def_span(assoc_item.def_id),
+                    format!("`{}{}` shadowed here{}", prefix, item.name, rename_message),
+                );
             }
-            if potential_assoc_types.len() == assoc_items.len() {
-                // When the amount of missing associated types equals the number of
-                // extra type arguments present. A suggesting to replace the generic args with
-                // associated types is already emitted.
-                already_has_generics_args_suggestion = true;
-            } else if let (Ok(snippet), false, false) =
-                (tcx.sess.source_map().span_to_snippet(*span), dupes, shadows)
-            {
-                let types: Vec<_> =
-                    assoc_items.iter().map(|item| format!("{} = Type", item.name)).collect();
-                let code = if snippet.ends_with('>') {
-                    // The user wrote `Trait<'a>` or similar and we don't have a type we can
-                    // suggest, but at least we can clue them to the correct syntax
-                    // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the
-                    // suggestion.
-                    format!("{}, {}>", &snippet[..snippet.len() - 1], types.join(", "))
-                } else if in_expr_or_pat {
-                    // The user wrote `Iterator`, so we don't have a type we can suggest, but at
-                    // least we can clue them to the correct syntax `Iterator::<Item = Type>`.
-                    format!("{}::<{}>", snippet, types.join(", "))
-                } else {
-                    // The user wrote `Iterator`, so we don't have a type we can suggest, but at
-                    // least we can clue them to the correct syntax `Iterator<Item = Type>`.
-                    format!("{}<{}>", snippet, types.join(", "))
-                };
-                suggestions.push((*span, code));
-            } else if dupes {
-                where_constraints.push(*span);
+
+            let rename_message = if is_shadowed { ", consider renaming it" } else { "" };
+
+            if let Some(sp) = tcx.hir().span_if_local(item.def_id) {
+                err.span_label(
+                    sp,
+                    format!("`{}{}` defined here{}", prefix, item.name, rename_message),
+                );
             }
         }
+        if potential_assoc_types.len() == missing_assoc_types.len() {
+            // When the amount of missing associated types equals the number of
+            // extra type arguments present. A suggesting to replace the generic args with
+            // associated types is already emitted.
+            already_has_generics_args_suggestion = true;
+        } else if let (Ok(snippet), false, false) =
+            (tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows)
+        {
+            let types: Vec<_> = missing_assoc_types
+                .iter()
+                .map(|(item, _)| format!("{} = Type", item.name))
+                .collect();
+            let code = if snippet.ends_with('>') {
+                // The user wrote `Trait<'a>` or similar and we don't have a type we can
+                // suggest, but at least we can clue them to the correct syntax
+                // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the
+                // suggestion.
+                format!("{}, {}>", &snippet[..snippet.len() - 1], types.join(", "))
+            } else if in_expr_or_pat {
+                // The user wrote `Iterator`, so we don't have a type we can suggest, but at
+                // least we can clue them to the correct syntax `Iterator::<Item = Type>`.
+                format!("{}::<{}>", snippet, types.join(", "))
+            } else {
+                // The user wrote `Iterator`, so we don't have a type we can suggest, but at
+                // least we can clue them to the correct syntax `Iterator<Item = Type>`.
+                format!("{}<{}>", snippet, types.join(", "))
+            };
+            suggestions.push((principal_span, code));
+        } else if dupes {
+            where_constraints.push(principal_span);
+        }
+
         let where_msg = "consider introducing a new type parameter, adding `where` constraints \
                          using the fully-qualified path to the associated types";
         if !where_constraints.is_empty() && suggestions.is_empty() {
@@ -925,32 +917,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
         if suggestions.len() != 1 || already_has_generics_args_suggestion {
             // We don't need this label if there's an inline suggestion, show otherwise.
-            for (span, assoc_items) in &associated_types {
-                let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
-                for item in assoc_items {
-                    types_count += 1;
-                    *names.entry(item.name).or_insert(0) += 1;
-                }
-                let mut label = vec![];
-                for item in assoc_items {
-                    let postfix = if names[&item.name] > 1 {
-                        let trait_def_id = item.container_id(tcx);
-                        format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id))
-                    } else {
-                        String::new()
-                    };
-                    label.push(format!("`{}`{}", item.name, postfix));
-                }
-                if !label.is_empty() {
-                    err.span_label(
-                        *span,
-                        format!(
-                            "associated type{} {} must be specified",
-                            pluralize!(label.len()),
-                            label.join(", "),
-                        ),
-                    );
-                }
+            let mut names: FxIndexMap<_, usize> = FxIndexMap::default();
+            for (item, _) in &missing_assoc_types {
+                types_count += 1;
+                *names.entry(item.name).or_insert(0) += 1;
+            }
+            let mut label = vec![];
+            for (item, trait_ref) in &missing_assoc_types {
+                let postfix = if names[&item.name] > 1 {
+                    format!(" (from trait `{}`)", trait_ref.print_trait_sugared())
+                } else {
+                    String::new()
+                };
+                label.push(format!("`{}`{}", item.name, postfix));
+            }
+            if !label.is_empty() {
+                err.span_label(
+                    principal_span,
+                    format!(
+                        "associated type{} {} must be specified",
+                        pluralize!(label.len()),
+                        label.join(", "),
+                    ),
+                );
             }
         }
         suggestions.sort_by_key(|&(span, _)| span);
@@ -1007,8 +996,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     )),
                 ..
             }) = node
-            && let Some(ty_def_id) = qself_ty.ty_def_id()
-            && let [inherent_impl] = tcx.inherent_impls(ty_def_id)
+            && let Some(adt_def) = qself_ty.ty_adt_def()
+            && let [inherent_impl] = tcx.inherent_impls(adt_def.did())
             && let name = format!("{ident2}_{ident3}")
             && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx
                 .associated_items(inherent_impl)
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 7683c87168b..a357ade0294 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -123,6 +123,13 @@ pub trait HirTyLowerer<'tcx> {
     /// Returns the const to use when a const is omitted.
     fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx>;
 
+    fn register_trait_ascription_bounds(
+        &self,
+        bounds: Vec<(ty::Clause<'tcx>, Span)>,
+        hir_id: HirId,
+        span: Span,
+    );
+
     /// Probe bounds in scope where the bounded type coincides with the given type parameter.
     ///
     /// Rephrased, this returns bounds of the form `T: Trait`, where `T` is a type parameter
@@ -2312,6 +2319,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     self.lower_fn_ty(hir_ty.hir_id, bf.safety, bf.abi, bf.decl, None, Some(hir_ty)),
                 )
             }
+            hir::TyKind::UnsafeBinder(_binder) => {
+                let guar = self
+                    .dcx()
+                    .struct_span_err(hir_ty.span, "unsafe binders are not yet implemented")
+                    .emit();
+                Ty::new_error(tcx, guar)
+            }
             hir::TyKind::TraitObject(bounds, lifetime, repr) => {
                 if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) {
                     // Don't continue with type analysis if the `dyn` keyword is missing
@@ -2368,6 +2382,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
                 self.lower_opaque_ty(opaque_ty.def_id, in_trait)
             }
+            hir::TyKind::TraitAscription(hir_bounds) => {
+                // Impl trait in bindings lower as an infer var with additional
+                // set of type bounds.
+                let self_ty = self.ty_infer(None, hir_ty.span);
+                let mut bounds = Bounds::default();
+                self.lower_bounds(
+                    self_ty,
+                    hir_bounds.iter(),
+                    &mut bounds,
+                    ty::List::empty(),
+                    PredicateFilter::All,
+                );
+                self.register_trait_ascription_bounds(
+                    bounds.clauses().collect(),
+                    hir_ty.hir_id,
+                    hir_ty.span,
+                );
+                self_ty
+            }
             // If we encounter a type relative path with RTN generics, then it must have
             // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore
             // it's certainly in an illegal position.
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 20ba9ae2632..8dd8a5c98ef 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -288,7 +288,13 @@ impl<'a> State<'a> {
             hir::TyKind::BareFn(f) => {
                 self.print_ty_fn(f.abi, f.safety, f.decl, None, f.generic_params, f.param_names);
             }
+            hir::TyKind::UnsafeBinder(unsafe_binder) => {
+                self.print_unsafe_binder(unsafe_binder);
+            }
             hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"),
+            hir::TyKind::TraitAscription(bounds) => {
+                self.print_bounds("impl", bounds);
+            }
             hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false),
             hir::TyKind::TraitObject(bounds, lifetime, syntax) => {
                 if syntax == ast::TraitObjectSyntax::Dyn {
@@ -339,6 +345,15 @@ impl<'a> State<'a> {
         self.end()
     }
 
+    fn print_unsafe_binder(&mut self, unsafe_binder: &hir::UnsafeBinderTy<'_>) {
+        self.ibox(INDENT_UNIT);
+        self.word("unsafe");
+        self.print_generic_params(unsafe_binder.generic_params);
+        self.nbsp();
+        self.print_type(unsafe_binder.inner_ty);
+        self.end();
+    }
+
     fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(item.span.lo());
@@ -1530,6 +1545,19 @@ impl<'a> State<'a> {
 
                 self.word(")");
             }
+            hir::ExprKind::UnsafeBinderCast(kind, expr, ty) => {
+                match kind {
+                    hir::UnsafeBinderCastKind::Wrap => self.word("wrap_binder!("),
+                    hir::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder!("),
+                }
+                self.print_expr(expr);
+                if let Some(ty) = ty {
+                    self.word(",");
+                    self.space();
+                    self.print_type(ty);
+                }
+                self.word(")");
+            }
             hir::ExprKind::Yield(expr, _) => {
                 self.word_space("yield");
                 self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 56903865277..66978399efb 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -72,12 +72,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if self.try_structurally_resolve_type(expr.span, ty).is_never()
             && self.expr_guaranteed_to_constitute_read_for_never(expr)
         {
-            if let Some(_) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {
+            if let Some(adjustments) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {
                 let reported = self.dcx().span_delayed_bug(
                     expr.span,
                     "expression with never type wound up being adjusted",
                 );
-                return Ty::new_error(self.tcx(), reported);
+
+                return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &adjustments[..] {
+                    target.to_owned()
+                } else {
+                    Ty::new_error(self.tcx(), reported)
+                };
             }
 
             let adj_ty = self.next_ty_var(expr.span);
@@ -329,6 +334,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // Assignment does call `drop_in_place`, though, but its safety
                     // requirements are not the same.
                     ExprKind::AddrOf(..) | hir::ExprKind::Field(..) => false,
+
+                    // Place-preserving expressions only constitute reads if their
+                    // parent expression constitutes a read.
+                    ExprKind::Type(..) | ExprKind::UnsafeBinderCast(..) => {
+                        self.expr_guaranteed_to_constitute_read_for_never(expr)
+                    }
+
                     ExprKind::Assign(lhs, _, _) => {
                         // Only the LHS does not constitute a read
                         expr.hir_id != lhs.hir_id
@@ -353,7 +365,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     | ExprKind::Binary(_, _, _)
                     | ExprKind::Unary(_, _)
                     | ExprKind::Cast(_, _)
-                    | ExprKind::Type(_, _)
                     | ExprKind::DropTemps(_)
                     | ExprKind::If(_, _, _)
                     | ExprKind::Closure(_)
@@ -564,7 +575,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.check_expr_index(base, idx, expr, brackets_span)
             }
             ExprKind::Yield(value, _) => self.check_expr_yield(value, expr),
-            hir::ExprKind::Err(guar) => Ty::new_error(tcx, guar),
+            ExprKind::UnsafeBinderCast(kind, expr, ty) => {
+                self.check_expr_unsafe_binder_cast(kind, expr, ty, expected)
+            }
+            ExprKind::Err(guar) => Ty::new_error(tcx, guar),
         }
     }
 
@@ -1634,6 +1648,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    fn check_expr_unsafe_binder_cast(
+        &self,
+        _kind: hir::UnsafeBinderCastKind,
+        expr: &'tcx hir::Expr<'tcx>,
+        _hir_ty: Option<&'tcx hir::Ty<'tcx>>,
+        _expected: Expectation<'tcx>,
+    ) -> Ty<'tcx> {
+        let guar =
+            self.dcx().struct_span_err(expr.span, "unsafe binders are not yet implemented").emit();
+        Ty::new_error(self.tcx, guar)
+    }
+
     fn check_expr_array(
         &self,
         args: &'tcx [hir::Expr<'tcx>],
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 27ec2e9e0d4..ecbae6ac72f 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -341,6 +341,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                 self.walk_expr(subexpr)?;
             }
 
+            hir::ExprKind::UnsafeBinderCast(_, subexpr, _) => {
+                self.walk_expr(subexpr)?;
+            }
+
             hir::ExprKind::Unary(hir::UnOp::Deref, base) => {
                 // *base
                 self.walk_expr(base)?;
@@ -1360,7 +1364,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                 self.cat_res(expr.hir_id, expr.span, expr_ty, res)
             }
 
+            // both type ascription and unsafe binder casts don't affect
+            // the place-ness of the subexpression.
             hir::ExprKind::Type(e, _) => self.cat_expr(e),
+            hir::ExprKind::UnsafeBinderCast(_, e, _) => self.cat_expr(e),
 
             hir::ExprKind::AddrOf(..)
             | hir::ExprKind::Call(..)
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 863be3bdcb2..0dacfc9b7bf 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -4,11 +4,11 @@ use std::slice;
 use rustc_abi::FieldIdx;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey};
-use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::{ExprKind, GenericArg, HirId, Node, QPath};
+use rustc_hir::{self as hir, ExprKind, GenericArg, HirId, Node, QPath, intravisit};
 use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend;
 use rustc_hir_analysis::hir_ty_lowering::generics::{
     check_generic_arg_count_for_call, lower_generic_args,
@@ -25,7 +25,7 @@ use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::{
     self, AdtKind, CanonicalUserType, GenericArgKind, GenericArgsRef, GenericParamDefKind,
-    IsIdentity, Ty, TyCtxt, UserArgs, UserSelfTy, UserType,
+    IsIdentity, Ty, TyCtxt, UserArgs, UserSelfTy,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
@@ -216,11 +216,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         debug!("fcx {}", self.tag());
 
         if Self::can_contain_user_lifetime_bounds((args, user_self_ty)) {
-            let canonicalized =
-                self.canonicalize_user_type_annotation(UserType::TypeOf(def_id, UserArgs {
-                    args,
-                    user_self_ty,
-                }));
+            let canonicalized = self.canonicalize_user_type_annotation(ty::UserType::new(
+                ty::UserTypeKind::TypeOf(def_id, UserArgs { args, user_self_ty }),
+            ));
             debug!(?canonicalized);
             self.write_user_type_annotation(hir_id, canonicalized);
         }
@@ -462,13 +460,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         LoweredTy::from_raw(self, hir_ty.span, ty)
     }
 
+    /// Walk a `hir_ty` and collect any clauses that may have come from a type
+    /// within the `hir_ty`. These clauses will be canonicalized with a user type
+    /// annotation so that we can enforce these bounds in borrowck, too.
+    pub(crate) fn collect_impl_trait_clauses_from_hir_ty(
+        &self,
+        hir_ty: &'tcx hir::Ty<'tcx>,
+    ) -> ty::Clauses<'tcx> {
+        struct CollectClauses<'a, 'tcx> {
+            clauses: Vec<ty::Clause<'tcx>>,
+            fcx: &'a FnCtxt<'a, 'tcx>,
+        }
+
+        impl<'tcx> intravisit::Visitor<'tcx> for CollectClauses<'_, 'tcx> {
+            fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
+                if let Some(clauses) = self.fcx.trait_ascriptions.borrow().get(&ty.hir_id.local_id)
+                {
+                    self.clauses.extend(clauses.iter().cloned());
+                }
+                intravisit::walk_ty(self, ty)
+            }
+        }
+
+        let mut clauses = CollectClauses { clauses: vec![], fcx: self };
+        clauses.visit_ty(hir_ty);
+        self.tcx.mk_clauses(&clauses.clauses)
+    }
+
     #[instrument(level = "debug", skip_all)]
-    pub(crate) fn lower_ty_saving_user_provided_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
+    pub(crate) fn lower_ty_saving_user_provided_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> Ty<'tcx> {
         let ty = self.lower_ty(hir_ty);
         debug!(?ty);
 
         if Self::can_contain_user_lifetime_bounds(ty.raw) {
-            let c_ty = self.canonicalize_response(UserType::Ty(ty.raw));
+            let c_ty = self.canonicalize_response(ty::UserType::new(ty::UserTypeKind::Ty(ty.raw)));
             debug!(?c_ty);
             self.typeck_results.borrow_mut().user_provided_types_mut().insert(hir_ty.hir_id, c_ty);
         }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index aacdcf027b6..b9011e89f04 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -10,10 +10,11 @@ use std::ops::Deref;
 
 use hir::def_id::CRATE_DEF_ID;
 use rustc_errors::DiagCtxtHandle;
-use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::{self as hir, HirId, ItemLocalMap};
 use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
 use rustc_infer::infer;
+use rustc_infer::traits::Obligation;
 use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
@@ -114,6 +115,12 @@ pub(crate) struct FnCtxt<'a, 'tcx> {
 
     pub(super) diverging_fallback_behavior: DivergingFallbackBehavior,
     pub(super) diverging_block_behavior: DivergingBlockBehavior,
+
+    /// Clauses that we lowered as part of the `impl_trait_in_bindings` feature.
+    ///
+    /// These are stored here so we may collect them when canonicalizing user
+    /// type ascriptions later.
+    pub(super) trait_ascriptions: RefCell<ItemLocalMap<Vec<ty::Clause<'tcx>>>>,
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -141,6 +148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             fallback_has_occurred: Cell::new(false),
             diverging_fallback_behavior,
             diverging_block_behavior,
+            trait_ascriptions: Default::default(),
         }
     }
 
@@ -252,6 +260,30 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
         }
     }
 
+    fn register_trait_ascription_bounds(
+        &self,
+        bounds: Vec<(ty::Clause<'tcx>, Span)>,
+        hir_id: HirId,
+        _span: Span,
+    ) {
+        for (clause, span) in bounds {
+            if clause.has_escaping_bound_vars() {
+                self.dcx().span_delayed_bug(span, "clause should have no escaping bound vars");
+                continue;
+            }
+
+            self.trait_ascriptions.borrow_mut().entry(hir_id.local_id).or_default().push(clause);
+
+            let clause = self.normalize(span, clause);
+            self.register_predicate(Obligation::new(
+                self.tcx,
+                self.misc(span),
+                self.param_env,
+                clause,
+            ));
+        }
+    }
+
     fn probe_ty_param_bounds(
         &self,
         _: Span,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index ddcd90a2a9d..21b1768ae6f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -10,7 +10,7 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{
     Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId,
-    Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicateKind,
+    Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicateKind, expr_needs_parens,
 };
 use rustc_hir_analysis::collect::suggest_impl_trait;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
@@ -35,7 +35,6 @@ use tracing::{debug, instrument};
 
 use super::FnCtxt;
 use crate::fn_ctxt::rustc_span::BytePos;
-use crate::hir::is_range_literal;
 use crate::method::probe;
 use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
 use crate::{errors, fluent_generated as fluent};
@@ -2648,7 +2647,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
 
                     let make_sugg = |expr: &Expr<'_>, span: Span, sugg: &str| {
-                        if self.needs_parentheses(expr) {
+                        if expr_needs_parens(expr) {
                             (
                                 vec![
                                     (span.shrink_to_lo(), format!("{prefix}{sugg}(")),
@@ -2861,7 +2860,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             return None;
                         }
 
-                        if self.needs_parentheses(expr) {
+                        if expr_needs_parens(expr) {
                             return Some((
                                 vec![
                                     (span, format!("{suggestion}(")),
@@ -2902,16 +2901,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         false
     }
 
-    fn needs_parentheses(&self, expr: &hir::Expr<'_>) -> bool {
-        match expr.kind {
-            // parenthesize if needed (Issue #46756)
-            hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
-            // parenthesize borrows of range literals (Issue #54505)
-            _ if is_range_literal(expr) => true,
-            _ => false,
-        }
-    }
-
     pub(crate) fn suggest_cast(
         &self,
         err: &mut Diag<'_>,
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index f427b0b805e..48fd5f1f982 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -2,7 +2,7 @@ use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{HirId, PatKind};
 use rustc_infer::traits::ObligationCauseCode;
-use rustc_middle::ty::{Ty, UserType};
+use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
 use rustc_span::def_id::LocalDefId;
 use tracing::debug;
@@ -92,7 +92,12 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
             Some(ref ty) => {
                 let o_ty = self.fcx.lower_ty(ty);
 
-                let c_ty = self.fcx.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw));
+                let c_ty = self.fcx.infcx.canonicalize_user_type_annotation(
+                    ty::UserType::new_with_bounds(
+                        ty::UserTypeKind::Ty(o_ty.raw),
+                        self.fcx.collect_impl_trait_clauses_from_hir_ty(ty),
+                    ),
+                );
                 debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty);
                 self.fcx
                     .typeck_results
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index b31ee1a55d6..ef431c852e9 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -17,7 +17,6 @@ use rustc_middle::ty::adjustment::{
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{
     self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, UserArgs,
-    UserType,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_span::{DUMMY_SP, Span};
@@ -491,9 +490,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                     user_self_ty: None, // not relevant here
                 };
 
-                self.fcx.canonicalize_user_type_annotation(UserType::TypeOf(
-                    pick.item.def_id,
-                    user_args,
+                self.fcx.canonicalize_user_type_annotation(ty::UserType::new(
+                    ty::UserTypeKind::TypeOf(pick.item.def_id, user_args),
                 ))
             });
 
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 2a8ed26aa2b..e7726845652 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -10,8 +10,12 @@ use rustc_errors::{
 };
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
-use rustc_hir::{self as hir, BindingMode, ByRef, HirId, LangItem, Mutability, Pat, PatKind};
+use rustc_hir::{
+    self as hir, BindingMode, ByRef, ExprKind, HirId, LangItem, Mutability, Pat, PatKind,
+    expr_needs_parens,
+};
 use rustc_infer::infer;
+use rustc_middle::traits::PatternOriginExpr;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
@@ -94,10 +98,32 @@ struct PatInfo<'a, 'tcx> {
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn pattern_cause(&self, ti: &TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> {
+        // If origin_expr exists, then expected represents the type of origin_expr.
+        // If span also exists, then span == origin_expr.span (although it doesn't need to exist).
+        // In that case, we can peel away references from both and treat them
+        // as the same.
+        let origin_expr_info = ti.origin_expr.map(|mut cur_expr| {
+            let mut count = 0;
+
+            // cur_ty may have more layers of references than cur_expr.
+            // We can only make suggestions about cur_expr, however, so we'll
+            // use that as our condition for stopping.
+            while let ExprKind::AddrOf(.., inner) = &cur_expr.kind {
+                cur_expr = inner;
+                count += 1;
+            }
+
+            PatternOriginExpr {
+                peeled_span: cur_expr.span,
+                peeled_count: count,
+                peeled_prefix_suggestion_parentheses: expr_needs_parens(cur_expr),
+            }
+        });
+
         let code = ObligationCauseCode::Pattern {
             span: ti.span,
             root_ty: ti.expected,
-            origin_expr: ti.origin_expr.is_some(),
+            origin_expr: origin_expr_info,
         };
         self.cause(cause_span, code)
     }
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index e17a68c8692..6f1e3a0cf8c 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -476,7 +476,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             for (local_id, c_ty) in sorted_user_provided_types {
                 let hir_id = HirId { owner: common_hir_owner, local_id };
 
-                if let ty::UserType::TypeOf(_, user_args) = c_ty.value {
+                if let ty::UserTypeKind::TypeOf(_, user_args) = c_ty.value.kind {
                     // This is a unit-testing mechanism.
                     let span = self.tcx().hir().span(hir_id);
                     // We need to buffer the errors in order to guarantee a consistent
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 07ae24ee6d3..91f190c6a28 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -371,7 +371,6 @@ pub(crate) fn initialize_checked_jobserver(early_dcx: &EarlyDiagCtxt) {
 
 // JUSTIFICATION: before session exists, only config
 #[allow(rustc::bad_opt_access)]
-#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
     trace!("run_compiler");
 
@@ -425,7 +424,11 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
                 config.opts.unstable_opts.translate_directionality_markers,
             ) {
                 Ok(bundle) => bundle,
-                Err(e) => early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")),
+                Err(e) => {
+                    // We can't translate anything if we failed to load translations
+                    #[allow(rustc::untranslatable_diagnostic)]
+                    early_dcx.early_fatal(format!("failed to load fluent bundle: {e}"))
+                }
             };
 
             let mut locale_resources = config.locale_resources;
@@ -479,7 +482,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
             let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints());
             if let Some(register_lints) = config.register_lints.as_deref() {
                 register_lints(&sess, &mut lint_store);
-                sess.registered_lints = true;
             }
             sess.lint_store = Some(Lrc::new(lint_store));
 
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 62f35333015..430bc7db077 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -1125,6 +1125,18 @@ pub(crate) fn start_codegen<'tcx>(
         }
     }
 
+    // This must run after monomorphization so that all generic types
+    // have been instantiated.
+    if tcx.sess.opts.unstable_opts.print_type_sizes {
+        tcx.sess.code_stats.print_type_sizes();
+    }
+
+    if tcx.sess.opts.unstable_opts.print_vtable_sizes {
+        let crate_name = tcx.crate_name(LOCAL_CRATE);
+
+        tcx.sess.code_stats.print_vtable_sizes(crate_name);
+    }
+
     codegen
 }
 
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 7e3a1332630..bb2ad3b3dd0 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -127,18 +127,6 @@ impl Linker {
     ) -> Linker {
         let ongoing_codegen = passes::start_codegen(codegen_backend, tcx);
 
-        // This must run after monomorphization so that all generic types
-        // have been instantiated.
-        if tcx.sess.opts.unstable_opts.print_type_sizes {
-            tcx.sess.code_stats.print_type_sizes();
-        }
-
-        if tcx.sess.opts.unstable_opts.print_vtable_sizes {
-            let crate_name = tcx.crate_name(LOCAL_CRATE);
-
-            tcx.sess.code_stats.print_vtable_sizes(crate_name);
-        }
-
         Linker {
             dep_graph: tcx.dep_graph.clone(),
             output_filenames: Arc::clone(tcx.output_filenames(())),
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index d3213b1263c..2af25bfd3aa 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -35,10 +35,10 @@ pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
 pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dyn CodegenBackend) {
     let tf = sym::target_feature;
 
-    let unstable_target_features = codegen_backend.target_features(sess, true);
+    let unstable_target_features = codegen_backend.target_features_cfg(sess, true);
     sess.unstable_target_features.extend(unstable_target_features.iter().cloned());
 
-    let target_features = codegen_backend.target_features(sess, false);
+    let target_features = codegen_backend.target_features_cfg(sess, false);
     sess.target_features.extend(target_features.iter().cloned());
 
     cfg.extend(target_features.into_iter().map(|feat| (tf, Some(feat))));
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 49e6b763590..01d9ac20fae 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -806,10 +806,14 @@ lint_unexpected_cfg_add_build_rs_println = or consider adding `{$build_rs_printl
 lint_unexpected_cfg_add_cargo_feature = consider using a Cargo feature instead
 lint_unexpected_cfg_add_cargo_toml_lint_cfg = or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg}
 lint_unexpected_cfg_add_cmdline_arg = to expect this configuration use `{$cmdline_arg}`
+lint_unexpected_cfg_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of it's defining crate, try updating your dependencies with `cargo update`
+
 lint_unexpected_cfg_define_features = consider defining some features in `Cargo.toml`
 lint_unexpected_cfg_doc_cargo = see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
 lint_unexpected_cfg_doc_rustc = see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
+lint_unexpected_cfg_from_external_macro_origin = using a cfg inside a {$macro_kind} will use the cfgs from the destination crate and not the ones from the defining crate
+lint_unexpected_cfg_from_external_macro_refer = try refering to `{$macro_name}` crate for guidance on how handle this unexpected cfg
 lint_unexpected_cfg_name = unexpected `cfg` condition name: `{$name}`
 lint_unexpected_cfg_name_expected_names = expected names are: {$possibilities}{$and_more ->
         [0] {""}
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 093cc16fb4c..3543784bc72 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -3038,7 +3038,7 @@ impl EarlyLintPass for SpecialModuleName {
         for item in &krate.items {
             if let ast::ItemKind::Mod(
                 _,
-                ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _),
+                ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _, _),
             ) = item.kind
             {
                 if item.attrs.iter().any(|a| a.has_name(sym::path)) {
diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
index 16994846545..63a722f6067 100644
--- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
+++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
@@ -1,9 +1,10 @@
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::bug;
 use rustc_session::Session;
 use rustc_session::config::ExpectedValues;
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::symbol::Ident;
-use rustc_span::{Span, Symbol, sym};
+use rustc_span::{ExpnKind, Span, Symbol, sym};
 
 use crate::lints;
 
@@ -60,6 +61,35 @@ fn cargo_help_sub(
     }
 }
 
+fn rustc_macro_help(span: Span) -> Option<lints::UnexpectedCfgRustcMacroHelp> {
+    let oexpn = span.ctxt().outer_expn_data();
+    if let Some(def_id) = oexpn.macro_def_id
+        && let ExpnKind::Macro(macro_kind, macro_name) = oexpn.kind
+        && def_id.krate != LOCAL_CRATE
+    {
+        Some(lints::UnexpectedCfgRustcMacroHelp { macro_kind: macro_kind.descr(), macro_name })
+    } else {
+        None
+    }
+}
+
+fn cargo_macro_help(span: Span) -> Option<lints::UnexpectedCfgCargoMacroHelp> {
+    let oexpn = span.ctxt().outer_expn_data();
+    if let Some(def_id) = oexpn.macro_def_id
+        && let ExpnKind::Macro(macro_kind, macro_name) = oexpn.kind
+        && def_id.krate != LOCAL_CRATE
+    {
+        Some(lints::UnexpectedCfgCargoMacroHelp {
+            macro_kind: macro_kind.descr(),
+            macro_name,
+            // FIXME: Get access to a `TyCtxt` from an `EarlyContext`
+            // crate_name: cx.tcx.crate_name(def_id.krate),
+        })
+    } else {
+        None
+    }
+}
+
 pub(super) fn unexpected_cfg_name(
     sess: &Session,
     (name, name_span): (Symbol, Span),
@@ -85,6 +115,7 @@ pub(super) fn unexpected_cfg_name(
     };
 
     let is_from_cargo = rustc_session::utils::was_invoked_from_cargo();
+    let is_from_external_macro = rustc_middle::lint::in_external_macro(sess, name_span);
     let mut is_feature_cfg = name == sym::feature;
 
     let code_sugg = if is_feature_cfg && is_from_cargo {
@@ -185,12 +216,21 @@ pub(super) fn unexpected_cfg_name(
     };
 
     let invocation_help = if is_from_cargo {
-        let sub = if !is_feature_cfg { Some(cargo_help_sub(sess, &inst)) } else { None };
-        lints::unexpected_cfg_name::InvocationHelp::Cargo { sub }
+        let help = if !is_feature_cfg && !is_from_external_macro {
+            Some(cargo_help_sub(sess, &inst))
+        } else {
+            None
+        };
+        lints::unexpected_cfg_name::InvocationHelp::Cargo {
+            help,
+            macro_help: cargo_macro_help(name_span),
+        }
     } else {
-        lints::unexpected_cfg_name::InvocationHelp::Rustc(lints::UnexpectedCfgRustcHelp::new(
-            &inst(EscapeQuotes::No),
-        ))
+        let help = lints::UnexpectedCfgRustcHelp::new(&inst(EscapeQuotes::No));
+        lints::unexpected_cfg_name::InvocationHelp::Rustc {
+            help,
+            macro_help: rustc_macro_help(name_span),
+        }
     };
 
     lints::UnexpectedCfgName { code_sugg, invocation_help, name }
@@ -216,7 +256,9 @@ pub(super) fn unexpected_cfg_value(
         .copied()
         .flatten()
         .collect();
+
     let is_from_cargo = rustc_session::utils::was_invoked_from_cargo();
+    let is_from_external_macro = rustc_middle::lint::in_external_macro(sess, name_span);
 
     // Show the full list if all possible values for a given name, but don't do it
     // for names as the possibilities could be very long
@@ -284,25 +326,31 @@ pub(super) fn unexpected_cfg_value(
     };
 
     let invocation_help = if is_from_cargo {
-        let help = if name == sym::feature {
+        let help = if name == sym::feature && !is_from_external_macro {
             if let Some((value, _value_span)) = value {
                 Some(lints::unexpected_cfg_value::CargoHelp::AddFeature { value })
             } else {
                 Some(lints::unexpected_cfg_value::CargoHelp::DefineFeatures)
             }
-        } else if can_suggest_adding_value {
+        } else if can_suggest_adding_value && !is_from_external_macro {
             Some(lints::unexpected_cfg_value::CargoHelp::Other(cargo_help_sub(sess, &inst)))
         } else {
             None
         };
-        lints::unexpected_cfg_value::InvocationHelp::Cargo(help)
+        lints::unexpected_cfg_value::InvocationHelp::Cargo {
+            help,
+            macro_help: cargo_macro_help(name_span),
+        }
     } else {
         let help = if can_suggest_adding_value {
             Some(lints::UnexpectedCfgRustcHelp::new(&inst(EscapeQuotes::No)))
         } else {
             None
         };
-        lints::unexpected_cfg_value::InvocationHelp::Rustc(help)
+        lints::unexpected_cfg_value::InvocationHelp::Rustc {
+            help,
+            macro_help: rustc_macro_help(name_span),
+        }
     };
 
     lints::UnexpectedCfgValue {
diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs
index 7e298a9a63c..10769b57a76 100644
--- a/compiler/rustc_lint/src/dangling.rs
+++ b/compiler/rustc_lint/src/dangling.rs
@@ -192,6 +192,8 @@ fn is_temporary_rvalue(expr: &Expr<'_>) -> bool {
         | ExprKind::DropTemps(..)
         | ExprKind::Let(..) => false,
 
+        ExprKind::UnsafeBinderCast(..) => false,
+
         // Not applicable
         ExprKind::Type(..) | ExprKind::Err(..) => false,
     }
diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs
index 2db229ed133..1402129195f 100644
--- a/compiler/rustc_lint/src/if_let_rescope.rs
+++ b/compiler/rustc_lint/src/if_let_rescope.rs
@@ -422,6 +422,7 @@ impl<'tcx, 'a> Visitor<'tcx> for FindSignificantDropper<'tcx, 'a> {
             hir::ExprKind::Unary(_, expr)
             | hir::ExprKind::Cast(expr, _)
             | hir::ExprKind::Type(expr, _)
+            | hir::ExprKind::UnsafeBinderCast(_, expr, _)
             | hir::ExprKind::Yield(expr, _)
             | hir::ExprKind::AddrOf(_, _, expr)
             | hir::ExprKind::Match(expr, _, _)
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 20822f23bf1..5da9f6d2053 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2172,6 +2172,25 @@ impl UnexpectedCfgRustcHelp {
     }
 }
 
+#[derive(Subdiagnostic)]
+#[note(lint_unexpected_cfg_from_external_macro_origin)]
+#[help(lint_unexpected_cfg_from_external_macro_refer)]
+pub(crate) struct UnexpectedCfgRustcMacroHelp {
+    pub macro_kind: &'static str,
+    pub macro_name: Symbol,
+}
+
+#[derive(Subdiagnostic)]
+#[note(lint_unexpected_cfg_from_external_macro_origin)]
+#[help(lint_unexpected_cfg_from_external_macro_refer)]
+#[help(lint_unexpected_cfg_cargo_update)]
+pub(crate) struct UnexpectedCfgCargoMacroHelp {
+    pub macro_kind: &'static str,
+    pub macro_name: Symbol,
+    // FIXME: Figure out a way to get the crate name
+    // crate_name: String,
+}
+
 #[derive(LintDiagnostic)]
 #[diag(lint_unexpected_cfg_name)]
 pub(crate) struct UnexpectedCfgName {
@@ -2276,10 +2295,17 @@ pub(crate) mod unexpected_cfg_name {
         #[note(lint_unexpected_cfg_doc_cargo)]
         Cargo {
             #[subdiagnostic]
-            sub: Option<super::UnexpectedCfgCargoHelp>,
+            macro_help: Option<super::UnexpectedCfgCargoMacroHelp>,
+            #[subdiagnostic]
+            help: Option<super::UnexpectedCfgCargoHelp>,
         },
         #[note(lint_unexpected_cfg_doc_rustc)]
-        Rustc(#[subdiagnostic] super::UnexpectedCfgRustcHelp),
+        Rustc {
+            #[subdiagnostic]
+            macro_help: Option<super::UnexpectedCfgRustcMacroHelp>,
+            #[subdiagnostic]
+            help: super::UnexpectedCfgRustcHelp,
+        },
     }
 }
 
@@ -2382,9 +2408,19 @@ pub(crate) mod unexpected_cfg_value {
     #[derive(Subdiagnostic)]
     pub(crate) enum InvocationHelp {
         #[note(lint_unexpected_cfg_doc_cargo)]
-        Cargo(#[subdiagnostic] Option<CargoHelp>),
+        Cargo {
+            #[subdiagnostic]
+            help: Option<CargoHelp>,
+            #[subdiagnostic]
+            macro_help: Option<super::UnexpectedCfgCargoMacroHelp>,
+        },
         #[note(lint_unexpected_cfg_doc_rustc)]
-        Rustc(#[subdiagnostic] Option<super::UnexpectedCfgRustcHelp>),
+        Rustc {
+            #[subdiagnostic]
+            help: Option<super::UnexpectedCfgRustcHelp>,
+            #[subdiagnostic]
+            macro_help: Option<super::UnexpectedCfgRustcMacroHelp>,
+        },
     }
 
     #[derive(Subdiagnostic)]
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index 641d1d8e798..e8de0acb7c9 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -77,7 +77,7 @@ pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
             verify_ok(tcx, &linkage);
             (ty, linkage)
         })
-        .collect::<Vec<_>>()
+        .collect()
 }
 
 fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 5c80d24f502..df5b06c6d16 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1264,12 +1264,7 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool {
 
 fn should_encode_constness(def_kind: DefKind) -> bool {
     match def_kind {
-        DefKind::Fn
-        | DefKind::AssocFn
-        | DefKind::Closure
-        | DefKind::Impl { of_trait: true }
-        | DefKind::Variant
-        | DefKind::Ctor(..) => true,
+        DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Ctor(_, CtorKind::Fn) => true,
 
         DefKind::Struct
         | DefKind::Union
@@ -1281,7 +1276,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
         | DefKind::Static { .. }
         | DefKind::TyAlias
         | DefKind::OpaqueTy
-        | DefKind::Impl { of_trait: false }
+        | DefKind::Impl { .. }
         | DefKind::ForeignTy
         | DefKind::ConstParam
         | DefKind::InlineConst
@@ -1296,6 +1291,8 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
         | DefKind::ExternCrate
+        | DefKind::Ctor(_, CtorKind::Const)
+        | DefKind::Variant
         | DefKind::SyntheticCoroutineBody => false,
     }
 }
@@ -2164,10 +2161,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_dylib_dependency_formats(&mut self) -> LazyArray<Option<LinkagePreference>> {
         empty_proc_macro!(self);
         let formats = self.tcx.dependency_formats(());
-        for (ty, arr) in formats.iter() {
-            if *ty != CrateType::Dylib {
-                continue;
-            }
+        if let Some(arr) = formats.get(&CrateType::Dylib) {
             return self.lazy_array(arr.iter().map(|slot| match *slot {
                 Linkage::NotLinked | Linkage::IncludedFromDylib => None,
 
diff --git a/compiler/rustc_middle/src/middle/dependency_format.rs b/compiler/rustc_middle/src/middle/dependency_format.rs
index a3aff9a1101..e3b40b64157 100644
--- a/compiler/rustc_middle/src/middle/dependency_format.rs
+++ b/compiler/rustc_middle/src/middle/dependency_format.rs
@@ -7,6 +7,7 @@
 // FIXME: move this file to rustc_metadata::dependency_format, but
 // this will introduce circular dependency between rustc_metadata and rustc_middle
 
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_macros::{Decodable, Encodable, HashStable};
 use rustc_session::config::CrateType;
 
@@ -18,7 +19,7 @@ pub type DependencyList = Vec<Linkage>;
 /// A mapping of all required dependencies for a particular flavor of output.
 ///
 /// This is local to the tcx, and is generally relevant to one session.
-pub type Dependencies = Vec<(CrateType, DependencyList)>;
+pub type Dependencies = FxIndexMap<CrateType, DependencyList>;
 
 #[derive(Copy, Clone, PartialEq, Debug, HashStable, Encodable, Decodable)]
 pub enum Linkage {
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 52009422d98..d8a39191920 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -467,6 +467,9 @@ impl<'tcx> Const<'tcx> {
                 let const_val = tcx.valtree_to_const_val((ty, valtree));
                 Self::Val(const_val, ty)
             }
+            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
+                Self::Unevaluated(UnevaluatedConst { def, args, promoted: None }, ty)
+            }
             _ => Self::Ty(ty, c),
         }
     }
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 1f50b67cb50..266dc7ad2b3 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -294,10 +294,22 @@ pub enum Linkage {
     Common,
 }
 
+/// Specifies the symbol visibility with regards to dynamic linking.
+///
+/// Visibility doesn't have any effect when linkage is internal.
+///
+/// DSO means dynamic shared object, that is a dynamically linked executable or dylib.
 #[derive(Copy, Clone, PartialEq, Debug, HashStable)]
 pub enum Visibility {
+    /// Export the symbol from the DSO and apply overrides of the symbol by outside DSOs to within
+    /// the DSO if the object file format supports this.
     Default,
+    /// Hide the symbol outside of the defining DSO even when external linkage is used to export it
+    /// from the object file.
     Hidden,
+    /// Export the symbol from the DSO, but don't apply overrides of the symbol by outside DSOs to
+    /// within the DSO. Equivalent to default visibility with object file formats that don't support
+    /// overriding exported symbols by another DSO.
     Protected,
 }
 
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 970dc72e1ff..66fec2dd0f7 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -41,7 +41,8 @@ pub trait Key: Sized {
         None
     }
 
-    fn ty_def_id(&self) -> Option<DefId> {
+    /// Used to detect when ADT def ids are used as keys in a cycle for better error reporting.
+    fn def_id_for_ty_in_cycle(&self) -> Option<DefId> {
         None
     }
 }
@@ -423,7 +424,7 @@ impl<'tcx> Key for Ty<'tcx> {
         DUMMY_SP
     }
 
-    fn ty_def_id(&self) -> Option<DefId> {
+    fn def_id_for_ty_in_cycle(&self) -> Option<DefId> {
         match *self.kind() {
             ty::Adt(adt, _) => Some(adt.did()),
             ty::Coroutine(def_id, ..) => Some(def_id),
@@ -471,8 +472,8 @@ impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> {
         self.value.default_span(tcx)
     }
 
-    fn ty_def_id(&self) -> Option<DefId> {
-        self.value.ty_def_id()
+    fn def_id_for_ty_in_cycle(&self) -> Option<DefId> {
+        self.value.def_id_for_ty_in_cycle()
     }
 }
 
@@ -593,7 +594,7 @@ impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>
         DUMMY_SP
     }
 
-    fn ty_def_id(&self) -> Option<DefId> {
+    fn def_id_for_ty_in_cycle(&self) -> Option<DefId> {
         match self.1.value.kind() {
             ty::Adt(adt, _) => Some(adt.did()),
             _ => None,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index fc3d690a8a9..cc4e31294bd 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -746,7 +746,10 @@ rustc_queries! {
         desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) }
     }
 
-    /// Returns `true` if this is a const fn / const impl.
+    /// Returns the constness of function-like things (tuple struct/variant constructors, functions,
+    /// methods)
+    ///
+    /// Will ICE if used on things that are always const or never const.
     ///
     /// **Do not call this function manually.** It is only meant to cache the base data for the
     /// higher-level functions. Consider using `is_const_fn` or `is_const_trait_impl` instead.
@@ -2230,7 +2233,7 @@ rustc_queries! {
     }
 
     /// Returns the Rust target features for the current target. These are not always the same as LLVM target features!
-    query rust_target_features(_: CrateNum) -> &'tcx UnordMap<String, rustc_target::target_features::Stability> {
+    query rust_target_features(_: CrateNum) -> &'tcx UnordMap<String, rustc_target::target_features::StabilityComputed> {
         arena_cache
         eval_always
         desc { "looking up Rust target features" }
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index c8675660e0f..3337f7ceee7 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -44,16 +44,16 @@ pub struct DynamicQuery<'tcx, C: QueryCache> {
     pub format_value: fn(&C::Value) -> String,
 }
 
-pub struct QuerySystemFns<'tcx> {
+pub struct QuerySystemFns {
     pub engine: QueryEngine,
     pub local_providers: Providers,
     pub extern_providers: ExternProviders,
-    pub encode_query_results: fn(
+    pub encode_query_results: for<'tcx> fn(
         tcx: TyCtxt<'tcx>,
         encoder: &mut CacheEncoder<'_, 'tcx>,
         query_result_index: &mut EncodedDepNodeIndex,
     ),
-    pub try_mark_green: fn(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool,
+    pub try_mark_green: for<'tcx> fn(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool,
 }
 
 pub struct QuerySystem<'tcx> {
@@ -68,7 +68,7 @@ pub struct QuerySystem<'tcx> {
     /// This is `None` if we are not incremental compilation mode
     pub on_disk_cache: Option<OnDiskCache>,
 
-    pub fns: QuerySystemFns<'tcx>,
+    pub fns: QuerySystemFns,
 
     pub jobs: AtomicU64,
 }
@@ -323,7 +323,7 @@ macro_rules! define_callbacks {
                 // Increase this limit if necessary, but do try to keep the size low if possible
                 #[cfg(target_pointer_width = "64")]
                 const _: () = {
-                    if mem::size_of::<Key<'static>>() > 80 {
+                    if mem::size_of::<Key<'static>>() > 88 {
                         panic!("{}", concat!(
                             "the query `",
                             stringify!($name),
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 0a77c3bc42f..8c434265d27 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -316,8 +316,8 @@ pub enum ObligationCauseCode<'tcx> {
         span: Option<Span>,
         /// The root expected type induced by a scrutinee or type expression.
         root_ty: Ty<'tcx>,
-        /// Whether the `Span` came from an expression or a type expression.
-        origin_expr: bool,
+        /// Information about the `Span`, if it came from an expression, otherwise `None`.
+        origin_expr: Option<PatternOriginExpr>,
     },
 
     /// Computing common supertype in an if expression
@@ -530,6 +530,25 @@ pub struct MatchExpressionArmCause<'tcx> {
     pub tail_defines_return_position_impl_trait: Option<LocalDefId>,
 }
 
+/// Information about the origin expression of a pattern, relevant to diagnostics.
+/// Fields here refer to the scrutinee of a pattern.
+/// If the scrutinee isn't given in the diagnostic, then this won't exist.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
+pub struct PatternOriginExpr {
+    /// A span representing the scrutinee expression, with all leading references
+    /// peeled from the expression.
+    /// Only references in the expression are peeled - if the expression refers to a variable
+    /// whose type is a reference, then that reference is kept because it wasn't created
+    /// in the expression.
+    pub peeled_span: Span,
+    /// The number of references that were peeled to produce `peeled_span`.
+    pub peeled_count: usize,
+    /// Does the peeled expression need to be wrapped in parentheses for
+    /// a prefix suggestion (i.e., dereference) to be valid.
+    pub peeled_prefix_suggestion_parentheses: bool,
+}
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[derive(TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
 pub struct IfExpressionCause<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 2841470d248..db1a479f580 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -3141,7 +3141,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Whether the trait impl is marked const. This does not consider stability or feature gates.
     pub fn is_const_trait_impl(self, def_id: DefId) -> bool {
         self.def_kind(def_id) == DefKind::Impl { of_trait: true }
-            && self.constness(def_id) == hir::Constness::Const
+            && self.impl_trait_header(def_id).unwrap().constness == hir::Constness::Const
     }
 
     pub fn intrinsic(self, def_id: impl IntoQueryParam<DefId> + Copy) -> Option<ty::IntrinsicDef> {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 80b11892a42..e47b0cf0b3b 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -95,7 +95,7 @@ pub use self::sty::{
 pub use self::trait_def::TraitDef;
 pub use self::typeck_results::{
     CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, IsIdentity,
-    TypeckResults, UserType, UserTypeAnnotationIndex,
+    TypeckResults, UserType, UserTypeAnnotationIndex, UserTypeKind,
 };
 pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
 use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
@@ -254,6 +254,7 @@ pub struct ImplTraitHeader<'tcx> {
     pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
     pub polarity: ImplPolarity,
     pub safety: hir::Safety,
+    pub constness: hir::Constness,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
@@ -2005,17 +2006,25 @@ impl<'tcx> TyCtxt<'tcx> {
         let def_id: DefId = def_id.into();
         match self.def_kind(def_id) {
             DefKind::Impl { of_trait: true } => {
-                self.constness(def_id) == hir::Constness::Const
-                    && self.is_const_trait(
-                        self.trait_id_of_impl(def_id)
-                            .expect("expected trait for trait implementation"),
-                    )
+                let header = self.impl_trait_header(def_id).unwrap();
+                header.constness == hir::Constness::Const
+                    && self.is_const_trait(header.trait_ref.skip_binder().def_id)
             }
             DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => {
                 self.constness(def_id) == hir::Constness::Const
             }
             DefKind::Trait => self.is_const_trait(def_id),
-            DefKind::AssocTy | DefKind::AssocFn => {
+            DefKind::AssocTy => {
+                let parent_def_id = self.parent(def_id);
+                match self.def_kind(parent_def_id) {
+                    DefKind::Impl { of_trait: false } => false,
+                    DefKind::Impl { of_trait: true } | DefKind::Trait => {
+                        self.is_conditionally_const(parent_def_id)
+                    }
+                    _ => bug!("unexpected parent item of associated type: {parent_def_id:?}"),
+                }
+            }
+            DefKind::AssocFn => {
                 let parent_def_id = self.parent(def_id);
                 match self.def_kind(parent_def_id) {
                     DefKind::Impl { of_trait: false } => {
@@ -2024,7 +2033,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     DefKind::Impl { of_trait: true } | DefKind::Trait => {
                         self.is_conditionally_const(parent_def_id)
                     }
-                    _ => bug!("unexpected parent item of associated item: {parent_def_id:?}"),
+                    _ => bug!("unexpected parent item of associated fn: {parent_def_id:?}"),
                 }
             }
             DefKind::OpaqueTy => match self.opaque_ty_origin(def_id) {
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 8cba5f33278..551c113aa59 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -700,12 +700,31 @@ pub struct CanonicalUserTypeAnnotation<'tcx> {
 /// Canonical user type annotation.
 pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
 
+#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
+#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)]
+pub struct UserType<'tcx> {
+    pub kind: UserTypeKind<'tcx>,
+    pub bounds: ty::Clauses<'tcx>,
+}
+
+impl<'tcx> UserType<'tcx> {
+    pub fn new(kind: UserTypeKind<'tcx>) -> UserType<'tcx> {
+        UserType { kind, bounds: ty::ListWithCachedTypeInfo::empty() }
+    }
+
+    /// A user type annotation with additional bounds that need to be enforced.
+    /// These bounds are lowered from `impl Trait` in bindings.
+    pub fn new_with_bounds(kind: UserTypeKind<'tcx>, bounds: ty::Clauses<'tcx>) -> UserType<'tcx> {
+        UserType { kind, bounds }
+    }
+}
+
 /// A user-given type annotation attached to a constant. These arise
 /// from constants that are named via paths, like `Foo::<A>::new` and
 /// so forth.
 #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
 #[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)]
-pub enum UserType<'tcx> {
+pub enum UserTypeKind<'tcx> {
     Ty(Ty<'tcx>),
 
     /// The canonical type is the result of `type_of(def_id)` with the
@@ -721,9 +740,13 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
     /// Returns `true` if this represents the generic parameters of the form `[?0, ?1, ?2]`,
     /// i.e., each thing is mapped to a canonical variable with the same index.
     fn is_identity(&self) -> bool {
-        match self.value {
-            UserType::Ty(_) => false,
-            UserType::TypeOf(_, user_args) => {
+        if !self.value.bounds.is_empty() {
+            return false;
+        }
+
+        match self.value.kind {
+            UserTypeKind::Ty(_) => false,
+            UserTypeKind::TypeOf(_, user_args) => {
                 if user_args.user_self_ty.is_some() {
                     return false;
                 }
@@ -765,6 +788,18 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
 
 impl<'tcx> std::fmt::Display for UserType<'tcx> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        if self.bounds.is_empty() {
+            self.kind.fmt(f)
+        } else {
+            self.kind.fmt(f)?;
+            write!(f, " + ")?;
+            std::fmt::Debug::fmt(&self.bounds, f)
+        }
+    }
+}
+
+impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self {
             Self::Ty(arg0) => {
                 ty::print::with_no_trimmed_paths!(write!(f, "Ty({})", arg0))
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index b9a45ea3c2c..fda9898ed56 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -389,7 +389,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     .delay_as_bug();
             }
 
-            dtor_candidate = Some((*item_id, self.constness(impl_did)));
+            dtor_candidate = Some((*item_id, self.impl_trait_header(impl_did).unwrap().constness));
         });
 
         let (did, constness) = dtor_candidate?;
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 48d744a9ef6..390909bb0ab 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -100,7 +100,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
         }
         for info in &cycle_error.cycle {
             if info.query.dep_kind == dep_kinds::representability_adt_ty
-                && let Some(def_id) = info.query.ty_def_id
+                && let Some(def_id) = info.query.def_id_for_ty_in_cycle
                 && let Some(def_id) = def_id.as_local()
                 && !item_and_field_ids.iter().any(|&(id, _)| id == def_id)
             {
@@ -182,7 +182,7 @@ impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>>
             &cycle_error.cycle,
             |cycle| {
                 if cycle[0].query.dep_kind == dep_kinds::layout_of
-                    && let Some(def_id) = cycle[0].query.ty_def_id
+                    && let Some(def_id) = cycle[0].query.def_id_for_ty_in_cycle
                     && let Some(def_id) = def_id.as_local()
                     && let def_kind = tcx.def_kind(def_id)
                     && matches!(def_kind, DefKind::Closure)
@@ -209,7 +209,7 @@ impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>>
                         if frame.query.dep_kind != dep_kinds::layout_of {
                             continue;
                         }
-                        let Some(frame_def_id) = frame.query.ty_def_id else {
+                        let Some(frame_def_id) = frame.query.def_id_for_ty_in_cycle else {
                             continue;
                         };
                         let Some(frame_coroutine_kind) = tcx.coroutine_kind(frame_def_id) else {
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 6ce88cdc39d..70a74910a68 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -11,7 +11,7 @@ use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::{self, AdtDef, CanonicalUserTypeAnnotation, Ty, Variance};
 use rustc_middle::{bug, span_bug};
-use rustc_span::Span;
+use rustc_span::{DesugaringKind, Span};
 use tracing::{debug, instrument, trace};
 
 use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
@@ -630,6 +630,80 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         block.and(base_place.index(idx))
     }
 
+    /// Given a place that's either an array or a slice, returns an operand
+    /// with the length of the array/slice.
+    ///
+    /// For arrays it'll be `Operand::Constant` with the actual length;
+    /// For slices it'll be `Operand::Move` of a local using `PtrMetadata`.
+    fn len_of_slice_or_array(
+        &mut self,
+        block: BasicBlock,
+        place: Place<'tcx>,
+        span: Span,
+        source_info: SourceInfo,
+    ) -> Operand<'tcx> {
+        let place_ty = place.ty(&self.local_decls, self.tcx).ty;
+        let usize_ty = self.tcx.types.usize;
+
+        match place_ty.kind() {
+            ty::Array(_elem_ty, len_const) => {
+                // We know how long an array is, so just use that as a constant
+                // directly -- no locals needed. We do need one statement so
+                // that borrow- and initialization-checking consider it used,
+                // though. FIXME: Do we really *need* to count this as a use?
+                // Could partial array tracking work off something else instead?
+                self.cfg.push_fake_read(block, source_info, FakeReadCause::ForIndex, place);
+                let const_ = Const::from_ty_const(*len_const, usize_ty, self.tcx);
+                Operand::Constant(Box::new(ConstOperand { span, user_ty: None, const_ }))
+            }
+            ty::Slice(_elem_ty) => {
+                let ptr_or_ref = if let [PlaceElem::Deref] = place.projection[..]
+                    && let local_ty = self.local_decls[place.local].ty
+                    && local_ty.is_trivially_pure_clone_copy()
+                {
+                    // It's extremely common that we have something that can be
+                    // directly passed to `PtrMetadata`, so avoid an unnecessary
+                    // temporary and statement in those cases. Note that we can
+                    // only do that for `Copy` types -- not `&mut [_]` -- because
+                    // the MIR we're building here needs to pass NLL later.
+                    Operand::Copy(Place::from(place.local))
+                } else {
+                    let len_span = self.tcx.with_stable_hashing_context(|hcx| {
+                        let span = source_info.span;
+                        span.mark_with_reason(
+                            None,
+                            DesugaringKind::IndexBoundsCheckReborrow,
+                            span.edition(),
+                            hcx,
+                        )
+                    });
+                    let ptr_ty = Ty::new_imm_ptr(self.tcx, place_ty);
+                    let slice_ptr = self.temp(ptr_ty, span);
+                    self.cfg.push_assign(
+                        block,
+                        SourceInfo { span: len_span, ..source_info },
+                        slice_ptr,
+                        Rvalue::RawPtr(Mutability::Not, place),
+                    );
+                    Operand::Move(slice_ptr)
+                };
+
+                let len = self.temp(usize_ty, span);
+                self.cfg.push_assign(
+                    block,
+                    source_info,
+                    len,
+                    Rvalue::UnaryOp(UnOp::PtrMetadata, ptr_or_ref),
+                );
+
+                Operand::Move(len)
+            }
+            _ => {
+                span_bug!(span, "len called on place of type {place_ty:?}")
+            }
+        }
+    }
+
     fn bounds_check(
         &mut self,
         block: BasicBlock,
@@ -638,25 +712,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         expr_span: Span,
         source_info: SourceInfo,
     ) -> BasicBlock {
-        let usize_ty = self.tcx.types.usize;
-        let bool_ty = self.tcx.types.bool;
-        // bounds check:
-        let len = self.temp(usize_ty, expr_span);
-        let lt = self.temp(bool_ty, expr_span);
+        let slice = slice.to_place(self);
 
         // len = len(slice)
-        self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.to_place(self)));
+        let len = self.len_of_slice_or_array(block, slice, expr_span, source_info);
+
         // lt = idx < len
+        let bool_ty = self.tcx.types.bool;
+        let lt = self.temp(bool_ty, expr_span);
         self.cfg.push_assign(
             block,
             source_info,
             lt,
             Rvalue::BinaryOp(
                 BinOp::Lt,
-                Box::new((Operand::Copy(Place::from(index)), Operand::Copy(len))),
+                Box::new((Operand::Copy(Place::from(index)), len.to_copy())),
             ),
         );
-        let msg = BoundsCheck { len: Operand::Move(len), index: Operand::Copy(Place::from(index)) };
+        let msg = BoundsCheck { len, index: Operand::Copy(Place::from(index)) };
+
         // assert!(lt, "...")
         self.assert(block, Operand::Move(lt), true, msg, expr_span)
     }
diff --git a/compiler/rustc_mir_build/src/build/matches/match_pair.rs b/compiler/rustc_mir_build/src/build/matches/match_pair.rs
index 2815b390375..33fbd7b1a3f 100644
--- a/compiler/rustc_mir_build/src/build/matches/match_pair.rs
+++ b/compiler/rustc_mir_build/src/build/matches/match_pair.rs
@@ -176,9 +176,8 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
                         ty: cx.infcx.next_ty_var(span),
                     })
                     .args;
-                    let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::TypeOf(
-                        def_id,
-                        ty::UserArgs { args, user_self_ty: None },
+                    let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::new(
+                        ty::UserTypeKind::TypeOf(def_id, ty::UserArgs { args, user_self_ty: None }),
                     ));
                     let annotation = ty::CanonicalUserTypeAnnotation {
                         inferred_ty: pattern.ty,
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index d75f01dfba0..6770e562d50 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -15,7 +15,6 @@ use rustc_middle::ty::adjustment::{
 };
 use rustc_middle::ty::{
     self, AdtKind, GenericArgs, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs,
-    UserType,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_span::{Span, sym};
@@ -443,7 +442,9 @@ impl<'tcx> Cx<'tcx> {
                         let user_provided_types = self.typeck_results().user_provided_types();
                         let user_ty =
                             user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| {
-                                if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value {
+                                if let ty::UserTypeKind::TypeOf(ref mut did, _) =
+                                    &mut u_ty.value.kind
+                                {
                                     *did = adt_def.did();
                                 }
                                 Box::new(u_ty)
@@ -915,6 +916,11 @@ impl<'tcx> Cx<'tcx> {
                     }
                 }
             }
+
+            hir::ExprKind::UnsafeBinderCast(_kind, _source, _ty) => {
+                unreachable!("unsafe binders are not yet implemented")
+            }
+
             hir::ExprKind::DropTemps(source) => ExprKind::Use { source: self.mirror_expr(source) },
             hir::ExprKind::Array(fields) => ExprKind::Array { fields: self.mirror_exprs(fields) },
             hir::ExprKind::Tup(fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) },
diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs
index 53a2a0852eb..ed7c7e40993 100644
--- a/compiler/rustc_mir_build/src/thir/util.rs
+++ b/compiler/rustc_mir_build/src/thir/util.rs
@@ -1,6 +1,6 @@
 use rustc_hir as hir;
 use rustc_middle::bug;
-use rustc_middle::ty::{self, CanonicalUserType, TyCtxt, UserType};
+use rustc_middle::ty::{self, CanonicalUserType, TyCtxt};
 use tracing::debug;
 
 pub(crate) trait UserAnnotatedTyHelpers<'tcx> {
@@ -21,7 +21,7 @@ pub(crate) trait UserAnnotatedTyHelpers<'tcx> {
         let ty = self.typeck_results().node_type(hir_id);
         match ty.kind() {
             ty::Adt(adt_def, ..) => {
-                if let UserType::TypeOf(ref mut did, _) = &mut user_ty.value {
+                if let ty::UserTypeKind::TypeOf(ref mut did, _) = &mut user_ty.value.kind {
                     *did = adt_def.did();
                 }
                 Some(user_ty)
diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
index 4a9bcdaddb3..89ff93d9943 100644
--- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
@@ -179,15 +179,15 @@ where
     /// Advances the cursor to hold the dataflow state at `target` before its "primary" effect is
     /// applied.
     ///
-    /// The "before" effect at the target location *will be* applied.
+    /// The "early" effect at the target location *will be* applied.
     pub fn seek_before_primary_effect(&mut self, target: Location) {
-        self.seek_after(target, Effect::Before)
+        self.seek_after(target, Effect::Early)
     }
 
     /// Advances the cursor to hold the dataflow state at `target` after its "primary" effect is
     /// applied.
     ///
-    /// The "before" effect at the target location will be applied as well.
+    /// The "early" effect at the target location will be applied as well.
     pub fn seek_after_primary_effect(&mut self, target: Location) {
         self.seek_after(target, Effect::Primary)
     }
@@ -222,12 +222,12 @@ where
         #[rustfmt::skip]
         let next_effect = if A::Direction::IS_FORWARD {
             self.pos.curr_effect_index.map_or_else(
-                || Effect::Before.at_index(0),
+                || Effect::Early.at_index(0),
                 EffectIndex::next_in_forward_order,
             )
         } else {
             self.pos.curr_effect_index.map_or_else(
-                || Effect::Before.at_index(block_data.statements.len()),
+                || Effect::Early.at_index(block_data.statements.len()),
                 EffectIndex::next_in_backward_order,
             )
         };
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 566a6b09b2b..9d943ebe327 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -66,12 +66,12 @@ impl Direction for Backward {
     {
         let terminator = block_data.terminator();
         let location = Location { block, statement_index: block_data.statements.len() };
-        analysis.apply_before_terminator_effect(state, terminator, location);
-        analysis.apply_terminator_effect(state, terminator, location);
+        analysis.apply_early_terminator_effect(state, terminator, location);
+        analysis.apply_primary_terminator_effect(state, terminator, location);
         for (statement_index, statement) in block_data.statements.iter().enumerate().rev() {
             let location = Location { block, statement_index };
-            analysis.apply_before_statement_effect(state, statement, location);
-            analysis.apply_statement_effect(state, statement, location);
+            analysis.apply_early_statement_effect(state, statement, location);
+            analysis.apply_primary_statement_effect(state, statement, location);
         }
 
         let exit_state = state;
@@ -159,14 +159,14 @@ impl Direction for Backward {
                 let location = Location { block, statement_index: from.statement_index };
                 let terminator = block_data.terminator();
 
-                if from.effect == Effect::Before {
-                    analysis.apply_before_terminator_effect(state, terminator, location);
-                    if to == Effect::Before.at_index(terminator_index) {
+                if from.effect == Effect::Early {
+                    analysis.apply_early_terminator_effect(state, terminator, location);
+                    if to == Effect::Early.at_index(terminator_index) {
                         return;
                     }
                 }
 
-                analysis.apply_terminator_effect(state, terminator, location);
+                analysis.apply_primary_terminator_effect(state, terminator, location);
                 if to == Effect::Primary.at_index(terminator_index) {
                     return;
                 }
@@ -180,7 +180,7 @@ impl Direction for Backward {
                 let location = Location { block, statement_index: from.statement_index };
                 let statement = &block_data.statements[from.statement_index];
 
-                analysis.apply_statement_effect(state, statement, location);
+                analysis.apply_primary_statement_effect(state, statement, location);
                 if to == Effect::Primary.at_index(from.statement_index) {
                     return;
                 }
@@ -188,7 +188,7 @@ impl Direction for Backward {
                 from.statement_index - 1
             }
 
-            Effect::Before => from.statement_index,
+            Effect::Early => from.statement_index,
         };
 
         // Handle all statements between `first_unapplied_idx` and `to.statement_index`.
@@ -196,21 +196,21 @@ impl Direction for Backward {
         for statement_index in (to.statement_index..next_effect).rev().map(|i| i + 1) {
             let location = Location { block, statement_index };
             let statement = &block_data.statements[statement_index];
-            analysis.apply_before_statement_effect(state, statement, location);
-            analysis.apply_statement_effect(state, statement, location);
+            analysis.apply_early_statement_effect(state, statement, location);
+            analysis.apply_primary_statement_effect(state, statement, location);
         }
 
         // Handle the statement at `to`.
 
         let location = Location { block, statement_index: to.statement_index };
         let statement = &block_data.statements[to.statement_index];
-        analysis.apply_before_statement_effect(state, statement, location);
+        analysis.apply_early_statement_effect(state, statement, location);
 
-        if to.effect == Effect::Before {
+        if to.effect == Effect::Early {
             return;
         }
 
-        analysis.apply_statement_effect(state, statement, location);
+        analysis.apply_primary_statement_effect(state, statement, location);
     }
 
     fn visit_results_in_block<'mir, 'tcx, A>(
@@ -228,17 +228,17 @@ impl Direction for Backward {
 
         let loc = Location { block, statement_index: block_data.statements.len() };
         let term = block_data.terminator();
-        results.analysis.apply_before_terminator_effect(state, term, loc);
-        vis.visit_terminator_before_primary_effect(results, state, term, loc);
-        results.analysis.apply_terminator_effect(state, term, loc);
-        vis.visit_terminator_after_primary_effect(results, state, term, loc);
+        results.analysis.apply_early_terminator_effect(state, term, loc);
+        vis.visit_after_early_terminator_effect(results, state, term, loc);
+        results.analysis.apply_primary_terminator_effect(state, term, loc);
+        vis.visit_after_primary_terminator_effect(results, state, term, loc);
 
         for (statement_index, stmt) in block_data.statements.iter().enumerate().rev() {
             let loc = Location { block, statement_index };
-            results.analysis.apply_before_statement_effect(state, stmt, loc);
-            vis.visit_statement_before_primary_effect(results, state, stmt, loc);
-            results.analysis.apply_statement_effect(state, stmt, loc);
-            vis.visit_statement_after_primary_effect(results, state, stmt, loc);
+            results.analysis.apply_early_statement_effect(state, stmt, loc);
+            vis.visit_after_early_statement_effect(results, state, stmt, loc);
+            results.analysis.apply_primary_statement_effect(state, stmt, loc);
+            vis.visit_after_primary_statement_effect(results, state, stmt, loc);
         }
 
         vis.visit_block_start(state);
@@ -294,13 +294,13 @@ impl Direction for Forward {
     {
         for (statement_index, statement) in block_data.statements.iter().enumerate() {
             let location = Location { block, statement_index };
-            analysis.apply_before_statement_effect(state, statement, location);
-            analysis.apply_statement_effect(state, statement, location);
+            analysis.apply_early_statement_effect(state, statement, location);
+            analysis.apply_primary_statement_effect(state, statement, location);
         }
         let terminator = block_data.terminator();
         let location = Location { block, statement_index: block_data.statements.len() };
-        analysis.apply_before_terminator_effect(state, terminator, location);
-        let edges = analysis.apply_terminator_effect(state, terminator, location);
+        analysis.apply_early_terminator_effect(state, terminator, location);
+        let edges = analysis.apply_primary_terminator_effect(state, terminator, location);
 
         let exit_state = state;
         match edges {
@@ -368,21 +368,21 @@ impl Direction for Forward {
         // after effect, do so now and start the loop below from the next statement.
 
         let first_unapplied_index = match from.effect {
-            Effect::Before => from.statement_index,
+            Effect::Early => from.statement_index,
 
             Effect::Primary if from.statement_index == terminator_index => {
                 debug_assert_eq!(from, to);
 
                 let location = Location { block, statement_index: terminator_index };
                 let terminator = block_data.terminator();
-                analysis.apply_terminator_effect(state, terminator, location);
+                analysis.apply_primary_terminator_effect(state, terminator, location);
                 return;
             }
 
             Effect::Primary => {
                 let location = Location { block, statement_index: from.statement_index };
                 let statement = &block_data.statements[from.statement_index];
-                analysis.apply_statement_effect(state, statement, location);
+                analysis.apply_primary_statement_effect(state, statement, location);
 
                 // If we only needed to apply the after effect of the statement at `idx`, we are
                 // done.
@@ -399,8 +399,8 @@ impl Direction for Forward {
         for statement_index in first_unapplied_index..to.statement_index {
             let location = Location { block, statement_index };
             let statement = &block_data.statements[statement_index];
-            analysis.apply_before_statement_effect(state, statement, location);
-            analysis.apply_statement_effect(state, statement, location);
+            analysis.apply_early_statement_effect(state, statement, location);
+            analysis.apply_primary_statement_effect(state, statement, location);
         }
 
         // Handle the statement or terminator at `to`.
@@ -408,17 +408,17 @@ impl Direction for Forward {
         let location = Location { block, statement_index: to.statement_index };
         if to.statement_index == terminator_index {
             let terminator = block_data.terminator();
-            analysis.apply_before_terminator_effect(state, terminator, location);
+            analysis.apply_early_terminator_effect(state, terminator, location);
 
             if to.effect == Effect::Primary {
-                analysis.apply_terminator_effect(state, terminator, location);
+                analysis.apply_primary_terminator_effect(state, terminator, location);
             }
         } else {
             let statement = &block_data.statements[to.statement_index];
-            analysis.apply_before_statement_effect(state, statement, location);
+            analysis.apply_early_statement_effect(state, statement, location);
 
             if to.effect == Effect::Primary {
-                analysis.apply_statement_effect(state, statement, location);
+                analysis.apply_primary_statement_effect(state, statement, location);
             }
         }
     }
@@ -438,18 +438,18 @@ impl Direction for Forward {
 
         for (statement_index, stmt) in block_data.statements.iter().enumerate() {
             let loc = Location { block, statement_index };
-            results.analysis.apply_before_statement_effect(state, stmt, loc);
-            vis.visit_statement_before_primary_effect(results, state, stmt, loc);
-            results.analysis.apply_statement_effect(state, stmt, loc);
-            vis.visit_statement_after_primary_effect(results, state, stmt, loc);
+            results.analysis.apply_early_statement_effect(state, stmt, loc);
+            vis.visit_after_early_statement_effect(results, state, stmt, loc);
+            results.analysis.apply_primary_statement_effect(state, stmt, loc);
+            vis.visit_after_primary_statement_effect(results, state, stmt, loc);
         }
 
         let loc = Location { block, statement_index: block_data.statements.len() };
         let term = block_data.terminator();
-        results.analysis.apply_before_terminator_effect(state, term, loc);
-        vis.visit_terminator_before_primary_effect(results, state, term, loc);
-        results.analysis.apply_terminator_effect(state, term, loc);
-        vis.visit_terminator_after_primary_effect(results, state, term, loc);
+        results.analysis.apply_early_terminator_effect(state, term, loc);
+        vis.visit_after_early_terminator_effect(results, state, term, loc);
+        results.analysis.apply_primary_terminator_effect(state, term, loc);
+        vis.visit_after_primary_terminator_effect(results, state, term, loc);
 
         vis.visit_block_end(state);
     }
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index f844e8fbe03..5b2b128e035 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -724,7 +724,7 @@ where
         }
     }
 
-    fn visit_statement_before_primary_effect(
+    fn visit_after_early_statement_effect(
         &mut self,
         results: &mut Results<'tcx, A>,
         state: &A::Domain,
@@ -737,7 +737,7 @@ where
         }
     }
 
-    fn visit_statement_after_primary_effect(
+    fn visit_after_primary_statement_effect(
         &mut self,
         results: &mut Results<'tcx, A>,
         state: &A::Domain,
@@ -748,7 +748,7 @@ where
         self.prev_state.clone_from(state)
     }
 
-    fn visit_terminator_before_primary_effect(
+    fn visit_after_early_terminator_effect(
         &mut self,
         results: &mut Results<'tcx, A>,
         state: &A::Domain,
@@ -761,7 +761,7 @@ where
         }
     }
 
-    fn visit_terminator_after_primary_effect(
+    fn visit_after_primary_terminator_effect(
         &mut self,
         results: &mut Results<'tcx, A>,
         state: &A::Domain,
diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs
index e063eaf74bd..cb8159ce37b 100644
--- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs
@@ -38,10 +38,8 @@
 //! [Hasse diagram]: https://en.wikipedia.org/wiki/Hasse_diagram
 //! [poset]: https://en.wikipedia.org/wiki/Partially_ordered_set
 
-use std::iter;
-
+use rustc_index::Idx;
 use rustc_index::bit_set::{BitSet, MixedBitSet};
-use rustc_index::{Idx, IndexVec};
 
 use crate::framework::BitSetExt;
 
@@ -70,53 +68,6 @@ pub trait HasTop {
     const TOP: Self;
 }
 
-/// A `bool` is a "two-point" lattice with `true` as the top element and `false` as the bottom:
-///
-/// ```text
-///      true
-///        |
-///      false
-/// ```
-impl JoinSemiLattice for bool {
-    fn join(&mut self, other: &Self) -> bool {
-        if let (false, true) = (*self, *other) {
-            *self = true;
-            return true;
-        }
-
-        false
-    }
-}
-
-impl HasBottom for bool {
-    const BOTTOM: Self = false;
-
-    fn is_bottom(&self) -> bool {
-        !self
-    }
-}
-
-impl HasTop for bool {
-    const TOP: Self = true;
-}
-
-/// A tuple (or list) of lattices is itself a lattice whose least upper bound is the concatenation
-/// of the least upper bounds of each element of the tuple (or list).
-///
-/// In other words:
-///     (A₀, A₁, ..., Aₙ) ∨ (B₀, B₁, ..., Bₙ) = (A₀∨B₀, A₁∨B₁, ..., Aₙ∨Bₙ)
-impl<I: Idx, T: JoinSemiLattice> JoinSemiLattice for IndexVec<I, T> {
-    fn join(&mut self, other: &Self) -> bool {
-        assert_eq!(self.len(), other.len());
-
-        let mut changed = false;
-        for (a, b) in iter::zip(self, other) {
-            changed |= a.join(b);
-        }
-        changed
-    }
-}
-
 /// A `BitSet` represents the lattice formed by the powerset of all possible values of
 /// the index type `T` ordered by inclusion. Equivalently, it is a tuple of "two-point" lattices,
 /// one for each possible value of `T`.
@@ -197,18 +148,6 @@ impl<T> MaybeReachable<T> {
     }
 }
 
-impl<T> HasBottom for MaybeReachable<T> {
-    const BOTTOM: Self = MaybeReachable::Unreachable;
-
-    fn is_bottom(&self) -> bool {
-        matches!(self, Self::Unreachable)
-    }
-}
-
-impl<T: HasTop> HasTop for MaybeReachable<T> {
-    const TOP: Self = MaybeReachable::Reachable(T::TOP);
-}
-
 impl<S> MaybeReachable<S> {
     /// Return whether the current state contains the given element. If the state is unreachable,
     /// it does no contain anything.
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index 7f5a68e884e..41df5fae0de 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -56,7 +56,7 @@ mod visitor;
 pub use self::cursor::ResultsCursor;
 pub use self::direction::{Backward, Direction, Forward};
 pub use self::lattice::{JoinSemiLattice, MaybeReachable};
-pub use self::results::{EntrySets, Results};
+pub use self::results::{EntryStates, Results};
 pub use self::visitor::{ResultsVisitor, visit_results};
 
 /// Analysis domains are all bitsets of various kinds. This trait holds
@@ -122,8 +122,23 @@ pub trait Analysis<'tcx> {
     // `resume`). It's not obvious how to handle `yield` points in coroutines, however.
     fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain);
 
+    /// Updates the current dataflow state with an "early" effect, i.e. one
+    /// that occurs immediately before the given statement.
+    ///
+    /// This method is useful if the consumer of the results of this analysis only needs to observe
+    /// *part* of the effect of a statement (e.g. for two-phase borrows). As a general rule,
+    /// analyses should not implement this without also implementing
+    /// `apply_primary_statement_effect`.
+    fn apply_early_statement_effect(
+        &mut self,
+        _state: &mut Self::Domain,
+        _statement: &mir::Statement<'tcx>,
+        _location: Location,
+    ) {
+    }
+
     /// Updates the current dataflow state with the effect of evaluating a statement.
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         statement: &mir::Statement<'tcx>,
@@ -131,15 +146,16 @@ pub trait Analysis<'tcx> {
     );
 
     /// Updates the current dataflow state with an effect that occurs immediately *before* the
-    /// given statement.
+    /// given terminator.
     ///
-    /// This method is useful if the consumer of the results of this analysis only needs to observe
-    /// *part* of the effect of a statement (e.g. for two-phase borrows). As a general rule,
-    /// analyses should not implement this without also implementing `apply_statement_effect`.
-    fn apply_before_statement_effect(
+    /// This method is useful if the consumer of the results of this analysis needs only to observe
+    /// *part* of the effect of a terminator (e.g. for two-phase borrows). As a general rule,
+    /// analyses should not implement this without also implementing
+    /// `apply_primary_terminator_effect`.
+    fn apply_early_terminator_effect(
         &mut self,
         _state: &mut Self::Domain,
-        _statement: &mir::Statement<'tcx>,
+        _terminator: &mir::Terminator<'tcx>,
         _location: Location,
     ) {
     }
@@ -150,7 +166,7 @@ pub trait Analysis<'tcx> {
     /// in this function. That should go in `apply_call_return_effect`. For example, in the
     /// `InitializedPlaces` analyses, the return place for a function call is not marked as
     /// initialized here.
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
         _state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
@@ -159,27 +175,13 @@ pub trait Analysis<'tcx> {
         terminator.edges()
     }
 
-    /// Updates the current dataflow state with an effect that occurs immediately *before* the
-    /// given terminator.
-    ///
-    /// This method is useful if the consumer of the results of this analysis needs only to observe
-    /// *part* of the effect of a terminator (e.g. for two-phase borrows). As a general rule,
-    /// analyses should not implement this without also implementing `apply_terminator_effect`.
-    fn apply_before_terminator_effect(
-        &mut self,
-        _state: &mut Self::Domain,
-        _terminator: &mir::Terminator<'tcx>,
-        _location: Location,
-    ) {
-    }
-
     /* Edge-specific effects */
 
     /// Updates the current dataflow state with the effect of a successful return from a `Call`
     /// terminator.
     ///
-    /// This is separate from `apply_terminator_effect` to properly track state across unwind
-    /// edges.
+    /// This is separate from `apply_primary_terminator_effect` to properly track state across
+    /// unwind edges.
     fn apply_call_return_effect(
         &mut self,
         _state: &mut Self::Domain,
@@ -234,11 +236,12 @@ pub trait Analysis<'tcx> {
         Self: Sized,
         Self::Domain: DebugWithContext<Self>,
     {
-        let mut entry_sets =
+        let mut entry_states =
             IndexVec::from_fn_n(|_| self.bottom_value(body), body.basic_blocks.len());
-        self.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
+        self.initialize_start_block(body, &mut entry_states[mir::START_BLOCK]);
 
-        if Self::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != self.bottom_value(body) {
+        if Self::Direction::IS_BACKWARD && entry_states[mir::START_BLOCK] != self.bottom_value(body)
+        {
             bug!("`initialize_start_block` is not yet supported for backward dataflow analyses");
         }
 
@@ -262,9 +265,9 @@ pub trait Analysis<'tcx> {
         let mut state = self.bottom_value(body);
         while let Some(bb) = dirty_queue.pop() {
             // Set the state to the entry state of the block.
-            // This is equivalent to `state = entry_sets[bb].clone()`,
+            // This is equivalent to `state = entry_states[bb].clone()`,
             // but it saves an allocation, thus improving compile times.
-            state.clone_from(&entry_sets[bb]);
+            state.clone_from(&entry_states[bb]);
 
             Self::Direction::apply_effects_in_block(
                 &mut self,
@@ -273,7 +276,7 @@ pub trait Analysis<'tcx> {
                 bb,
                 &body[bb],
                 |target: BasicBlock, state: &Self::Domain| {
-                    let set_changed = entry_sets[target].join(state);
+                    let set_changed = entry_states[target].join(state);
                     if set_changed {
                         dirty_queue.insert(target);
                     }
@@ -281,7 +284,7 @@ pub trait Analysis<'tcx> {
             );
         }
 
-        let mut results = Results { analysis: self, entry_sets };
+        let mut results = Results { analysis: self, entry_states };
 
         if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
             let res = write_graphviz_results(tcx, body, &mut results, pass_name);
@@ -358,11 +361,10 @@ impl<T, S: GenKill<T>> GenKill<T> for MaybeReachable<S> {
 // NOTE: DO NOT CHANGE VARIANT ORDER. The derived `Ord` impls rely on the current order.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
 enum Effect {
-    /// The "before" effect (e.g., `apply_before_statement_effect`) for a statement (or
-    /// terminator).
-    Before,
+    /// The "early" effect (e.g., `apply_early_statement_effect`) for a statement/terminator.
+    Early,
 
-    /// The "primary" effect (e.g., `apply_statement_effect`) for a statement (or terminator).
+    /// The "primary" effect (e.g., `apply_primary_statement_effect`) for a statement/terminator.
     Primary,
 }
 
@@ -381,15 +383,15 @@ pub struct EffectIndex {
 impl EffectIndex {
     fn next_in_forward_order(self) -> Self {
         match self.effect {
-            Effect::Before => Effect::Primary.at_index(self.statement_index),
-            Effect::Primary => Effect::Before.at_index(self.statement_index + 1),
+            Effect::Early => Effect::Primary.at_index(self.statement_index),
+            Effect::Primary => Effect::Early.at_index(self.statement_index + 1),
         }
     }
 
     fn next_in_backward_order(self) -> Self {
         match self.effect {
-            Effect::Before => Effect::Primary.at_index(self.statement_index),
-            Effect::Primary => Effect::Before.at_index(self.statement_index - 1),
+            Effect::Early => Effect::Primary.at_index(self.statement_index),
+            Effect::Primary => Effect::Early.at_index(self.statement_index - 1),
         }
     }
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs
index a7dbd99b8ab..8e2c3afddb3 100644
--- a/compiler/rustc_mir_dataflow/src/framework/results.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/results.rs
@@ -6,7 +6,7 @@ use rustc_middle::mir::{BasicBlock, Body, traversal};
 use super::{Analysis, ResultsCursor, ResultsVisitor, visit_results};
 use crate::framework::cursor::ResultsHandle;
 
-pub type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as Analysis<'tcx>>::Domain>;
+pub type EntryStates<'tcx, A> = IndexVec<BasicBlock, <A as Analysis<'tcx>>::Domain>;
 
 /// A dataflow analysis that has converged to fixpoint. It only holds the domain values at the
 /// entry of each basic block. Domain values in other parts of the block are recomputed on the fly
@@ -17,7 +17,7 @@ where
     A: Analysis<'tcx>,
 {
     pub analysis: A,
-    pub entry_sets: EntrySets<'tcx, A>,
+    pub entry_states: EntryStates<'tcx, A>,
 }
 
 impl<'tcx, A> Results<'tcx, A>
@@ -40,7 +40,7 @@ where
 
     /// Gets the dataflow state for the given block.
     pub fn entry_set_for_block(&self, block: BasicBlock) -> &A::Domain {
-        &self.entry_sets[block]
+        &self.entry_states[block]
     }
 
     pub fn visit_with<'mir>(
diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs
index 14fb6dfb50c..8e7d4ab0fa3 100644
--- a/compiler/rustc_mir_dataflow/src/framework/tests.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs
@@ -73,7 +73,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> {
 ///
 /// The `102` in the block's entry set is derived from the basic block index and ensures that the
 /// expected state is unique across all basic blocks. Remember, it is generated by
-/// `mock_entry_sets`, not from actually running `MockAnalysis` to fixpoint.
+/// `mock_entry_states`, not from actually running `MockAnalysis` to fixpoint.
 struct MockAnalysis<'tcx, D> {
     body: &'tcx mir::Body<'tcx>,
     dir: PhantomData<D>,
@@ -90,7 +90,7 @@ impl<D: Direction> MockAnalysis<'_, D> {
         ret
     }
 
-    fn mock_entry_sets(&self) -> IndexVec<BasicBlock, BitSet<usize>> {
+    fn mock_entry_states(&self) -> IndexVec<BasicBlock, BitSet<usize>> {
         let empty = self.bottom_value(self.body);
         let mut ret = IndexVec::from_elem(empty, &self.body.basic_blocks);
 
@@ -104,7 +104,7 @@ impl<D: Direction> MockAnalysis<'_, D> {
     /// Returns the index that should be added to the dataflow state at the given target.
     fn effect(&self, loc: EffectIndex) -> usize {
         let idx = match loc.effect {
-            Effect::Before => loc.statement_index * 2,
+            Effect::Early => loc.statement_index * 2,
             Effect::Primary => loc.statement_index * 2 + 1,
         };
 
@@ -128,14 +128,14 @@ impl<D: Direction> MockAnalysis<'_, D> {
 
         let target = match target {
             SeekTarget::BlockEntry { .. } => return ret,
-            SeekTarget::Before(loc) => Effect::Before.at_index(loc.statement_index),
+            SeekTarget::Early(loc) => Effect::Early.at_index(loc.statement_index),
             SeekTarget::After(loc) => Effect::Primary.at_index(loc.statement_index),
         };
 
         let mut pos = if D::IS_FORWARD {
-            Effect::Before.at_index(0)
+            Effect::Early.at_index(0)
         } else {
-            Effect::Before.at_index(self.body[block].statements.len())
+            Effect::Early.at_index(self.body[block].statements.len())
         };
 
         loop {
@@ -168,52 +168,52 @@ impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> {
         unimplemented!("This is never called since `MockAnalysis` is never iterated to fixpoint");
     }
 
-    fn apply_statement_effect(
+    fn apply_early_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         _statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
-        let idx = self.effect(Effect::Primary.at_index(location.statement_index));
+        let idx = self.effect(Effect::Early.at_index(location.statement_index));
         assert!(state.insert(idx));
     }
 
-    fn apply_before_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         _statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
-        let idx = self.effect(Effect::Before.at_index(location.statement_index));
+        let idx = self.effect(Effect::Primary.at_index(location.statement_index));
         assert!(state.insert(idx));
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_early_terminator_effect(
         &mut self,
         state: &mut Self::Domain,
-        terminator: &'mir mir::Terminator<'tcx>,
+        _terminator: &mir::Terminator<'tcx>,
         location: Location,
-    ) -> TerminatorEdges<'mir, 'tcx> {
-        let idx = self.effect(Effect::Primary.at_index(location.statement_index));
+    ) {
+        let idx = self.effect(Effect::Early.at_index(location.statement_index));
         assert!(state.insert(idx));
-        terminator.edges()
     }
 
-    fn apply_before_terminator_effect(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
-        _terminator: &mir::Terminator<'tcx>,
+        terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
-    ) {
-        let idx = self.effect(Effect::Before.at_index(location.statement_index));
+    ) -> TerminatorEdges<'mir, 'tcx> {
+        let idx = self.effect(Effect::Primary.at_index(location.statement_index));
         assert!(state.insert(idx));
+        terminator.edges()
     }
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 enum SeekTarget {
     BlockEntry(BasicBlock),
-    Before(Location),
+    Early(Location),
     After(Location),
 }
 
@@ -223,7 +223,7 @@ impl SeekTarget {
 
         match *self {
             BlockEntry(block) => block,
-            Before(loc) | After(loc) => loc.block,
+            Early(loc) | After(loc) => loc.block,
         }
     }
 
@@ -235,7 +235,7 @@ impl SeekTarget {
             .map(move |(i, kind)| {
                 let loc = Location { block, statement_index: i };
                 match kind {
-                    0 => SeekTarget::Before(loc),
+                    0 => SeekTarget::Early(loc),
                     1 => SeekTarget::After(loc),
                     _ => unreachable!(),
                 }
@@ -249,7 +249,7 @@ fn test_cursor<D: Direction>(analysis: MockAnalysis<'_, D>) {
     let body = analysis.body;
 
     let mut cursor =
-        Results { entry_sets: analysis.mock_entry_sets(), analysis }.into_results_cursor(body);
+        Results { entry_states: analysis.mock_entry_states(), analysis }.into_results_cursor(body);
 
     cursor.allow_unreachable();
 
@@ -262,7 +262,7 @@ fn test_cursor<D: Direction>(analysis: MockAnalysis<'_, D>) {
 
         match targ {
             BlockEntry(block) => cursor.seek_to_block_entry(block),
-            Before(loc) => cursor.seek_before_primary_effect(loc),
+            Early(loc) => cursor.seek_before_primary_effect(loc),
             After(loc) => cursor.seek_after_primary_effect(loc),
         }
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs
index bde41974d47..d18e9fa33f0 100644
--- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs
@@ -35,9 +35,9 @@ where
 {
     fn visit_block_start(&mut self, _state: &A::Domain) {}
 
-    /// Called with the `before_statement_effect` of the given statement applied to `state` but not
-    /// its `statement_effect`.
-    fn visit_statement_before_primary_effect(
+    /// // njn: grep for "before", "primary", etc.
+    /// Called after the "early" effect of the given statement is applied to `state`.
+    fn visit_after_early_statement_effect(
         &mut self,
         _results: &mut Results<'tcx, A>,
         _state: &A::Domain,
@@ -46,9 +46,8 @@ where
     ) {
     }
 
-    /// Called with both the `before_statement_effect` and the `statement_effect` of the given
-    /// statement applied to `state`.
-    fn visit_statement_after_primary_effect(
+    /// Called after the "primary" effect of the given statement is applied to `state`.
+    fn visit_after_primary_statement_effect(
         &mut self,
         _results: &mut Results<'tcx, A>,
         _state: &A::Domain,
@@ -57,9 +56,8 @@ where
     ) {
     }
 
-    /// Called with the `before_terminator_effect` of the given terminator applied to `state` but
-    /// not its `terminator_effect`.
-    fn visit_terminator_before_primary_effect(
+    /// Called after the "early" effect of the given terminator is applied to `state`.
+    fn visit_after_early_terminator_effect(
         &mut self,
         _results: &mut Results<'tcx, A>,
         _state: &A::Domain,
@@ -68,11 +66,10 @@ where
     ) {
     }
 
-    /// Called with both the `before_terminator_effect` and the `terminator_effect` of the given
-    /// terminator applied to `state`.
+    /// Called after the "primary" effect of the given terminator is applied to `state`.
     ///
     /// The `call_return_effect` (if one exists) will *not* be applied to `state`.
-    fn visit_terminator_after_primary_effect(
+    fn visit_after_primary_terminator_effect(
         &mut self,
         _results: &mut Results<'tcx, A>,
         _state: &A::Domain,
diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
index cec654cac72..568d8a5acaf 100644
--- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
@@ -33,22 +33,22 @@ impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals {
         // No locals are aliased on function entry
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         statement: &Statement<'tcx>,
         location: Location,
     ) {
-        Self::transfer_function(trans).visit_statement(statement, location);
+        Self::transfer_function(state).visit_statement(statement, location);
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'mir Terminator<'tcx>,
         location: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
-        Self::transfer_function(trans).visit_terminator(terminator, location);
+        Self::transfer_function(state).visit_terminator(terminator, location);
         terminator.edges()
     }
 }
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index 91677657602..fb02408e17d 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -70,7 +70,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
     pub fn is_unwind_dead(
         &self,
         place: mir::Place<'tcx>,
-        state: &MaybeReachable<MixedBitSet<MovePathIndex>>,
+        state: &<Self as Analysis<'tcx>>::Domain,
     ) -> bool {
         if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) {
             let mut maybe_live = false;
@@ -218,26 +218,26 @@ impl<'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'_, 'tcx> {
 
 impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
     fn update_bits(
-        trans: &mut <Self as Analysis<'tcx>>::Domain,
+        state: &mut <Self as Analysis<'tcx>>::Domain,
         path: MovePathIndex,
-        state: DropFlagState,
+        dfstate: DropFlagState,
     ) {
-        match state {
-            DropFlagState::Absent => trans.kill(path),
-            DropFlagState::Present => trans.gen_(path),
+        match dfstate {
+            DropFlagState::Absent => state.kill(path),
+            DropFlagState::Present => state.gen_(path),
         }
     }
 }
 
 impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> {
     fn update_bits(
-        trans: &mut <Self as Analysis<'tcx>>::Domain,
+        state: &mut <Self as Analysis<'tcx>>::Domain,
         path: MovePathIndex,
-        state: DropFlagState,
+        dfstate: DropFlagState,
     ) {
-        match state {
-            DropFlagState::Absent => trans.gen_(path),
-            DropFlagState::Present => trans.kill(path),
+        match dfstate {
+            DropFlagState::Absent => state.gen_(path),
+            DropFlagState::Present => state.kill(path),
         }
     }
 }
@@ -263,14 +263,14 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
         });
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
         drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| {
-            Self::update_bits(trans, path, s)
+            Self::update_bits(state, path, s)
         });
 
         // Mark all places as "maybe init" if they are mutably borrowed. See #90752.
@@ -282,12 +282,12 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
             && let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref())
         {
             on_all_children_bits(self.move_data(), mpi, |child| {
-                trans.gen_(child);
+                state.gen_(child);
             })
         }
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
@@ -309,7 +309,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
 
     fn apply_call_return_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _block: mir::BasicBlock,
         return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
@@ -320,7 +320,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
                 self.move_data(),
                 self.move_data().rev_lookup.find(place.as_ref()),
                 |mpi| {
-                    trans.gen_(mpi);
+                    state.gen_(mpi);
                 },
             );
         });
@@ -345,7 +345,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
         };
 
         let mut discriminants = enum_def.discriminants(self.tcx);
-        edge_effects.apply(|trans, edge| {
+        edge_effects.apply(|state, edge| {
             let Some(value) = edge.value else {
                 return;
             };
@@ -363,25 +363,27 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
                 self.move_data(),
                 enum_place,
                 variant,
-                |mpi| trans.kill(mpi),
+                |mpi| state.kill(mpi),
             );
         });
     }
 }
 
+/// There can be many more `MovePathIndex` than there are locals in a MIR body.
+/// We use a mixed bitset to avoid paying too high a memory footprint.
+pub type MaybeUninitializedPlacesDomain = MixedBitSet<MovePathIndex>;
+
 impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
-    /// There can be many more `MovePathIndex` than there are locals in a MIR body.
-    /// We use a mixed bitset to avoid paying too high a memory footprint.
-    type Domain = MixedBitSet<MovePathIndex>;
+    type Domain = MaybeUninitializedPlacesDomain;
 
     const NAME: &'static str = "maybe_uninit";
 
     fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
-        // bottom = initialized (start_block_effect counters this at outset)
+        // bottom = initialized (`initialize_start_block` overwrites this on first entry)
         MixedBitSet::new_empty(self.move_data().move_paths.len())
     }
 
-    // sets on_entry bits for Arg places
+    // sets state bits for Arg places
     fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
         // set all bits to 1 (uninit) before gathering counter-evidence
         state.insert_all();
@@ -392,28 +394,28 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
         });
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
         drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| {
-            Self::update_bits(trans, path, s)
+            Self::update_bits(state, path, s)
         });
 
         // Unlike in `MaybeInitializedPlaces` above, we don't need to change the state when a
         // mutable borrow occurs. Places cannot become uninitialized through a mutable reference.
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
         drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| {
-            Self::update_bits(trans, path, s)
+            Self::update_bits(state, path, s)
         });
         if self.skip_unreachable_unwind.contains(location.block) {
             let mir::TerminatorKind::Drop { target, unwind, .. } = terminator.kind else { bug!() };
@@ -426,7 +428,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
 
     fn apply_call_return_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _block: mir::BasicBlock,
         return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
@@ -437,7 +439,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
                 self.move_data(),
                 self.move_data().rev_lookup.find(place.as_ref()),
                 |mpi| {
-                    trans.kill(mpi);
+                    state.kill(mpi);
                 },
             );
         });
@@ -466,7 +468,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
         };
 
         let mut discriminants = enum_def.discriminants(self.tcx);
-        edge_effects.apply(|trans, edge| {
+        edge_effects.apply(|state, edge| {
             let Some(value) = edge.value else {
                 return;
             };
@@ -484,16 +486,18 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
                 self.move_data(),
                 enum_place,
                 variant,
-                |mpi| trans.gen_(mpi),
+                |mpi| state.gen_(mpi),
             );
         });
     }
 }
 
+/// There can be many more `InitIndex` than there are locals in a MIR body.
+/// We use a mixed bitset to avoid paying too high a memory footprint.
+pub type EverInitializedPlacesDomain = MixedBitSet<InitIndex>;
+
 impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
-    /// There can be many more `InitIndex` than there are locals in a MIR body.
-    /// We use a mixed bitset to avoid paying too high a memory footprint.
-    type Domain = MixedBitSet<InitIndex>;
+    type Domain = EverInitializedPlacesDomain;
 
     const NAME: &'static str = "ever_init";
 
@@ -508,10 +512,10 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
         }
     }
 
-    #[instrument(skip(self, trans), level = "debug")]
-    fn apply_statement_effect(
+    #[instrument(skip(self, state), level = "debug")]
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         stmt: &mir::Statement<'tcx>,
         location: Location,
     ) {
@@ -521,7 +525,7 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
         let rev_lookup = &move_data.rev_lookup;
 
         debug!("initializes move_indexes {:?}", init_loc_map[location]);
-        trans.gen_all(init_loc_map[location].iter().copied());
+        state.gen_all(init_loc_map[location].iter().copied());
 
         if let mir::StatementKind::StorageDead(local) = stmt.kind {
             // End inits for StorageDead, so that an immutable variable can
@@ -531,15 +535,15 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
                     "clears the ever initialized status of {:?}",
                     init_path_map[move_path_index]
                 );
-                trans.kill_all(init_path_map[move_path_index].iter().copied());
+                state.kill_all(init_path_map[move_path_index].iter().copied());
             }
         }
     }
 
-    #[instrument(skip(self, trans, terminator), level = "debug")]
-    fn apply_terminator_effect<'mir>(
+    #[instrument(skip(self, state, terminator), level = "debug")]
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
@@ -548,7 +552,7 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
         let init_loc_map = &move_data.init_loc_map;
         debug!(?term);
         debug!("initializes move_indexes {:?}", init_loc_map[location]);
-        trans.gen_all(
+        state.gen_all(
             init_loc_map[location]
                 .iter()
                 .filter(|init_index| {
@@ -561,7 +565,7 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
 
     fn apply_call_return_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         block: mir::BasicBlock,
         _return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
@@ -570,7 +574,7 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
 
         let call_loc = self.body.terminator_loc(block);
         for init_index in &init_loc_map[call_loc] {
-            trans.gen_(*init_index);
+            state.gen_(*init_index);
         }
     }
 }
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index fd7254a0210..b2050a6adf9 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -40,33 +40,33 @@ impl<'tcx> Analysis<'tcx> for MaybeLiveLocals {
         // No variables are live until we observe a use
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
-        TransferFunction(trans).visit_statement(statement, location);
+        TransferFunction(state).visit_statement(statement, location);
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
-        TransferFunction(trans).visit_terminator(terminator, location);
+        TransferFunction(state).visit_terminator(terminator, location);
         terminator.edges()
     }
 
     fn apply_call_return_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _block: mir::BasicBlock,
         return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
         if let CallReturnPlaces::Yield(resume_place) = return_places {
-            YieldResumeEffect(trans).visit_place(
+            YieldResumeEffect(state).visit_place(
                 &resume_place,
                 PlaceContext::MutatingUse(MutatingUseContext::Yield),
                 Location::START,
@@ -74,7 +74,7 @@ impl<'tcx> Analysis<'tcx> for MaybeLiveLocals {
         } else {
             return_places.for_each(|place| {
                 if let Some(local) = place.as_local() {
-                    trans.kill(local);
+                    state.kill(local);
                 }
             });
         }
@@ -137,10 +137,10 @@ enum DefUse {
 }
 
 impl DefUse {
-    fn apply(trans: &mut BitSet<Local>, place: Place<'_>, context: PlaceContext) {
+    fn apply(state: &mut BitSet<Local>, place: Place<'_>, context: PlaceContext) {
         match DefUse::for_place(place, context) {
-            Some(DefUse::Def) => trans.kill(place.local),
-            Some(DefUse::Use) => trans.gen_(place.local),
+            Some(DefUse::Def) => state.kill(place.local),
+            Some(DefUse::Use) => state.gen_(place.local),
             None => {}
         }
     }
@@ -232,9 +232,9 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
         // No variables are live until we observe a use
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         statement: &mir::Statement<'tcx>,
         location: Location,
     ) {
@@ -258,34 +258,34 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
         };
         if let Some(destination) = destination {
             if !destination.is_indirect()
-                && !trans.contains(destination.local)
+                && !state.contains(destination.local)
                 && !self.always_live.contains(destination.local)
             {
                 // This store is dead
                 return;
             }
         }
-        TransferFunction(trans).visit_statement(statement, location);
+        TransferFunction(state).visit_statement(statement, location);
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
     ) -> TerminatorEdges<'mir, 'tcx> {
-        TransferFunction(trans).visit_terminator(terminator, location);
+        TransferFunction(state).visit_terminator(terminator, location);
         terminator.edges()
     }
 
     fn apply_call_return_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _block: mir::BasicBlock,
         return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
         if let CallReturnPlaces::Yield(resume_place) = return_places {
-            YieldResumeEffect(trans).visit_place(
+            YieldResumeEffect(state).visit_place(
                 &resume_place,
                 PlaceContext::MutatingUse(MutatingUseContext::Yield),
                 Location::START,
@@ -293,7 +293,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
         } else {
             return_places.for_each(|place| {
                 if let Some(local) = place.as_local() {
-                    trans.remove(local);
+                    state.remove(local);
                 }
             });
         }
diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs
index d69a8019c8d..3f29b819a6d 100644
--- a/compiler/rustc_mir_dataflow/src/impls/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs
@@ -5,7 +5,8 @@ mod storage_liveness;
 
 pub use self::borrowed_locals::{MaybeBorrowedLocals, borrowed_locals};
 pub use self::initialized::{
-    EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
+    EverInitializedPlaces, EverInitializedPlacesDomain, MaybeInitializedPlaces,
+    MaybeUninitializedPlaces, MaybeUninitializedPlacesDomain,
 };
 pub use self::liveness::{
     MaybeLiveLocals, MaybeTransitiveLiveLocals, TransferFunction as LivenessTransferFunction,
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 1aae06d79d3..65b480d3a5e 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -44,23 +44,23 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageLive<'a> {
         BitSet::new_empty(body.local_decls.len())
     }
 
-    fn initialize_start_block(&self, body: &Body<'tcx>, on_entry: &mut Self::Domain) {
-        on_entry.union(&*self.always_live_locals);
+    fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
+        state.union(&*self.always_live_locals);
 
         for arg in body.args_iter() {
-            on_entry.insert(arg);
+            state.insert(arg);
         }
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         stmt: &Statement<'tcx>,
         _: Location,
     ) {
         match stmt.kind {
-            StatementKind::StorageLive(l) => trans.gen_(l),
-            StatementKind::StorageDead(l) => trans.kill(l),
+            StatementKind::StorageLive(l) => state.gen_(l),
+            StatementKind::StorageDead(l) => state.kill(l),
             _ => (),
         }
     }
@@ -86,25 +86,25 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageDead<'a> {
         BitSet::new_empty(body.local_decls.len())
     }
 
-    fn initialize_start_block(&self, body: &Body<'tcx>, on_entry: &mut Self::Domain) {
+    fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
         assert_eq!(body.local_decls.len(), self.always_live_locals.domain_size());
         // Do not iterate on return place and args, as they are trivially always live.
         for local in body.vars_and_temps_iter() {
             if !self.always_live_locals.contains(local) {
-                on_entry.insert(local);
+                state.insert(local);
             }
         }
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         stmt: &Statement<'tcx>,
         _: Location,
     ) {
         match stmt.kind {
-            StatementKind::StorageLive(l) => trans.kill(l),
-            StatementKind::StorageDead(l) => trans.gen_(l),
+            StatementKind::StorageLive(l) => state.kill(l),
+            StatementKind::StorageDead(l) => state.gen_(l),
             _ => (),
         }
     }
@@ -134,31 +134,31 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
         BitSet::new_empty(body.local_decls.len())
     }
 
-    fn initialize_start_block(&self, body: &Body<'tcx>, on_entry: &mut Self::Domain) {
+    fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
         // The resume argument is live on function entry (we don't care about
         // the `self` argument)
         for arg in body.args_iter().skip(1) {
-            on_entry.insert(arg);
+            state.insert(arg);
         }
     }
 
-    fn apply_before_statement_effect(
+    fn apply_early_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         stmt: &Statement<'tcx>,
         loc: Location,
     ) {
         // If a place is borrowed in a statement, it needs storage for that statement.
-        MaybeBorrowedLocals::transfer_function(trans).visit_statement(stmt, loc);
+        MaybeBorrowedLocals::transfer_function(state).visit_statement(stmt, loc);
 
         match &stmt.kind {
-            StatementKind::StorageDead(l) => trans.kill(*l),
+            StatementKind::StorageDead(l) => state.kill(*l),
 
             // If a place is assigned to in a statement, it needs storage for that statement.
             StatementKind::Assign(box (place, _))
             | StatementKind::SetDiscriminant { box place, .. }
             | StatementKind::Deinit(box place) => {
-                trans.gen_(place.local);
+                state.gen_(place.local);
             }
 
             // Nothing to do for these. Match exhaustively so this fails to compile when new
@@ -176,29 +176,29 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
         }
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _: &Statement<'tcx>,
         loc: Location,
     ) {
         // If we move from a place then it only stops needing storage *after*
         // that statement.
-        self.check_for_move(trans, loc);
+        self.check_for_move(state, loc);
     }
 
-    fn apply_before_terminator_effect(
+    fn apply_early_terminator_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &Terminator<'tcx>,
         loc: Location,
     ) {
         // If a place is borrowed in a terminator, it needs storage for that terminator.
-        MaybeBorrowedLocals::transfer_function(trans).visit_terminator(terminator, loc);
+        MaybeBorrowedLocals::transfer_function(state).visit_terminator(terminator, loc);
 
         match &terminator.kind {
             TerminatorKind::Call { destination, .. } => {
-                trans.gen_(destination.local);
+                state.gen_(destination.local);
             }
 
             // Note that we do *not* gen the `resume_arg` of `Yield` terminators. The reason for
@@ -213,7 +213,7 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
                         InlineAsmOperand::Out { place, .. }
                         | InlineAsmOperand::InOut { out_place: place, .. } => {
                             if let Some(place) = place {
-                                trans.gen_(place.local);
+                                state.gen_(place.local);
                             }
                         }
                         InlineAsmOperand::In { .. }
@@ -242,9 +242,9 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
         }
     }
 
-    fn apply_terminator_effect<'t>(
+    fn apply_primary_terminator_effect<'t>(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         terminator: &'t Terminator<'tcx>,
         loc: Location,
     ) -> TerminatorEdges<'t, 'tcx> {
@@ -254,12 +254,12 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
             // Since `propagate_call_unwind` doesn't exist, we have to kill the
             // destination here, and then gen it again in `call_return_effect`.
             TerminatorKind::Call { destination, .. } => {
-                trans.kill(destination.local);
+                state.kill(destination.local);
             }
 
             // The same applies to InlineAsm outputs.
             TerminatorKind::InlineAsm { ref operands, .. } => {
-                CallReturnPlaces::InlineAsm(operands).for_each(|place| trans.kill(place.local));
+                CallReturnPlaces::InlineAsm(operands).for_each(|place| state.kill(place.local));
             }
 
             // Nothing to do for these. Match exhaustively so this fails to compile when new
@@ -279,32 +279,32 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
             | TerminatorKind::Unreachable => {}
         }
 
-        self.check_for_move(trans, loc);
+        self.check_for_move(state, loc);
         terminator.edges()
     }
 
     fn apply_call_return_effect(
         &mut self,
-        trans: &mut Self::Domain,
+        state: &mut Self::Domain,
         _block: BasicBlock,
         return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
-        return_places.for_each(|place| trans.gen_(place.local));
+        return_places.for_each(|place| state.gen_(place.local));
     }
 }
 
 impl<'tcx> MaybeRequiresStorage<'_, 'tcx> {
     /// Kill locals that are fully moved and have not been borrowed.
-    fn check_for_move(&mut self, trans: &mut <Self as Analysis<'tcx>>::Domain, loc: Location) {
+    fn check_for_move(&mut self, state: &mut <Self as Analysis<'tcx>>::Domain, loc: Location) {
         let body = self.borrowed_locals.body();
-        let mut visitor = MoveVisitor { trans, borrowed_locals: &mut self.borrowed_locals };
+        let mut visitor = MoveVisitor { state, borrowed_locals: &mut self.borrowed_locals };
         visitor.visit_location(body, loc);
     }
 }
 
 struct MoveVisitor<'a, 'mir, 'tcx> {
     borrowed_locals: &'a mut BorrowedLocalsResults<'mir, 'tcx>,
-    trans: &'a mut BitSet<Local>,
+    state: &'a mut BitSet<Local>,
 }
 
 impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx> {
@@ -312,7 +312,7 @@ impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx> {
         if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context {
             self.borrowed_locals.seek_before_primary_effect(loc);
             if !self.borrowed_locals.get().contains(local) {
-                self.trans.kill(local);
+                self.state.kill(local);
             }
         }
     }
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 2248972cecc..85255db5d9a 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -18,7 +18,7 @@ pub use self::drop_flag_effects::{
     move_path_children_matching, on_all_children_bits, on_lookup_result_bits,
 };
 pub use self::framework::{
-    Analysis, Backward, Direction, EntrySets, Forward, GenKill, JoinSemiLattice, MaybeReachable,
+    Analysis, Backward, Direction, EntryStates, Forward, GenKill, JoinSemiLattice, MaybeReachable,
     Results, ResultsCursor, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice,
     visit_results,
 };
diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs
index 10f1e009855..74209da876a 100644
--- a/compiler/rustc_mir_dataflow/src/points.rs
+++ b/compiler/rustc_mir_dataflow/src/points.rs
@@ -125,7 +125,7 @@ where
     A: Analysis<'tcx, Domain = BitSet<N>>,
     N: Idx,
 {
-    fn visit_statement_after_primary_effect(
+    fn visit_after_primary_statement_effect(
         &mut self,
         _results: &mut Results<'tcx, A>,
         state: &A::Domain,
@@ -139,7 +139,7 @@ where
         });
     }
 
-    fn visit_terminator_after_primary_effect(
+    fn visit_after_primary_terminator_effect(
         &mut self,
         _results: &mut Results<'tcx, A>,
         state: &A::Domain,
diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index 34ef8afdde3..85cf8ca2104 100644
--- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -1,6 +1,5 @@
 use rustc_ast::MetaItem;
 use rustc_hir::def_id::DefId;
-use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::{self, Body, Local, Location};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
@@ -254,7 +253,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals {
         &self,
         tcx: TyCtxt<'tcx>,
         place: mir::Place<'tcx>,
-        state: &BitSet<Local>,
+        state: &Self::Domain,
         call: PeekCall,
     ) {
         info!(?place, "peek_at");
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index ed8678de1eb..9328870c7ae 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -67,7 +67,7 @@ impl<V: Clone> Clone for StateData<V> {
     }
 }
 
-impl<V: JoinSemiLattice + Clone + HasBottom> JoinSemiLattice for StateData<V> {
+impl<V: JoinSemiLattice + Clone> JoinSemiLattice for StateData<V> {
     fn join(&mut self, other: &Self) -> bool {
         let mut changed = false;
         #[allow(rustc::potential_query_instability)]
@@ -342,7 +342,7 @@ impl<V: Clone + HasBottom> State<V> {
     }
 }
 
-impl<V: JoinSemiLattice + Clone + HasBottom> JoinSemiLattice for State<V> {
+impl<V: JoinSemiLattice + Clone> JoinSemiLattice for State<V> {
     fn join(&mut self, other: &Self) -> bool {
         match (&mut *self, other) {
             (_, State::Unreachable) => false,
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 858752a3f01..31d5245fb5c 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -878,7 +878,7 @@ struct StorageConflictVisitor<'a, 'tcx> {
 impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, MaybeRequiresStorage<'a, 'tcx>>
     for StorageConflictVisitor<'a, 'tcx>
 {
-    fn visit_statement_before_primary_effect(
+    fn visit_after_early_statement_effect(
         &mut self,
         _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>,
         state: &BitSet<Local>,
@@ -888,7 +888,7 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, MaybeRequiresStorage<'a, 'tcx>>
         self.apply_state(state, loc);
     }
 
-    fn visit_terminator_before_primary_effect(
+    fn visit_after_early_terminator_effect(
         &mut self,
         _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>,
         state: &BitSet<Local>,
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index b94c925b1db..711cf2edc46 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -106,7 +106,7 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> {
         }
     }
 
-    fn apply_statement_effect(
+    fn apply_primary_statement_effect(
         &mut self,
         state: &mut Self::Domain,
         statement: &Statement<'tcx>,
@@ -117,7 +117,7 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> {
         }
     }
 
-    fn apply_terminator_effect<'mir>(
+    fn apply_primary_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
         terminator: &'mir Terminator<'tcx>,
@@ -224,7 +224,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
     }
 
     /// The effect of a successful function call return should not be
-    /// applied here, see [`Analysis::apply_terminator_effect`].
+    /// applied here, see [`Analysis::apply_primary_terminator_effect`].
     fn handle_terminator<'mir>(
         &self,
         terminator: &'mir Terminator<'tcx>,
@@ -954,7 +954,7 @@ fn try_write_constant<'tcx>(
 
 impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> {
     #[instrument(level = "trace", skip(self, results, statement))]
-    fn visit_statement_before_primary_effect(
+    fn visit_after_early_statement_effect(
         &mut self,
         results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
         state: &State<FlatSet<Scalar>>,
@@ -976,7 +976,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collect
     }
 
     #[instrument(level = "trace", skip(self, results, statement))]
-    fn visit_statement_after_primary_effect(
+    fn visit_after_primary_statement_effect(
         &mut self,
         results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
         state: &State<FlatSet<Scalar>>,
@@ -1001,7 +1001,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collect
         }
     }
 
-    fn visit_terminator_before_primary_effect(
+    fn visit_after_early_terminator_effect(
         &mut self,
         results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>,
         state: &State<FlatSet<Scalar>>,
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 0c0f3b61977..3ebc9113725 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -127,7 +127,7 @@ impl InitializationData<'_, '_> {
         self.uninits.seek_before_primary_effect(loc);
     }
 
-    fn maybe_live_dead(&self, path: MovePathIndex) -> (bool, bool) {
+    fn maybe_init_uninit(&self, path: MovePathIndex) -> (bool, bool) {
         (self.inits.get().contains(path), self.uninits.get().contains(path))
     }
 }
@@ -153,23 +153,23 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> {
 
     #[instrument(level = "debug", skip(self), ret)]
     fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle {
-        let ((maybe_live, maybe_dead), multipart) = match mode {
-            DropFlagMode::Shallow => (self.init_data.maybe_live_dead(path), false),
+        let ((maybe_init, maybe_uninit), multipart) = match mode {
+            DropFlagMode::Shallow => (self.init_data.maybe_init_uninit(path), false),
             DropFlagMode::Deep => {
-                let mut some_live = false;
-                let mut some_dead = false;
+                let mut some_maybe_init = false;
+                let mut some_maybe_uninit = false;
                 let mut children_count = 0;
                 on_all_children_bits(self.move_data(), path, |child| {
-                    let (live, dead) = self.init_data.maybe_live_dead(child);
-                    debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead));
-                    some_live |= live;
-                    some_dead |= dead;
+                    let (maybe_init, maybe_uninit) = self.init_data.maybe_init_uninit(child);
+                    debug!("elaborate_drop: state({:?}) = {:?}", child, (maybe_init, maybe_uninit));
+                    some_maybe_init |= maybe_init;
+                    some_maybe_uninit |= maybe_uninit;
                     children_count += 1;
                 });
-                ((some_live, some_dead), children_count != 1)
+                ((some_maybe_init, some_maybe_uninit), children_count != 1)
             }
         };
-        match (maybe_live, maybe_dead, multipart) {
+        match (maybe_init, maybe_uninit, multipart) {
             (false, _, _) => DropStyle::Dead,
             (true, false, _) => DropStyle::Static,
             (true, true, false) => DropStyle::Conditional,
@@ -283,15 +283,15 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
                 LookupResult::Exact(path) => {
                     self.init_data.seek_before(self.body.terminator_loc(bb));
                     on_all_children_bits(self.move_data(), path, |child| {
-                        let (maybe_live, maybe_dead) = self.init_data.maybe_live_dead(child);
+                        let (maybe_init, maybe_uninit) = self.init_data.maybe_init_uninit(child);
                         debug!(
                             "collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}",
                             child,
                             place,
                             path,
-                            (maybe_live, maybe_dead)
+                            (maybe_init, maybe_uninit)
                         );
-                        if maybe_live && maybe_dead {
+                        if maybe_init && maybe_uninit {
                             self.create_drop_flag(child, terminator.source_info.span)
                         }
                     });
@@ -303,8 +303,8 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
                     }
 
                     self.init_data.seek_before(self.body.terminator_loc(bb));
-                    let (_maybe_live, maybe_dead) = self.init_data.maybe_live_dead(parent);
-                    if maybe_dead {
+                    let (_maybe_init, maybe_uninit) = self.init_data.maybe_init_uninit(parent);
+                    if maybe_uninit {
                         self.tcx.dcx().span_delayed_bug(
                             terminator.source_info.span,
                             format!(
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index a6ba2f32d32..adc3374df2e 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -47,7 +47,6 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
                         }
                         ctx.simplify_bool_cmp(rvalue);
                         ctx.simplify_ref_deref(rvalue);
-                        ctx.simplify_len(rvalue);
                         ctx.simplify_ptr_aggregate(rvalue);
                         ctx.simplify_cast(rvalue);
                     }
@@ -132,18 +131,6 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
         }
     }
 
-    /// Transform `Len([_; N])` ==> `N`.
-    fn simplify_len(&self, rvalue: &mut Rvalue<'tcx>) {
-        if let Rvalue::Len(ref place) = *rvalue {
-            let place_ty = place.ty(self.local_decls, self.tcx).ty;
-            if let ty::Array(_, len) = *place_ty.kind() {
-                let const_ = Const::from_ty_const(len, self.tcx.types.usize, self.tcx);
-                let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None };
-                *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
-            }
-        }
-    }
-
     /// Transform `Aggregate(RawPtr, [p, ()])` ==> `Cast(PtrToPtr, p)`.
     fn simplify_ptr_aggregate(&self, rvalue: &mut Rvalue<'tcx>) {
         if let Rvalue::Aggregate(box AggregateKind::RawPtr(pointee_ty, mutability), fields) = rvalue
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index f0fcb44603b..5c090bf7cad 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -189,6 +189,7 @@ declare_passes! {
     mod simplify_comparison_integral : SimplifyComparisonIntegral;
     mod single_use_consts : SingleUseConsts;
     mod sroa : ScalarReplacementOfAggregates;
+    mod strip_debuginfo : StripDebugInfo;
     mod unreachable_enum_branching : UnreachableEnumBranching;
     mod unreachable_prop : UnreachablePropagation;
     mod validate : Validator;
@@ -699,6 +700,8 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &o1(simplify_branches::SimplifyConstCondition::Final),
             &o1(remove_noop_landing_pads::RemoveNoopLandingPads),
             &o1(simplify::SimplifyCfg::Final),
+            // After the last SimplifyCfg, because this wants one-block functions.
+            &strip_debuginfo::StripDebugInfo,
             &copy_prop::CopyProp,
             &dead_store_elimination::DeadStoreElimination::Final,
             &nrvo::RenameReturnPlace,
diff --git a/compiler/rustc_mir_transform/src/strip_debuginfo.rs b/compiler/rustc_mir_transform/src/strip_debuginfo.rs
new file mode 100644
index 00000000000..438c75726bb
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/strip_debuginfo.rs
@@ -0,0 +1,34 @@
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+use rustc_session::config::MirStripDebugInfo;
+
+/// Conditionally remove some of the VarDebugInfo in MIR.
+///
+/// In particular, stripping non-parameter debug info for tiny, primitive-like
+/// methods in core saves work later, and nobody ever wanted to use it anyway.
+pub(super) struct StripDebugInfo;
+
+impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.opts.unstable_opts.mir_strip_debuginfo != MirStripDebugInfo::None
+    }
+
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        match tcx.sess.opts.unstable_opts.mir_strip_debuginfo {
+            MirStripDebugInfo::None => return,
+            MirStripDebugInfo::AllLocals => {}
+            MirStripDebugInfo::LocalsInTinyFunctions
+                if let TerminatorKind::Return { .. } =
+                    body.basic_blocks[START_BLOCK].terminator().kind => {}
+            MirStripDebugInfo::LocalsInTinyFunctions => return,
+        }
+
+        body.var_debug_info.retain(|vdi| {
+            matches!(
+                vdi.value,
+                VarDebugInfoContents::Place(place)
+                    if place.local.as_usize() <= body.arg_count && place.local != RETURN_PLACE,
+            )
+        });
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 404fbb6b839..bce015046e1 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -1115,14 +1115,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         );
                     }
                     UnOp::PtrMetadata => {
-                        if !matches!(self.body.phase, MirPhase::Runtime(_)) {
-                            // It would probably be fine to support this in earlier phases, but at
-                            // the time of writing it's only ever introduced from intrinsic
-                            // lowering or other runtime-phase optimization passes, so earlier
-                            // things can just `bug!` on it.
-                            self.fail(location, "PtrMetadata should be in runtime MIR only");
-                        }
-
                         check_kinds!(
                             a,
                             "Cannot PtrMetadata non-pointer non-reference type {:?}",
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 2426eb81678..443ddfc94ec 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -69,24 +69,30 @@ pub(crate) fn lex_token_trees<'psess, 'src>(
         token: Token::dummy(),
         diag_info: TokenTreeDiagInfo::default(),
     };
-    let (_open_spacing, stream, res) = lexer.lex_token_trees(/* is_delimited */ false);
-    let unmatched_delims = lexer.diag_info.unmatched_delims;
-
-    if res.is_ok() && unmatched_delims.is_empty() {
-        Ok(stream)
-    } else {
-        // Return error if there are unmatched delimiters or unclosed delimiters.
-        // We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch
-        // because the delimiter mismatch is more likely to be the root cause of error
-        let mut buffer: Vec<_> = unmatched_delims
-            .into_iter()
-            .filter_map(|unmatched_delim| make_unclosed_delims_error(unmatched_delim, psess))
-            .collect();
-        if let Err(errs) = res {
-            // Add unclosing delimiter or diff marker errors
-            buffer.extend(errs);
+    let res = lexer.lex_token_trees(/* is_delimited */ false);
+
+    let mut unmatched_delims: Vec<_> = lexer
+        .diag_info
+        .unmatched_delims
+        .into_iter()
+        .filter_map(|unmatched_delim| make_unclosed_delims_error(unmatched_delim, psess))
+        .collect();
+
+    match res {
+        Ok((_open_spacing, stream)) => {
+            if unmatched_delims.is_empty() {
+                Ok(stream)
+            } else {
+                // Return error if there are unmatched delimiters or unclosed delimiters.
+                Err(unmatched_delims)
+            }
+        }
+        Err(errs) => {
+            // We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch
+            // because the delimiter mismatch is more likely to be the root cause of error
+            unmatched_delims.extend(errs);
+            Err(unmatched_delims)
         }
-        Err(buffer)
     }
 }
 
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index ee38f16d4ec..b3f83a32024 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -1,12 +1,10 @@
 use rustc_ast::token::{self, Delimiter, Token};
 use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust::token_to_string;
-use rustc_errors::{Applicability, Diag};
-use rustc_span::symbol::kw;
+use rustc_errors::Diag;
 
 use super::diagnostics::{report_suspicious_mismatch_block, same_indentation_level};
 use super::{Lexer, UnmatchedDelim};
-use crate::Parser;
 
 impl<'psess, 'src> Lexer<'psess, 'src> {
     // Lex into a token stream. The `Spacing` in the result is that of the
@@ -14,7 +12,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
     pub(super) fn lex_token_trees(
         &mut self,
         is_delimited: bool,
-    ) -> (Spacing, TokenStream, Result<(), Vec<Diag<'psess>>>) {
+    ) -> Result<(Spacing, TokenStream), Vec<Diag<'psess>>> {
         // Move past the opening delimiter.
         let open_spacing = self.bump_minimal();
 
@@ -27,25 +25,25 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
                     debug_assert!(!matches!(delim, Delimiter::Invisible(_)));
                     buf.push(match self.lex_token_tree_open_delim(delim) {
                         Ok(val) => val,
-                        Err(errs) => return (open_spacing, TokenStream::new(buf), Err(errs)),
+                        Err(errs) => return Err(errs),
                     })
                 }
                 token::CloseDelim(delim) => {
                     // Invisible delimiters cannot occur here because `TokenTreesReader` parses
                     // code directly from strings, with no macro expansion involved.
                     debug_assert!(!matches!(delim, Delimiter::Invisible(_)));
-                    return (
-                        open_spacing,
-                        TokenStream::new(buf),
-                        if is_delimited { Ok(()) } else { Err(vec![self.close_delim_err(delim)]) },
-                    );
+                    return if is_delimited {
+                        Ok((open_spacing, TokenStream::new(buf)))
+                    } else {
+                        Err(vec![self.close_delim_err(delim)])
+                    };
                 }
                 token::Eof => {
-                    return (
-                        open_spacing,
-                        TokenStream::new(buf),
-                        if is_delimited { Err(vec![self.eof_err()]) } else { Ok(()) },
-                    );
+                    return if is_delimited {
+                        Err(vec![self.eof_err()])
+                    } else {
+                        Ok((open_spacing, TokenStream::new(buf)))
+                    };
                 }
                 _ => {
                     // Get the next normal token.
@@ -107,10 +105,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
         // Lex the token trees within the delimiters.
         // We stop at any delimiter so we can try to recover if the user
         // uses an incorrect delimiter.
-        let (open_spacing, tts, res) = self.lex_token_trees(/* is_delimited */ true);
-        if let Err(errs) = res {
-            return Err(self.unclosed_delim_err(tts, errs));
-        }
+        let (open_spacing, tts) = self.lex_token_trees(/* is_delimited */ true)?;
 
         // Expand to cover the entire delimited token tree.
         let delim_span = DelimSpan::from_pair(pre_span, self.token.span);
@@ -247,67 +242,6 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
         this_spacing
     }
 
-    fn unclosed_delim_err(
-        &mut self,
-        tts: TokenStream,
-        mut errs: Vec<Diag<'psess>>,
-    ) -> Vec<Diag<'psess>> {
-        // If there are unclosed delims, see if there are diff markers and if so, point them
-        // out instead of complaining about the unclosed delims.
-        let mut parser = Parser::new(self.psess, tts, None);
-        let mut diff_errs = vec![];
-        // Suggest removing a `{` we think appears in an `if`/`while` condition.
-        // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition,
-        // but we have no way of tracking this in the lexer itself, so we piggyback on the parser.
-        let mut in_cond = false;
-        while parser.token != token::Eof {
-            if let Err(diff_err) = parser.err_vcs_conflict_marker() {
-                diff_errs.push(diff_err);
-            } else if parser.is_keyword_ahead(0, &[kw::If, kw::While]) {
-                in_cond = true;
-            } else if matches!(
-                parser.token.kind,
-                token::CloseDelim(Delimiter::Brace) | token::FatArrow
-            ) {
-                // End of the `if`/`while` body, or the end of a `match` guard.
-                in_cond = false;
-            } else if in_cond && parser.token == token::OpenDelim(Delimiter::Brace) {
-                // Store the `&&` and `let` to use their spans later when creating the diagnostic
-                let maybe_andand = parser.look_ahead(1, |t| t.clone());
-                let maybe_let = parser.look_ahead(2, |t| t.clone());
-                if maybe_andand == token::OpenDelim(Delimiter::Brace) {
-                    // This might be the beginning of the `if`/`while` body (i.e., the end of the
-                    // condition).
-                    in_cond = false;
-                } else if maybe_andand == token::AndAnd && maybe_let.is_keyword(kw::Let) {
-                    let mut err = parser.dcx().struct_span_err(
-                        parser.token.span,
-                        "found a `{` in the middle of a let-chain",
-                    );
-                    err.span_suggestion(
-                        parser.token.span,
-                        "consider removing this brace to parse the `let` as part of the same chain",
-                        "",
-                        Applicability::MachineApplicable,
-                    );
-                    err.span_label(
-                        maybe_andand.span.to(maybe_let.span),
-                        "you might have meant to continue the let-chain here",
-                    );
-                    errs.push(err);
-                }
-            }
-            parser.bump();
-        }
-        if !diff_errs.is_empty() {
-            for err in errs {
-                err.cancel();
-            }
-            return diff_errs;
-        }
-        errs
-    }
-
     fn close_delim_err(&mut self, delim: Delimiter) -> Diag<'psess> {
         // An unexpected closing delimiter (i.e., there is no matching opening delimiter).
         let token_str = token_to_string(&self.token);
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 44f42e5fbf2..a2136399b0c 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -15,7 +15,7 @@ use rustc_ast::visit::{Visitor, walk_expr};
 use rustc_ast::{
     self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy,
     ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall,
-    MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp,
+    MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind,
 };
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -1931,6 +1931,12 @@ impl<'a> Parser<'a> {
             Ok(match ident.name {
                 sym::offset_of => Some(this.parse_expr_offset_of(lo)?),
                 sym::type_ascribe => Some(this.parse_expr_type_ascribe(lo)?),
+                sym::wrap_binder => {
+                    Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Wrap)?)
+                }
+                sym::unwrap_binder => {
+                    Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Unwrap)?)
+                }
                 _ => None,
             })
         })
@@ -2006,6 +2012,17 @@ impl<'a> Parser<'a> {
         Ok(self.mk_expr(span, ExprKind::Type(expr, ty)))
     }
 
+    pub(crate) fn parse_expr_unsafe_binder_cast(
+        &mut self,
+        lo: Span,
+        kind: UnsafeBinderCastKind,
+    ) -> PResult<'a, P<Expr>> {
+        let expr = self.parse_expr()?;
+        let ty = if self.eat(&TokenKind::Comma) { Some(self.parse_ty()?) } else { None };
+        let span = lo.to(self.token.span);
+        Ok(self.mk_expr(span, ExprKind::UnsafeBinderCast(kind, expr, ty)))
+    }
+
     /// Returns a string literal if the next token is a string literal.
     /// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind,
     /// and returns `None` if the next token is not literal at all.
@@ -4016,7 +4033,9 @@ impl MutVisitor for CondChecker<'_> {
                 mut_visit::walk_expr(self, e);
                 self.forbid_let_reason = forbid_let_reason;
             }
-            ExprKind::Cast(ref mut op, _) | ExprKind::Type(ref mut op, _) => {
+            ExprKind::Cast(ref mut op, _)
+            | ExprKind::Type(ref mut op, _)
+            | ExprKind::UnsafeBinderCast(_, ref mut op, _) => {
                 let forbid_let_reason = self.forbid_let_reason;
                 self.forbid_let_reason = Some(OtherForbidden);
                 self.visit_expr(op);
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 58b4bf8980b..e27fc963eb9 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -45,7 +45,7 @@ impl<'a> Parser<'a> {
             let (inner_attrs, items, inner_span) =
                 self.parse_mod(&token::CloseDelim(Delimiter::Brace))?;
             attrs.extend(inner_attrs);
-            ModKind::Loaded(items, Inline::Yes, inner_span)
+            ModKind::Loaded(items, Inline::Yes, inner_span, Ok(()))
         };
         Ok((id, ItemKind::Mod(safety, mod_kind)))
     }
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 8cff23c2e32..f696074e66a 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -5,7 +5,7 @@ use rustc_ast::{
     self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy,
     GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability,
     Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty,
-    TyKind,
+    TyKind, UnsafeBinderTy,
 };
 use rustc_errors::{Applicability, PResult};
 use rustc_span::symbol::{Ident, kw, sym};
@@ -348,6 +348,10 @@ impl<'a> Parser<'a> {
                     TyKind::Err(guar)
                 }
             }
+        } else if self.check_keyword(kw::Unsafe)
+            && self.look_ahead(1, |tok| matches!(tok.kind, token::Lt))
+        {
+            self.parse_unsafe_binder_ty()?
         } else {
             let msg = format!("expected type, found {}", super::token_descr(&self.token));
             let mut err = self.dcx().struct_span_err(lo, msg);
@@ -369,6 +373,19 @@ impl<'a> Parser<'a> {
         if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
     }
 
+    fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> {
+        let lo = self.token.span;
+        assert!(self.eat_keyword(kw::Unsafe));
+        self.expect_lt()?;
+        let generic_params = self.parse_generic_params()?;
+        self.expect_gt()?;
+        let inner_ty = self.parse_ty()?;
+        let span = lo.to(self.prev_token.span);
+        self.psess.gated_spans.gate(sym::unsafe_binders, span);
+
+        Ok(TyKind::UnsafeBinder(P(UnsafeBinderTy { generic_params, inner_ty })))
+    }
+
     /// Parses either:
     /// - `(TYPE)`, a parenthesized type.
     /// - `(TYPE,)`, a tuple with a single field of type TYPE.
diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs
index 76edb51c0bc..7ccbc7bdc57 100644
--- a/compiler/rustc_passes/src/input_stats.rs
+++ b/compiler/rustc_passes/src/input_stats.rs
@@ -315,9 +315,40 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
 
     fn visit_expr(&mut self, e: &'v hir::Expr<'v>) {
         record_variants!((self, e, e.kind, Some(e.hir_id), hir, Expr, ExprKind), [
-            ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, DropTemps,
-            Let, If, Loop, Match, Closure, Block, Assign, AssignOp, Field, Index, Path, AddrOf,
-            Break, Continue, Ret, Become, InlineAsm, OffsetOf, Struct, Repeat, Yield, Err
+            ConstBlock,
+            Array,
+            Call,
+            MethodCall,
+            Tup,
+            Binary,
+            Unary,
+            Lit,
+            Cast,
+            Type,
+            DropTemps,
+            Let,
+            If,
+            Loop,
+            Match,
+            Closure,
+            Block,
+            Assign,
+            AssignOp,
+            Field,
+            Index,
+            Path,
+            AddrOf,
+            Break,
+            Continue,
+            Ret,
+            Become,
+            InlineAsm,
+            OffsetOf,
+            Struct,
+            Repeat,
+            Yield,
+            UnsafeBinderCast,
+            Err
         ]);
         hir_visit::walk_expr(self, e)
     }
@@ -335,10 +366,12 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
             Ptr,
             Ref,
             BareFn,
+            UnsafeBinder,
             Never,
             Tup,
             Path,
             OpaqueDef,
+            TraitAscription,
             TraitObject,
             Typeof,
             Infer,
@@ -571,7 +604,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
                 If, While, ForLoop, Loop, Match, Closure, Block, Await, TryBlock, Assign,
                 AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret,
                 InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet,
-                Become, IncludedBytes, Gen, Err, Dummy
+                Become, IncludedBytes, Gen, UnsafeBinderCast, Err, Dummy
             ]
         );
         ast_visit::walk_expr(self, e)
@@ -585,6 +618,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
             Ref,
             PinnedRef,
             BareFn,
+            UnsafeBinder,
             Never,
             Tup,
             Path,
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 09cbb648f9b..034f7308c4a 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -447,6 +447,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
             | hir::ExprKind::InlineAsm(..)
             | hir::ExprKind::OffsetOf(..)
             | hir::ExprKind::Type(..)
+            | hir::ExprKind::UnsafeBinderCast(..)
             | hir::ExprKind::Err(_)
             | hir::ExprKind::Path(hir::QPath::TypeRelative(..))
             | hir::ExprKind::Path(hir::QPath::LangItem(..)) => {}
@@ -1051,6 +1052,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             hir::ExprKind::AddrOf(_, _, ref e)
             | hir::ExprKind::Cast(ref e, _)
             | hir::ExprKind::Type(ref e, _)
+            | hir::ExprKind::UnsafeBinderCast(_, ref e, _)
             | hir::ExprKind::DropTemps(ref e)
             | hir::ExprKind::Unary(_, ref e)
             | hir::ExprKind::Repeat(ref e, _) => self.propagate_through_expr(e, succ),
@@ -1443,6 +1445,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
         | hir::ExprKind::Path(_)
         | hir::ExprKind::Yield(..)
         | hir::ExprKind::Type(..)
+        | hir::ExprKind::UnsafeBinderCast(..)
         | hir::ExprKind::Err(_) => {}
     }
 }
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index b2f8d7dadff..766a9e1bdad 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -186,6 +186,7 @@ impl CheckInlineAssembly {
             | ExprKind::Lit(..)
             | ExprKind::Cast(..)
             | ExprKind::Type(..)
+            | ExprKind::UnsafeBinderCast(..)
             | ExprKind::Loop(..)
             | ExprKind::Match(..)
             | ExprKind::If(..)
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index f72f656b2f8..1b12af62ea5 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -349,9 +349,9 @@ pub(crate) fn create_query_frame<
             hasher.finish::<Hash64>()
         })
     };
-    let ty_def_id = key.ty_def_id();
+    let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle();
 
-    QueryStackFrame::new(description, span, def_id, def_kind, kind, ty_def_id, hash)
+    QueryStackFrame::new(description, span, def_id, def_kind, kind, def_id_for_ty_in_cycle, hash)
 }
 
 pub(crate) fn encode_query_results<'a, 'tcx, Q>(
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index b81386f06ec..82c51193a19 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -33,7 +33,7 @@ pub struct QueryStackFrame {
     pub def_id: Option<DefId>,
     pub def_kind: Option<DefKind>,
     /// A def-id that is extracted from a `Ty` in a query key
-    pub ty_def_id: Option<DefId>,
+    pub def_id_for_ty_in_cycle: Option<DefId>,
     pub dep_kind: DepKind,
     /// This hash is used to deterministically pick
     /// a query to remove cycles in the parallel compiler.
@@ -48,10 +48,10 @@ impl QueryStackFrame {
         def_id: Option<DefId>,
         def_kind: Option<DefKind>,
         dep_kind: DepKind,
-        ty_def_id: Option<DefId>,
+        def_id_for_ty_in_cycle: Option<DefId>,
         hash: impl FnOnce() -> Hash64,
     ) -> Self {
-        Self { description, span, def_id, def_kind, ty_def_id, dep_kind, hash: hash() }
+        Self { description, span, def_id, def_kind, def_id_for_ty_in_cycle, dep_kind, hash: hash() }
     }
 
     // FIXME(eddyb) Get more valid `Span`s on queries.
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 293cee500bb..924b8afa329 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -770,7 +770,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 );
             }
 
-            ItemKind::Mod(..) => {
+            ItemKind::Mod(.., ref mod_kind) => {
                 let module = self.r.new_module(
                     Some(parent),
                     ModuleKind::Def(def_kind, def_id, ident.name),
@@ -781,6 +781,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 );
                 self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
 
+                if let ast::ModKind::Loaded(_, _, _, Err(_)) = mod_kind {
+                    self.r.mods_with_parse_errors.insert(def_id);
+                }
+
                 // Descend into the module.
                 self.parent_scope.module = module;
             }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 4c76617a391..368eb3c26c7 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -3056,7 +3056,7 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder {
 
     fn visit_item(&mut self, item: &'tcx ast::Item) {
         if self.target_module == item.id {
-            if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind {
+            if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind {
                 let inject = mod_spans.inject_use_span;
                 if is_span_suitable_for_use_injection(inject) {
                     self.first_legal_span = Some(inject);
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 466e190028a..5906a682f3e 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -1428,6 +1428,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         ignore_import: Option<Import<'ra>>,
     ) -> PathResult<'ra> {
         let mut module = None;
+        let mut module_had_parse_errors = false;
         let mut allow_super = true;
         let mut second_binding = None;
 
@@ -1471,9 +1472,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                             continue;
                         }
                     }
-                    return PathResult::failed(ident, false, finalize.is_some(), module, || {
-                        ("there are too many leading `super` keywords".to_string(), None)
-                    });
+                    return PathResult::failed(
+                        ident,
+                        false,
+                        finalize.is_some(),
+                        module_had_parse_errors,
+                        module,
+                        || ("there are too many leading `super` keywords".to_string(), None),
+                    );
                 }
                 if segment_idx == 0 {
                     if name == kw::SelfLower {
@@ -1511,19 +1517,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
             // Report special messages for path segment keywords in wrong positions.
             if ident.is_path_segment_keyword() && segment_idx != 0 {
-                return PathResult::failed(ident, false, finalize.is_some(), module, || {
-                    let name_str = if name == kw::PathRoot {
-                        "crate root".to_string()
-                    } else {
-                        format!("`{name}`")
-                    };
-                    let label = if segment_idx == 1 && path[0].ident.name == kw::PathRoot {
-                        format!("global paths cannot start with {name_str}")
-                    } else {
-                        format!("{name_str} in paths can only be used in start position")
-                    };
-                    (label, None)
-                });
+                return PathResult::failed(
+                    ident,
+                    false,
+                    finalize.is_some(),
+                    module_had_parse_errors,
+                    module,
+                    || {
+                        let name_str = if name == kw::PathRoot {
+                            "crate root".to_string()
+                        } else {
+                            format!("`{name}`")
+                        };
+                        let label = if segment_idx == 1 && path[0].ident.name == kw::PathRoot {
+                            format!("global paths cannot start with {name_str}")
+                        } else {
+                            format!("{name_str} in paths can only be used in start position")
+                        };
+                        (label, None)
+                    },
+                );
             }
 
             let binding = if let Some(module) = module {
@@ -1589,6 +1602,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
                     let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);
                     if let Some(next_module) = binding.module() {
+                        if self.mods_with_parse_errors.contains(&next_module.def_id()) {
+                            module_had_parse_errors = true;
+                        }
                         module = Some(ModuleOrUniformRoot::Module(next_module));
                         record_segment_res(self, res);
                     } else if res == Res::ToolMod && !is_last && opt_ns.is_some() {
@@ -1614,6 +1630,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                             ident,
                             is_last,
                             finalize.is_some(),
+                            module_had_parse_errors,
                             module,
                             || {
                                 let label = format!(
@@ -1637,19 +1654,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         }
                     }
 
-                    return PathResult::failed(ident, is_last, finalize.is_some(), module, || {
-                        self.report_path_resolution_error(
-                            path,
-                            opt_ns,
-                            parent_scope,
-                            ribs,
-                            ignore_binding,
-                            ignore_import,
-                            module,
-                            segment_idx,
-                            ident,
-                        )
-                    });
+                    return PathResult::failed(
+                        ident,
+                        is_last,
+                        finalize.is_some(),
+                        module_had_parse_errors,
+                        module,
+                        || {
+                            self.report_path_resolution_error(
+                                path,
+                                opt_ns,
+                                parent_scope,
+                                ribs,
+                                ignore_binding,
+                                ignore_import,
+                                module,
+                                segment_idx,
+                                ident,
+                            )
+                        },
+                    );
                 }
             }
         }
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 51fbcb8ebb8..2ed3f4d2c4f 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -670,9 +670,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
     fn throw_unresolved_import_error(
         &mut self,
-        errors: Vec<(Import<'_>, UnresolvedImportError)>,
+        mut errors: Vec<(Import<'_>, UnresolvedImportError)>,
         glob_error: bool,
     ) {
+        errors.retain(|(_import, err)| match err.module {
+            // Skip `use` errors for `use foo::Bar;` if `foo.rs` has unrecovered parse errors.
+            Some(def_id) if self.mods_with_parse_errors.contains(&def_id) => false,
+            _ => true,
+        });
         if errors.is_empty() {
             return;
         }
@@ -898,6 +903,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 label,
                 suggestion,
                 module,
+                error_implied_by_parse_error: _,
             } => {
                 if no_ambiguity {
                     assert!(import.imported_module.get().is_none());
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 789d74876f7..bde11428d40 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -887,6 +887,28 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
                     },
                 )
             }
+            TyKind::UnsafeBinder(unsafe_binder) => {
+                // FIXME(unsafe_binder): Better span
+                let span = ty.span;
+                self.with_generic_param_rib(
+                    &unsafe_binder.generic_params,
+                    RibKind::Normal,
+                    LifetimeRibKind::Generics {
+                        binder: ty.id,
+                        kind: LifetimeBinderKind::BareFnType,
+                        span,
+                    },
+                    |this| {
+                        this.visit_generic_params(&unsafe_binder.generic_params, false);
+                        this.with_lifetime_rib(
+                            // We don't allow anonymous `unsafe &'_ ()` binders,
+                            // although I guess we could.
+                            LifetimeRibKind::AnonymousReportError,
+                            |this| this.visit_ty(&unsafe_binder.inner_ty),
+                        );
+                    },
+                )
+            }
             TyKind::Array(element_ty, length) => {
                 self.visit_ty(element_ty);
                 self.resolve_anon_const(length, AnonConstKind::ConstArg(IsRepeatExpr::No));
@@ -4395,6 +4417,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => {
                 PartialRes::new(module.res().unwrap())
             }
+            // A part of this path references a `mod` that had a parse error. To avoid resolution
+            // errors for each reference to that module, we don't emit an error for them until the
+            // `mod` is fixed. this can have a significant cascade effect.
+            PathResult::Failed { error_implied_by_parse_error: true, .. } => {
+                PartialRes::new(Res::Err)
+            }
             // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we
             // don't report an error right away, but try to fallback to a primitive type.
             // So, we are still able to successfully resolve something like
@@ -4443,6 +4471,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 suggestion,
                 module,
                 segment_name,
+                error_implied_by_parse_error: _,
             } => {
                 return Err(respan(span, ResolutionError::FailedToResolve {
                     segment: Some(segment_name),
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index ca4adce37ce..94adfcd3b91 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -450,6 +450,7 @@ enum PathResult<'ra> {
         module: Option<ModuleOrUniformRoot<'ra>>,
         /// The segment name of target
         segment_name: Symbol,
+        error_implied_by_parse_error: bool,
     },
 }
 
@@ -458,6 +459,7 @@ impl<'ra> PathResult<'ra> {
         ident: Ident,
         is_error_from_last_segment: bool,
         finalize: bool,
+        error_implied_by_parse_error: bool,
         module: Option<ModuleOrUniformRoot<'ra>>,
         label_and_suggestion: impl FnOnce() -> (String, Option<Suggestion>),
     ) -> PathResult<'ra> {
@@ -470,6 +472,7 @@ impl<'ra> PathResult<'ra> {
             suggestion,
             is_error_from_last_segment,
             module,
+            error_implied_by_parse_error,
         }
     }
 }
@@ -1198,6 +1201,8 @@ pub struct Resolver<'ra, 'tcx> {
     /// This is the `Span` where an `extern crate foo;` suggestion would be inserted, if `foo`
     /// could be a crate that wasn't imported. For diagnostics use only.
     current_crate_outer_attr_insert_span: Span,
+
+    mods_with_parse_errors: FxHashSet<DefId>,
 }
 
 /// This provides memory for the rest of the crate. The `'ra` lifetime that is
@@ -1543,6 +1548,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             impl_unexpanded_invocations: Default::default(),
             impl_binding_keys: Default::default(),
             current_crate_outer_attr_insert_span,
+            mods_with_parse_errors: Default::default(),
         };
 
         let root_parent_scope = ParentScope::module(graph_root, &resolver);
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 0b4d0e04c29..669a9c2428f 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -166,7 +166,7 @@ fn soft_custom_inner_attributes_gate(path: &ast::Path, invoc: &Invocation) -> bo
         [seg1, seg2] if seg1.ident.name == sym::rustfmt && seg2.ident.name == sym::skip => {
             if let InvocationKind::Attr { item, .. } = &invoc.kind {
                 if let Annotatable::Item(item) = item {
-                    if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, _)) = item.kind {
+                    if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, _, _)) = item.kind {
                         return true;
                     }
                 }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index cb6d539cdf9..936c2ca87d6 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -472,6 +472,13 @@ impl ToString for DebugInfoCompression {
     }
 }
 
+#[derive(Clone, Copy, Debug, PartialEq, Hash)]
+pub enum MirStripDebugInfo {
+    None,
+    LocalsInTinyFunctions,
+    AllLocals,
+}
+
 /// Split debug-information is enabled by `-C split-debuginfo`, this enum is only used if split
 /// debug-information is enabled (in either `Packed` or `Unpacked` modes), and the platform
 /// uses DWARF for debug-information.
@@ -2900,10 +2907,10 @@ pub(crate) mod dep_tracking {
         BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions,
         CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn,
         InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
-        LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
-        PatchableFunctionEntry, Polonius, RemapPathScopeComponents, ResolveDocLinks,
-        SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
-        WasiExecModel,
+        LtoCli, MirStripDebugInfo, NextSolverConfig, OomStrategy, OptLevel, OutFileName,
+        OutputType, OutputTypes, PatchableFunctionEntry, Polonius, RemapPathScopeComponents,
+        ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath,
+        SymbolManglingVersion, WasiExecModel,
     };
     use crate::lint;
     use crate::utils::NativeLib;
@@ -2971,6 +2978,7 @@ pub(crate) mod dep_tracking {
         LtoCli,
         DebugInfo,
         DebugInfoCompression,
+        MirStripDebugInfo,
         CollapseMacroDebuginfo,
         UnstableFeatures,
         NativeLib,
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index 99d9d5b7665..43cf1324edd 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -371,7 +371,7 @@ impl CheckCfg {
 
         ins!(sym::target_feature, empty_values).extend(
             rustc_target::target_features::all_rust_features()
-                .filter(|(_, s)| s.is_supported())
+                .filter(|(_, s)| s.in_cfg())
                 .map(|(f, _s)| f)
                 .chain(rustc_target::target_features::RUSTC_SPECIFIC_FEATURES.iter().cloned())
                 .map(Symbol::intern),
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index b01d9e5e8e3..3873a203bd3 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -391,6 +391,8 @@ mod desc {
     pub(crate) const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)";
     pub(crate) const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`";
     pub(crate) const parse_debuginfo_compression: &str = "one of `none`, `zlib`, or `zstd`";
+    pub(crate) const parse_mir_strip_debuginfo: &str =
+        "one of `none`, `locals-in-tiny-functions`, or `all-locals`";
     pub(crate) const parse_collapse_macro_debuginfo: &str = "one of `no`, `external`, or `yes`";
     pub(crate) const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
     pub(crate) const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of();
@@ -925,6 +927,16 @@ pub mod parse {
         true
     }
 
+    pub(crate) fn parse_mir_strip_debuginfo(slot: &mut MirStripDebugInfo, v: Option<&str>) -> bool {
+        match v {
+            Some("none") => *slot = MirStripDebugInfo::None,
+            Some("locals-in-tiny-functions") => *slot = MirStripDebugInfo::LocalsInTinyFunctions,
+            Some("all-locals") => *slot = MirStripDebugInfo::AllLocals,
+            _ => return false,
+        };
+        true
+    }
+
     pub(crate) fn parse_linker_flavor(slot: &mut Option<LinkerFlavorCli>, v: Option<&str>) -> bool {
         match v.and_then(LinkerFlavorCli::from_str) {
             Some(lf) => *slot = Some(lf),
@@ -1893,6 +1905,8 @@ options! {
     #[rustc_lint_opt_deny_field_access("use `Session::mir_opt_level` instead of this field")]
     mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
         "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
+    mir_strip_debuginfo: MirStripDebugInfo = (MirStripDebugInfo::None, parse_mir_strip_debuginfo, [TRACKED],
+        "Whether to remove some of the MIR debug info from methods.  Default: None"),
     move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
         "the size at which the `large_assignments` lint starts to be emitted"),
     mutable_noalias: bool = (true, parse_bool, [TRACKED],
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 993d111466b..9f6106f9cfb 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -8,7 +8,6 @@ use std::{env, fmt, io};
 
 use rustc_data_structures::flock;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
-use rustc_data_structures::jobserver::{self, Client};
 use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef};
 use rustc_data_structures::sync::{
     DynSend, DynSync, Lock, Lrc, MappedReadGuard, ReadGuard, RwLock,
@@ -154,16 +153,9 @@ pub struct Session {
     /// Data about code being compiled, gathered during compilation.
     pub code_stats: CodeStats,
 
-    /// Loaded up early on in the initialization of this `Session` to avoid
-    /// false positives about a job server in our environment.
-    pub jobserver: Client,
-
     /// This only ever stores a `LintStore` but we don't want a dependency on that type here.
     pub lint_store: Option<Lrc<dyn LintStoreMarker>>,
 
-    /// Should be set if any lints are registered in `lint_store`.
-    pub registered_lints: bool,
-
     /// Cap lint level specified by a driver specifically.
     pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
 
@@ -1072,9 +1064,7 @@ pub fn build_session(
         incr_comp_session: RwLock::new(IncrCompSession::NotInitialized),
         prof,
         code_stats: Default::default(),
-        jobserver: jobserver::client(),
         lint_store: None,
-        registered_lints: false,
         driver_lint_caps,
         ctfe_backtrace,
         miri_unleashed_features: Lock::new(Default::default()),
diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs
index dec2a77619b..c465367b6b9 100644
--- a/compiler/rustc_smir/src/rustc_internal/internal.rs
+++ b/compiler/rustc_smir/src/rustc_internal/internal.rs
@@ -141,6 +141,10 @@ impl RustcInternal for RigidTy {
             RigidTy::Coroutine(def, args, _mov) => {
                 rustc_ty::TyKind::Coroutine(def.0.internal(tables, tcx), args.internal(tables, tcx))
             }
+            RigidTy::CoroutineClosure(def, args) => rustc_ty::TyKind::CoroutineClosure(
+                def.0.internal(tables, tcx),
+                args.internal(tables, tcx),
+            ),
             RigidTy::CoroutineWitness(def, args) => rustc_ty::TyKind::CoroutineWitness(
                 def.0.internal(tables, tcx),
                 args.internal(tables, tcx),
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 614c9169d66..64d241067a8 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -107,6 +107,10 @@ impl<'tcx> Tables<'tcx> {
         stable_mir::ty::CoroutineDef(self.create_def_id(did))
     }
 
+    pub fn coroutine_closure_def(&mut self, did: DefId) -> stable_mir::ty::CoroutineClosureDef {
+        stable_mir::ty::CoroutineClosureDef(self.create_def_id(did))
+    }
+
     pub fn alias_def(&mut self, did: DefId) -> stable_mir::ty::AliasDef {
         stable_mir::ty::AliasDef(self.create_def_id(did))
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index fcdf8703b14..a5a17b4b573 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -565,8 +565,11 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
                     tables.tcx.coroutine_movability(*def_id).stable(tables),
                 )
             }
-            mir::AggregateKind::CoroutineClosure(..) => {
-                todo!("FIXME(async_closures): Lower these to SMIR")
+            mir::AggregateKind::CoroutineClosure(def_id, generic_args) => {
+                stable_mir::mir::AggregateKind::CoroutineClosure(
+                    tables.coroutine_closure_def(*def_id),
+                    generic_args.stable(tables),
+                )
             }
             mir::AggregateKind::RawPtr(ty, mutability) => {
                 stable_mir::mir::AggregateKind::RawPtr(ty.stable(tables), mutability.stable(tables))
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index a5826137181..3cdae437b7d 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1163,6 +1163,9 @@ pub enum DesugaringKind {
     WhileLoop,
     /// `async Fn()` bound modifier
     BoundModifier,
+    /// Marks a `&raw const *_1` needed as part of getting the length of a mutable
+    /// slice for the bounds check, so that MIRI's retag handling can recognize it.
+    IndexBoundsCheckReborrow,
 }
 
 impl DesugaringKind {
@@ -1179,6 +1182,7 @@ impl DesugaringKind {
             DesugaringKind::ForLoop => "`for` loop",
             DesugaringKind::WhileLoop => "`while` loop",
             DesugaringKind::BoundModifier => "trait bound modifier",
+            DesugaringKind::IndexBoundsCheckReborrow => "slice indexing",
         }
     }
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9b499c71603..e3708896ba9 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -2105,6 +2105,7 @@ symbols! {
         unreachable_macro,
         unrestricted_attribute_tokens,
         unsafe_attributes,
+        unsafe_binders,
         unsafe_block_in_unsafe_fn,
         unsafe_cell,
         unsafe_cell_raw_get,
@@ -2128,6 +2129,7 @@ symbols! {
         unwind_attributes,
         unwind_safe_trait,
         unwrap,
+        unwrap_binder,
         unwrap_or,
         use_extern_macros,
         use_nested_groups,
@@ -2186,6 +2188,7 @@ symbols! {
         windows,
         windows_subsystem,
         with_negative_coherence,
+        wrap_binder,
         wrapping_add,
         wrapping_div,
         wrapping_mul,
@@ -2201,6 +2204,7 @@ symbols! {
         writeln_macro,
         x86_amx_intrinsics,
         x87_reg,
+        x87_target_feature,
         xer,
         xmm_reg,
         xop_target_feature,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 59ccd6dff85..0d6d8488a23 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -2,7 +2,7 @@ use std::fmt::{self, Write};
 use std::mem::{self, discriminant};
 
 use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
-use rustc_hir::def_id::CrateNum;
+use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
 use rustc_middle::bug;
 use rustc_middle::ty::print::{PrettyPrinter, Print, PrintError, Printer};
@@ -378,6 +378,33 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
             Ok(())
         }
     }
+
+    fn print_impl_path(
+        &mut self,
+        impl_def_id: DefId,
+        args: &'tcx [GenericArg<'tcx>],
+        mut self_ty: Ty<'tcx>,
+        mut impl_trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Result<(), PrintError> {
+        let mut typing_env = ty::TypingEnv::post_analysis(self.tcx, impl_def_id);
+        if !args.is_empty() {
+            typing_env.param_env =
+                ty::EarlyBinder::bind(typing_env.param_env).instantiate(self.tcx, args);
+        }
+
+        match &mut impl_trait_ref {
+            Some(impl_trait_ref) => {
+                assert_eq!(impl_trait_ref.self_ty(), self_ty);
+                *impl_trait_ref = self.tcx.normalize_erasing_regions(typing_env, *impl_trait_ref);
+                self_ty = impl_trait_ref.self_ty();
+            }
+            None => {
+                self_ty = self.tcx.normalize_erasing_regions(typing_env, self_ty);
+            }
+        }
+
+        self.default_print_impl_path(impl_def_id, args, self_ty, impl_trait_ref)
+    }
 }
 
 impl<'tcx> PrettyPrinter<'tcx> for SymbolPrinter<'tcx> {
diff --git a/compiler/rustc_target/src/callconv/powerpc64.rs b/compiler/rustc_target/src/callconv/powerpc64.rs
index 71e533b8cc5..3a71592cbe0 100644
--- a/compiler/rustc_target/src/callconv/powerpc64.rs
+++ b/compiler/rustc_target/src/callconv/powerpc64.rs
@@ -99,7 +99,7 @@ where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout + HasTargetSpec,
 {
-    let abi = if cx.target_spec().env == "musl" {
+    let abi = if cx.target_spec().env == "musl" || cx.target_spec().os == "freebsd" {
         ELFv2
     } else if cx.target_spec().os == "aix" {
         AIX
diff --git a/compiler/rustc_target/src/spec/base/linux_musl.rs b/compiler/rustc_target/src/spec/base/linux_musl.rs
index e020bb85238..1a854fe362d 100644
--- a/compiler/rustc_target/src/spec/base/linux_musl.rs
+++ b/compiler/rustc_target/src/spec/base/linux_musl.rs
@@ -8,8 +8,5 @@ pub(crate) fn opts() -> TargetOptions {
     base.post_link_objects_self_contained = crt_objects::post_musl_self_contained();
     base.link_self_contained = LinkSelfContainedDefault::InferredForMusl;
 
-    // These targets statically link libc by default
-    base.crt_static_default = true;
-
     base
 }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 210d67fa1aa..7d308c6c662 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2603,6 +2603,18 @@ impl TargetOptions {
                 .collect();
         }
     }
+
+    pub(crate) fn has_feature(&self, search_feature: &str) -> bool {
+        self.features.split(',').any(|f| {
+            if let Some(f) = f.strip_prefix('+')
+                && f == search_feature
+            {
+                true
+            } else {
+                false
+            }
+        })
+    }
 }
 
 impl Default for TargetOptions {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
index bb65048a56d..4fefdfa5c5e 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
@@ -12,6 +12,9 @@ pub(crate) fn target() -> Target {
         | SanitizerSet::MEMORY
         | SanitizerSet::THREAD;
 
+    // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+    base.crt_static_default = true;
+
     Target {
         llvm_target: "aarch64-unknown-linux-musl".into(),
         metadata: crate::spec::TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs
index b96d8455a5b..416bb5432fd 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs
@@ -22,6 +22,8 @@ pub(crate) fn target() -> Target {
             features: "+strict-align,+v6".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}mcount".into(),
+            // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+            crt_static_default: true,
             ..base::linux_musl::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs
index 3418a7090d3..909eb78f698 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs
@@ -22,6 +22,8 @@ pub(crate) fn target() -> Target {
             features: "+strict-align,+v6,+vfp2,-d32".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}mcount".into(),
+            // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+            crt_static_default: true,
             ..base::linux_musl::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs
index 1bcd090b9f2..5e3ad42e5a4 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs
@@ -23,6 +23,8 @@ pub(crate) fn target() -> Target {
             max_atomic_width: Some(32),
             mcount: "\u{1}mcount".into(),
             has_thumb_interworking: true,
+            // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+            crt_static_default: true,
             ..base::linux_musl::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs
index 16923497325..843adcfc711 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs
@@ -26,6 +26,8 @@ pub(crate) fn target() -> Target {
             features: "+v7,+thumb2,+soft-float,-neon".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}mcount".into(),
+            // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+            crt_static_default: true,
             ..base::linux_musl::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs
index 5adfa0bc2f8..e0630817bc3 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs
@@ -25,6 +25,8 @@ pub(crate) fn target() -> Target {
             features: "+v7,+vfp3,-d32,+thumb2,-neon".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}mcount".into(),
+            // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+            crt_static_default: true,
             ..base::linux_musl::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs
index 623422a89ea..8ad93496f3a 100644
--- a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs
@@ -4,5 +4,7 @@ pub(crate) fn target() -> Target {
     let mut base = super::i686_unknown_linux_musl::target();
     base.cpu = "pentium".into();
     base.llvm_target = "i586-unknown-linux-musl".into();
+    // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+    base.crt_static_default = true;
     base
 }
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
index b805b80b85b..6ba87c732b7 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
@@ -6,6 +6,8 @@ pub(crate) fn target() -> Target {
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-melf_i386"]);
     base.stack_probes = StackProbeType::Inline;
+    // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+    base.crt_static_default = true;
 
     // The unwinder used by i686-unknown-linux-musl, the LLVM libunwind
     // implementation, apparently relies on frame pointers existing... somehow.
diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
index cc288e042d9..bddcc457498 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
@@ -8,7 +8,6 @@ pub(crate) fn target() -> Target {
     base.cpu = "mips64r2".into();
     base.features = "+mips64r2,+soft-float".into();
     base.max_atomic_width = Some(64);
-    base.crt_static_default = false;
 
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
index 69af2da1100..32f5c79d653 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
@@ -22,6 +22,8 @@ pub(crate) fn target() -> Target {
             abi: "abi64".into(),
             endian: Endian::Big,
             mcount: "_mcount".into(),
+            // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+            crt_static_default: true,
             ..base
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
index 4f50e8b7033..5e7c37fd46c 100644
--- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
@@ -5,6 +5,8 @@ pub(crate) fn target() -> Target {
     base.cpu = "mips64r2".into();
     base.features = "+mips64r2".into();
     base.max_atomic_width = Some(64);
+    // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+    base.crt_static_default = true;
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
         llvm_target: "mips64el-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs
index b283b3b1ef7..5076ae345a9 100644
--- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs
@@ -6,7 +6,6 @@ pub(crate) fn target() -> Target {
     base.cpu = "mips32r2".into();
     base.features = "+mips32r2,+soft-float".into();
     base.max_atomic_width = Some(32);
-    base.crt_static_default = false;
     Target {
         llvm_target: "mips-unknown-linux-musl".into(),
         metadata: crate::spec::TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs
index 744396aa1ba..339b32b6339 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs
@@ -5,7 +5,6 @@ pub(crate) fn target() -> Target {
     base.cpu = "mips32r2".into();
     base.features = "+mips32r2,+soft-float".into();
     base.max_atomic_width = Some(32);
-    base.crt_static_default = false;
     Target {
         llvm_target: "mipsel-unknown-linux-musl".into(),
         metadata: crate::spec::TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
index 68a3718035c..4ccb3ee4664 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
@@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target: "powerpc64-unknown-freebsd".into(),
         metadata: crate::spec::TargetMetadata {
-            description: Some("PPC64 FreeBSD (ELFv1 and ELFv2)".into()),
+            description: Some("PPC64 FreeBSD (ELFv2)".into()),
             tier: Some(3),
             host_tools: Some(true),
             std: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
index a964f417799..a54b17c87a7 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
@@ -7,6 +7,8 @@ pub(crate) fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::Inline;
+    // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+    base.crt_static_default = true;
 
     Target {
         llvm_target: "powerpc64-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
index 04fe5f9af33..952a00c52a2 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
@@ -6,6 +6,8 @@ pub(crate) fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::Inline;
+    // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+    base.crt_static_default = true;
 
     Target {
         llvm_target: "powerpc64le-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs
index 5372a83e29a..0cd0ea96ad3 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs
@@ -6,6 +6,8 @@ pub(crate) fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
     base.max_atomic_width = Some(32);
     base.stack_probes = StackProbeType::Inline;
+    // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+    base.crt_static_default = true;
 
     Target {
         llvm_target: "powerpc-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs
index 2305db81c5e..b86c3c2e8e0 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs
@@ -6,6 +6,8 @@ pub(crate) fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mspe"]);
     base.max_atomic_width = Some(32);
     base.stack_probes = StackProbeType::Inline;
+    // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+    base.crt_static_default = true;
 
     Target {
         llvm_target: "powerpc-unknown-linux-muslspe".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
index 08871d9d72b..a07429bb0c5 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
@@ -23,6 +23,8 @@ pub(crate) fn target() -> Target {
             llvm_abiname: "ilp32d".into(),
             max_atomic_width: Some(32),
             supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
+            // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+            crt_static_default: true,
             ..base::linux_musl::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
index 397c202ec1a..0a4cc3b8be6 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
@@ -21,7 +21,6 @@ pub(crate) fn target() -> Target {
             llvm_abiname: "lp64d".into(),
             max_atomic_width: Some(64),
             supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
-            crt_static_default: false,
             ..base::linux_musl::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs
index 7a78004927b..fbe8c48eca7 100644
--- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs
@@ -12,6 +12,8 @@ pub(crate) fn target() -> Target {
     base.stack_probes = StackProbeType::Inline;
     base.supported_sanitizers =
         SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD;
+    // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+    base.crt_static_default = true;
 
     Target {
         llvm_target: "s390x-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
index fdc9628f78e..770da60da9e 100644
--- a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target: "sparcv9-sun-solaris".into(),
         metadata: crate::spec::TargetMetadata {
-            description: Some("SPARC Solaris 11, illumos".into()),
+            description: Some("SPARC Solaris 11.4".into()),
             tier: Some(2),
             host_tools: Some(false),
             std: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs
index 2f539f4f600..a0852b4611e 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs
@@ -29,6 +29,8 @@ pub(crate) fn target() -> Target {
             features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}mcount".into(),
+            // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+            crt_static_default: true,
             ..base::linux_musl::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
index 28dd3c426c7..843568a4792 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target: "x86_64-pc-solaris".into(),
         metadata: crate::spec::TargetMetadata {
-            description: Some("64-bit Solaris 11, illumos".into()),
+            description: Some("64-bit Solaris 11.4".into()),
             tier: Some(2),
             host_tools: Some(false),
             std: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
index 8be0f335db9..8dcdc5be8a9 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
@@ -14,6 +14,8 @@ pub(crate) fn target() -> Target {
         | SanitizerSet::MEMORY
         | SanitizerSet::THREAD;
     base.supports_xray = true;
+    // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
+    base.crt_static_default = true;
 
     Target {
         llvm_target: "x86_64-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index c89045c93e3..29d3f826a15 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -5,6 +5,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_span::symbol::{Symbol, sym};
 
+use crate::spec::Target;
+
 /// Features that control behaviour of rustc, rather than the codegen.
 /// These exist globally and are not in the target-specific lists below.
 pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
@@ -15,45 +17,115 @@ pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
 pub const RUSTC_SPECIAL_FEATURES: &[&str] = &["backchain"];
 
 /// Stability information for target features.
+/// `Toggleability` is the type storing whether (un)stable features can be toggled:
+/// this is initially a function since it can depend on `Target`, but for stable hashing
+/// it needs to be something hashable to we have to make the type generic.
 #[derive(Debug, Clone, Copy)]
-pub enum Stability {
+pub enum Stability<Toggleability> {
     /// This target feature is stable, it can be used in `#[target_feature]` and
     /// `#[cfg(target_feature)]`.
-    Stable,
-    /// This target feature is unstable; using it in `#[target_feature]` or `#[cfg(target_feature)]`
-    /// requires enabling the given nightly feature.
-    Unstable(Symbol),
-    /// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be set in the basic
-    /// target definition. Used in particular for features that change the floating-point ABI.
+    Stable {
+        /// When enabling/disabling the feature via `-Ctarget-feature` or `#[target_feature]`,
+        /// determine if that is allowed.
+        allow_toggle: Toggleability,
+    },
+    /// This target feature is unstable. It is only present in `#[cfg(target_feature)]` on
+    /// nightly and using it in `#[target_feature]` requires enabling the given nightly feature.
+    Unstable {
+        /// This must be a *language* feature, or else rustc will ICE when reporting a missing
+        /// feature gate!
+        nightly_feature: Symbol,
+        /// See `Stable::allow_toggle` comment above.
+        allow_toggle: Toggleability,
+    },
+    /// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be
+    /// set in the basic target definition. It is never set in `cfg(target_feature)`. Used in
+    /// particular for features that change the floating-point ABI.
     Forbidden { reason: &'static str },
 }
-use Stability::*;
 
-impl<CTX> HashStable<CTX> for Stability {
+/// `Stability` where `allow_toggle` has not been computed yet.
+/// Returns `Ok` if the toggle is allowed, `Err` with an explanation of not.
+pub type StabilityUncomputed = Stability<fn(&Target) -> Result<(), &'static str>>;
+/// `Stability` where `allow_toggle` has already been computed.
+pub type StabilityComputed = Stability<Result<(), &'static str>>;
+
+impl<CTX, Toggleability: HashStable<CTX>> HashStable<CTX> for Stability<Toggleability> {
     #[inline]
     fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
         std::mem::discriminant(self).hash_stable(hcx, hasher);
         match self {
-            Stable => {}
-            Unstable(sym) => {
-                sym.hash_stable(hcx, hasher);
+            Stability::Stable { allow_toggle } => {
+                allow_toggle.hash_stable(hcx, hasher);
+            }
+            Stability::Unstable { nightly_feature, allow_toggle } => {
+                nightly_feature.hash_stable(hcx, hasher);
+                allow_toggle.hash_stable(hcx, hasher);
             }
-            Forbidden { .. } => {}
+            Stability::Forbidden { reason } => {
+                reason.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
+
+impl<Toggleability> Stability<Toggleability> {
+    /// Returns whether the feature can be used in `cfg(target_feature)` ever.
+    /// (It might still be nightly-only even if this returns `true`, so make sure to also check
+    /// `requires_nightly`.)
+    pub fn in_cfg(self) -> bool {
+        !matches!(self, Stability::Forbidden { .. })
+    }
+
+    /// Returns the nightly feature that is required to toggle this target feature via
+    /// `#[target_feature]`/`-Ctarget-feature` or to test it via `cfg(target_feature)`.
+    /// (For `cfg` we only care whether the feature is nightly or not, we don't require
+    /// the feature gate to actually be enabled when using a nightly compiler.)
+    ///
+    /// Before calling this, ensure the feature is even permitted for this use:
+    /// - for `#[target_feature]`/`-Ctarget-feature`, check `allow_toggle()`
+    /// - for `cfg(target_feature)`, check `in_cfg`
+    pub fn requires_nightly(self) -> Option<Symbol> {
+        match self {
+            Stability::Unstable { nightly_feature, .. } => Some(nightly_feature),
+            Stability::Stable { .. } => None,
+            Stability::Forbidden { .. } => panic!("forbidden features should not reach this far"),
         }
     }
 }
 
-impl Stability {
-    pub fn is_stable(self) -> bool {
-        matches!(self, Stable)
+impl StabilityUncomputed {
+    pub fn compute_toggleability(self, target: &Target) -> StabilityComputed {
+        use Stability::*;
+        match self {
+            Stable { allow_toggle } => Stable { allow_toggle: allow_toggle(target) },
+            Unstable { nightly_feature, allow_toggle } => {
+                Unstable { nightly_feature, allow_toggle: allow_toggle(target) }
+            }
+            Forbidden { reason } => Forbidden { reason },
+        }
     }
+}
 
-    /// Forbidden features are not supported.
-    pub fn is_supported(self) -> bool {
-        !matches!(self, Forbidden { .. })
+impl StabilityComputed {
+    /// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`.
+    /// (It might still be nightly-only even if this returns `true`, so make sure to also check
+    /// `requires_nightly`.)
+    pub fn allow_toggle(self) -> Result<(), &'static str> {
+        match self {
+            Stability::Stable { allow_toggle } => allow_toggle,
+            Stability::Unstable { allow_toggle, .. } => allow_toggle,
+            Stability::Forbidden { reason } => Err(reason),
+        }
     }
 }
 
+// Constructors for the list below, defaulting to "always allow toggle".
+const STABLE: StabilityUncomputed = Stability::Stable { allow_toggle: |_target| Ok(()) };
+const fn unstable(nightly_feature: Symbol) -> StabilityUncomputed {
+    Stability::Unstable { nightly_feature, allow_toggle: |_target| Ok(()) }
+}
+
 // Here we list target features that rustc "understands": they can be used in `#[target_feature]`
 // and `#[cfg(target_feature)]`. They also do not trigger any warnings when used with
 // `-Ctarget-feature`.
@@ -99,181 +171,196 @@ impl Stability {
 // Both of these are also applied transitively.
 type ImpliedFeatures = &'static [&'static str];
 
-const ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const ARM_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
-    ("aclass", Unstable(sym::arm_target_feature), &[]),
-    ("aes", Unstable(sym::arm_target_feature), &["neon"]),
-    ("crc", Unstable(sym::arm_target_feature), &[]),
-    ("d32", Unstable(sym::arm_target_feature), &[]),
-    ("dotprod", Unstable(sym::arm_target_feature), &["neon"]),
-    ("dsp", Unstable(sym::arm_target_feature), &[]),
-    ("fp-armv8", Unstable(sym::arm_target_feature), &["vfp4"]),
-    ("i8mm", Unstable(sym::arm_target_feature), &["neon"]),
-    ("mclass", Unstable(sym::arm_target_feature), &[]),
-    ("neon", Unstable(sym::arm_target_feature), &["vfp3"]),
-    ("rclass", Unstable(sym::arm_target_feature), &[]),
-    ("sha2", Unstable(sym::arm_target_feature), &["neon"]),
-    ("soft-float", Forbidden { reason: "unsound because it changes float ABI" }, &[]),
+    ("aclass", unstable(sym::arm_target_feature), &[]),
+    ("aes", unstable(sym::arm_target_feature), &["neon"]),
+    ("crc", unstable(sym::arm_target_feature), &[]),
+    ("d32", unstable(sym::arm_target_feature), &[]),
+    ("dotprod", unstable(sym::arm_target_feature), &["neon"]),
+    ("dsp", unstable(sym::arm_target_feature), &[]),
+    ("fp-armv8", unstable(sym::arm_target_feature), &["vfp4"]),
+    (
+        "fpregs",
+        Stability::Unstable {
+            nightly_feature: sym::arm_target_feature,
+            allow_toggle: |target: &Target| {
+                // Only allow toggling this if the target has `soft-float` set. With `soft-float`,
+                // `fpregs` isn't needed so changing it cannot affect the ABI.
+                if target.has_feature("soft-float") {
+                    Ok(())
+                } else {
+                    Err("unsound on hard-float targets because it changes float ABI")
+                }
+            },
+        },
+        &[],
+    ),
+    ("i8mm", unstable(sym::arm_target_feature), &["neon"]),
+    ("mclass", unstable(sym::arm_target_feature), &[]),
+    ("neon", unstable(sym::arm_target_feature), &["vfp3"]),
+    ("rclass", unstable(sym::arm_target_feature), &[]),
+    ("sha2", unstable(sym::arm_target_feature), &["neon"]),
+    ("soft-float", Stability::Forbidden { reason: "unsound because it changes float ABI" }, &[]),
     // This is needed for inline assembly, but shouldn't be stabilized as-is
     // since it should be enabled per-function using #[instruction_set], not
     // #[target_feature].
-    ("thumb-mode", Unstable(sym::arm_target_feature), &[]),
-    ("thumb2", Unstable(sym::arm_target_feature), &[]),
-    ("trustzone", Unstable(sym::arm_target_feature), &[]),
-    ("v5te", Unstable(sym::arm_target_feature), &[]),
-    ("v6", Unstable(sym::arm_target_feature), &["v5te"]),
-    ("v6k", Unstable(sym::arm_target_feature), &["v6"]),
-    ("v6t2", Unstable(sym::arm_target_feature), &["v6k", "thumb2"]),
-    ("v7", Unstable(sym::arm_target_feature), &["v6t2"]),
-    ("v8", Unstable(sym::arm_target_feature), &["v7"]),
-    ("vfp2", Unstable(sym::arm_target_feature), &[]),
-    ("vfp3", Unstable(sym::arm_target_feature), &["vfp2", "d32"]),
-    ("vfp4", Unstable(sym::arm_target_feature), &["vfp3"]),
-    ("virtualization", Unstable(sym::arm_target_feature), &[]),
+    ("thumb-mode", unstable(sym::arm_target_feature), &[]),
+    ("thumb2", unstable(sym::arm_target_feature), &[]),
+    ("trustzone", unstable(sym::arm_target_feature), &[]),
+    ("v5te", unstable(sym::arm_target_feature), &[]),
+    ("v6", unstable(sym::arm_target_feature), &["v5te"]),
+    ("v6k", unstable(sym::arm_target_feature), &["v6"]),
+    ("v6t2", unstable(sym::arm_target_feature), &["v6k", "thumb2"]),
+    ("v7", unstable(sym::arm_target_feature), &["v6t2"]),
+    ("v8", unstable(sym::arm_target_feature), &["v7"]),
+    ("vfp2", unstable(sym::arm_target_feature), &[]),
+    ("vfp3", unstable(sym::arm_target_feature), &["vfp2", "d32"]),
+    ("vfp4", unstable(sym::arm_target_feature), &["vfp3"]),
+    ("virtualization", unstable(sym::arm_target_feature), &[]),
     // tidy-alphabetical-end
-    // FIXME: need to also forbid turning off `fpregs` on hardfloat targets
 ];
 
-const AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const AARCH64_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     // FEAT_AES & FEAT_PMULL
-    ("aes", Stable, &["neon"]),
+    ("aes", STABLE, &["neon"]),
     // FEAT_BF16
-    ("bf16", Stable, &[]),
+    ("bf16", STABLE, &[]),
     // FEAT_BTI
-    ("bti", Stable, &[]),
+    ("bti", STABLE, &[]),
     // FEAT_CRC
-    ("crc", Stable, &[]),
+    ("crc", STABLE, &[]),
     // FEAT_CSSC
-    ("cssc", Unstable(sym::aarch64_unstable_target_feature), &[]),
+    ("cssc", unstable(sym::aarch64_unstable_target_feature), &[]),
     // FEAT_DIT
-    ("dit", Stable, &[]),
+    ("dit", STABLE, &[]),
     // FEAT_DotProd
-    ("dotprod", Stable, &["neon"]),
+    ("dotprod", STABLE, &["neon"]),
     // FEAT_DPB
-    ("dpb", Stable, &[]),
+    ("dpb", STABLE, &[]),
     // FEAT_DPB2
-    ("dpb2", Stable, &["dpb"]),
+    ("dpb2", STABLE, &["dpb"]),
     // FEAT_ECV
-    ("ecv", Unstable(sym::aarch64_unstable_target_feature), &[]),
+    ("ecv", unstable(sym::aarch64_unstable_target_feature), &[]),
     // FEAT_F32MM
-    ("f32mm", Stable, &["sve"]),
+    ("f32mm", STABLE, &["sve"]),
     // FEAT_F64MM
-    ("f64mm", Stable, &["sve"]),
+    ("f64mm", STABLE, &["sve"]),
     // FEAT_FAMINMAX
-    ("faminmax", Unstable(sym::aarch64_unstable_target_feature), &[]),
+    ("faminmax", unstable(sym::aarch64_unstable_target_feature), &[]),
     // FEAT_FCMA
-    ("fcma", Stable, &["neon"]),
+    ("fcma", STABLE, &["neon"]),
     // FEAT_FHM
-    ("fhm", Stable, &["fp16"]),
+    ("fhm", STABLE, &["fp16"]),
     // FEAT_FLAGM
-    ("flagm", Stable, &[]),
+    ("flagm", STABLE, &[]),
     // FEAT_FLAGM2
-    ("flagm2", Unstable(sym::aarch64_unstable_target_feature), &[]),
+    ("flagm2", unstable(sym::aarch64_unstable_target_feature), &[]),
     // FEAT_FP16
     // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608
-    ("fp16", Stable, &["neon"]),
+    ("fp16", STABLE, &["neon"]),
     // FEAT_FP8
-    ("fp8", Unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]),
+    ("fp8", unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]),
     // FEAT_FP8DOT2
-    ("fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["fp8dot4"]),
+    ("fp8dot2", unstable(sym::aarch64_unstable_target_feature), &["fp8dot4"]),
     // FEAT_FP8DOT4
-    ("fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["fp8fma"]),
+    ("fp8dot4", unstable(sym::aarch64_unstable_target_feature), &["fp8fma"]),
     // FEAT_FP8FMA
-    ("fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["fp8"]),
+    ("fp8fma", unstable(sym::aarch64_unstable_target_feature), &["fp8"]),
     // FEAT_FRINTTS
-    ("frintts", Stable, &[]),
+    ("frintts", STABLE, &[]),
     // FEAT_HBC
-    ("hbc", Unstable(sym::aarch64_unstable_target_feature), &[]),
+    ("hbc", unstable(sym::aarch64_unstable_target_feature), &[]),
     // FEAT_I8MM
-    ("i8mm", Stable, &[]),
+    ("i8mm", STABLE, &[]),
     // FEAT_JSCVT
     // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608
-    ("jsconv", Stable, &["neon"]),
+    ("jsconv", STABLE, &["neon"]),
     // FEAT_LOR
-    ("lor", Stable, &[]),
+    ("lor", STABLE, &[]),
     // FEAT_LSE
-    ("lse", Stable, &[]),
+    ("lse", STABLE, &[]),
     // FEAT_LSE128
-    ("lse128", Unstable(sym::aarch64_unstable_target_feature), &["lse"]),
+    ("lse128", unstable(sym::aarch64_unstable_target_feature), &["lse"]),
     // FEAT_LSE2
-    ("lse2", Unstable(sym::aarch64_unstable_target_feature), &[]),
+    ("lse2", unstable(sym::aarch64_unstable_target_feature), &[]),
     // FEAT_LUT
-    ("lut", Unstable(sym::aarch64_unstable_target_feature), &[]),
+    ("lut", unstable(sym::aarch64_unstable_target_feature), &[]),
     // FEAT_MOPS
-    ("mops", Unstable(sym::aarch64_unstable_target_feature), &[]),
+    ("mops", unstable(sym::aarch64_unstable_target_feature), &[]),
     // FEAT_MTE & FEAT_MTE2
-    ("mte", Stable, &[]),
+    ("mte", STABLE, &[]),
     // FEAT_AdvSimd & FEAT_FP
-    ("neon", Stable, &[]),
+    ("neon", STABLE, &[]),
     // FEAT_PAUTH (address authentication)
-    ("paca", Stable, &[]),
+    ("paca", STABLE, &[]),
     // FEAT_PAUTH (generic authentication)
-    ("pacg", Stable, &[]),
+    ("pacg", STABLE, &[]),
     // FEAT_PAN
-    ("pan", Stable, &[]),
+    ("pan", STABLE, &[]),
     // FEAT_PAuth_LR
-    ("pauth-lr", Unstable(sym::aarch64_unstable_target_feature), &[]),
+    ("pauth-lr", unstable(sym::aarch64_unstable_target_feature), &[]),
     // FEAT_PMUv3
-    ("pmuv3", Stable, &[]),
+    ("pmuv3", STABLE, &[]),
     // FEAT_RNG
-    ("rand", Stable, &[]),
+    ("rand", STABLE, &[]),
     // FEAT_RAS & FEAT_RASv1p1
-    ("ras", Stable, &[]),
+    ("ras", STABLE, &[]),
     // FEAT_LRCPC
-    ("rcpc", Stable, &[]),
+    ("rcpc", STABLE, &[]),
     // FEAT_LRCPC2
-    ("rcpc2", Stable, &["rcpc"]),
+    ("rcpc2", STABLE, &["rcpc"]),
     // FEAT_LRCPC3
-    ("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]),
+    ("rcpc3", unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]),
     // FEAT_RDM
-    ("rdm", Stable, &["neon"]),
+    ("rdm", STABLE, &["neon"]),
     // This is needed for inline assembly, but shouldn't be stabilized as-is
     // since it should be enabled globally using -Zfixed-x18, not
     // #[target_feature].
     // Note that cfg(target_feature = "reserve-x18") is currently not set for
     // targets that reserve x18 by default.
-    ("reserve-x18", Unstable(sym::aarch64_unstable_target_feature), &[]),
+    ("reserve-x18", unstable(sym::aarch64_unstable_target_feature), &[]),
     // FEAT_SB
-    ("sb", Stable, &[]),
+    ("sb", STABLE, &[]),
     // FEAT_SHA1 & FEAT_SHA256
-    ("sha2", Stable, &["neon"]),
+    ("sha2", STABLE, &["neon"]),
     // FEAT_SHA512 & FEAT_SHA3
-    ("sha3", Stable, &["sha2"]),
+    ("sha3", STABLE, &["sha2"]),
     // FEAT_SM3 & FEAT_SM4
-    ("sm4", Stable, &["neon"]),
+    ("sm4", STABLE, &["neon"]),
     // FEAT_SME
-    ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]),
+    ("sme", unstable(sym::aarch64_unstable_target_feature), &["bf16"]),
     // FEAT_SME_B16B16
-    ("sme-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16", "sme2", "sve-b16b16"]),
+    ("sme-b16b16", unstable(sym::aarch64_unstable_target_feature), &["bf16", "sme2", "sve-b16b16"]),
     // FEAT_SME_F16F16
-    ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]),
+    ("sme-f16f16", unstable(sym::aarch64_unstable_target_feature), &["sme2"]),
     // FEAT_SME_F64F64
-    ("sme-f64f64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]),
+    ("sme-f64f64", unstable(sym::aarch64_unstable_target_feature), &["sme"]),
     // FEAT_SME_F8F16
-    ("sme-f8f16", Unstable(sym::aarch64_unstable_target_feature), &["sme-f8f32"]),
+    ("sme-f8f16", unstable(sym::aarch64_unstable_target_feature), &["sme-f8f32"]),
     // FEAT_SME_F8F32
-    ("sme-f8f32", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]),
+    ("sme-f8f32", unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]),
     // FEAT_SME_FA64
-    ("sme-fa64", Unstable(sym::aarch64_unstable_target_feature), &["sme", "sve2"]),
+    ("sme-fa64", unstable(sym::aarch64_unstable_target_feature), &["sme", "sve2"]),
     // FEAT_SME_I16I64
-    ("sme-i16i64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]),
+    ("sme-i16i64", unstable(sym::aarch64_unstable_target_feature), &["sme"]),
     // FEAT_SME_LUTv2
-    ("sme-lutv2", Unstable(sym::aarch64_unstable_target_feature), &[]),
+    ("sme-lutv2", unstable(sym::aarch64_unstable_target_feature), &[]),
     // FEAT_SME2
-    ("sme2", Unstable(sym::aarch64_unstable_target_feature), &["sme"]),
+    ("sme2", unstable(sym::aarch64_unstable_target_feature), &["sme"]),
     // FEAT_SME2p1
-    ("sme2p1", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]),
+    ("sme2p1", unstable(sym::aarch64_unstable_target_feature), &["sme2"]),
     // FEAT_SPE
-    ("spe", Stable, &[]),
+    ("spe", STABLE, &[]),
     // FEAT_SSBS & FEAT_SSBS2
-    ("ssbs", Stable, &[]),
+    ("ssbs", STABLE, &[]),
     // FEAT_SSVE_FP8FDOT2
-    ("ssve-fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8dot4"]),
+    ("ssve-fp8dot2", unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8dot4"]),
     // FEAT_SSVE_FP8FDOT4
-    ("ssve-fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8fma"]),
+    ("ssve-fp8dot4", unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8fma"]),
     // FEAT_SSVE_FP8FMA
-    ("ssve-fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]),
+    ("ssve-fp8fma", unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]),
     // FEAT_SVE
     // It was decided that SVE requires Neon: https://github.com/rust-lang/rust/pull/91608
     //
@@ -281,46 +368,46 @@ const AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // exist together: https://developer.arm.com/documentation/102340/0100/New-features-in-SVE2
     //
     // "For backwards compatibility, Neon and VFP are required in the latest architectures."
-    ("sve", Stable, &["neon"]),
+    ("sve", STABLE, &["neon"]),
     // FEAT_SVE_B16B16 (SVE or SME Z-targeting instructions)
-    ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]),
+    ("sve-b16b16", unstable(sym::aarch64_unstable_target_feature), &["bf16"]),
     // FEAT_SVE2
-    ("sve2", Stable, &["sve"]),
+    ("sve2", STABLE, &["sve"]),
     // FEAT_SVE_AES & FEAT_SVE_PMULL128
-    ("sve2-aes", Stable, &["sve2", "aes"]),
+    ("sve2-aes", STABLE, &["sve2", "aes"]),
     // FEAT_SVE2_BitPerm
-    ("sve2-bitperm", Stable, &["sve2"]),
+    ("sve2-bitperm", STABLE, &["sve2"]),
     // FEAT_SVE2_SHA3
-    ("sve2-sha3", Stable, &["sve2", "sha3"]),
+    ("sve2-sha3", STABLE, &["sve2", "sha3"]),
     // FEAT_SVE2_SM4
-    ("sve2-sm4", Stable, &["sve2", "sm4"]),
+    ("sve2-sm4", STABLE, &["sve2", "sm4"]),
     // FEAT_SVE2p1
-    ("sve2p1", Unstable(sym::aarch64_unstable_target_feature), &["sve2"]),
+    ("sve2p1", unstable(sym::aarch64_unstable_target_feature), &["sve2"]),
     // FEAT_TME
-    ("tme", Stable, &[]),
-    ("v8.1a", Unstable(sym::aarch64_ver_target_feature), &[
+    ("tme", STABLE, &[]),
+    ("v8.1a", unstable(sym::aarch64_ver_target_feature), &[
         "crc", "lse", "rdm", "pan", "lor", "vh",
     ]),
-    ("v8.2a", Unstable(sym::aarch64_ver_target_feature), &["v8.1a", "ras", "dpb"]),
-    ("v8.3a", Unstable(sym::aarch64_ver_target_feature), &[
+    ("v8.2a", unstable(sym::aarch64_ver_target_feature), &["v8.1a", "ras", "dpb"]),
+    ("v8.3a", unstable(sym::aarch64_ver_target_feature), &[
         "v8.2a", "rcpc", "paca", "pacg", "jsconv",
     ]),
-    ("v8.4a", Unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]),
-    ("v8.5a", Unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]),
-    ("v8.6a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]),
-    ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &["v8.6a", "wfxt"]),
-    ("v8.8a", Unstable(sym::aarch64_ver_target_feature), &["v8.7a", "hbc", "mops"]),
-    ("v8.9a", Unstable(sym::aarch64_ver_target_feature), &["v8.8a", "cssc"]),
-    ("v9.1a", Unstable(sym::aarch64_ver_target_feature), &["v9a", "v8.6a"]),
-    ("v9.2a", Unstable(sym::aarch64_ver_target_feature), &["v9.1a", "v8.7a"]),
-    ("v9.3a", Unstable(sym::aarch64_ver_target_feature), &["v9.2a", "v8.8a"]),
-    ("v9.4a", Unstable(sym::aarch64_ver_target_feature), &["v9.3a", "v8.9a"]),
-    ("v9.5a", Unstable(sym::aarch64_ver_target_feature), &["v9.4a"]),
-    ("v9a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "sve2"]),
+    ("v8.4a", unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]),
+    ("v8.5a", unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]),
+    ("v8.6a", unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]),
+    ("v8.7a", unstable(sym::aarch64_ver_target_feature), &["v8.6a", "wfxt"]),
+    ("v8.8a", unstable(sym::aarch64_ver_target_feature), &["v8.7a", "hbc", "mops"]),
+    ("v8.9a", unstable(sym::aarch64_ver_target_feature), &["v8.8a", "cssc"]),
+    ("v9.1a", unstable(sym::aarch64_ver_target_feature), &["v9a", "v8.6a"]),
+    ("v9.2a", unstable(sym::aarch64_ver_target_feature), &["v9.1a", "v8.7a"]),
+    ("v9.3a", unstable(sym::aarch64_ver_target_feature), &["v9.2a", "v8.8a"]),
+    ("v9.4a", unstable(sym::aarch64_ver_target_feature), &["v9.3a", "v8.9a"]),
+    ("v9.5a", unstable(sym::aarch64_ver_target_feature), &["v9.4a"]),
+    ("v9a", unstable(sym::aarch64_ver_target_feature), &["v8.5a", "sve2"]),
     // FEAT_VHE
-    ("vh", Stable, &[]),
+    ("vh", STABLE, &[]),
     // FEAT_WFxT
-    ("wfxt", Unstable(sym::aarch64_unstable_target_feature), &[]),
+    ("wfxt", unstable(sym::aarch64_unstable_target_feature), &[]),
     // tidy-alphabetical-end
 ];
 
@@ -328,241 +415,256 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[
     &["paca", "pacg"], // Together these represent `pauth` in LLVM
 ];
 
-const X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const X86_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
-    ("adx", Stable, &[]),
-    ("aes", Stable, &["sse2"]),
-    ("amx-bf16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
-    ("amx-complex", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
-    ("amx-fp16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
-    ("amx-int8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
-    ("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]),
-    ("avx", Stable, &["sse4.2"]),
-    ("avx2", Stable, &["avx"]),
-    ("avx512bf16", Unstable(sym::avx512_target_feature), &["avx512bw"]),
-    ("avx512bitalg", Unstable(sym::avx512_target_feature), &["avx512bw"]),
-    ("avx512bw", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512cd", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512dq", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512f", Unstable(sym::avx512_target_feature), &["avx2", "fma", "f16c"]),
-    ("avx512fp16", Unstable(sym::avx512_target_feature), &["avx512bw", "avx512vl", "avx512dq"]),
-    ("avx512ifma", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512vbmi", Unstable(sym::avx512_target_feature), &["avx512bw"]),
-    ("avx512vbmi2", Unstable(sym::avx512_target_feature), &["avx512bw"]),
-    ("avx512vl", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512vnni", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512vp2intersect", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512vpopcntdq", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avxifma", Unstable(sym::avx512_target_feature), &["avx2"]),
-    ("avxneconvert", Unstable(sym::avx512_target_feature), &["avx2"]),
-    ("avxvnni", Unstable(sym::avx512_target_feature), &["avx2"]),
-    ("avxvnniint16", Unstable(sym::avx512_target_feature), &["avx2"]),
-    ("avxvnniint8", Unstable(sym::avx512_target_feature), &["avx2"]),
-    ("bmi1", Stable, &[]),
-    ("bmi2", Stable, &[]),
-    ("cmpxchg16b", Stable, &[]),
-    ("ermsb", Unstable(sym::ermsb_target_feature), &[]),
-    ("f16c", Stable, &["avx"]),
-    ("fma", Stable, &["avx"]),
-    ("fxsr", Stable, &[]),
-    ("gfni", Unstable(sym::avx512_target_feature), &["sse2"]),
-    ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
-    ("lzcnt", Stable, &[]),
-    ("movbe", Stable, &[]),
-    ("pclmulqdq", Stable, &["sse2"]),
-    ("popcnt", Stable, &[]),
-    ("prfchw", Unstable(sym::prfchw_target_feature), &[]),
-    ("rdrand", Stable, &[]),
-    ("rdseed", Stable, &[]),
-    ("rtm", Unstable(sym::rtm_target_feature), &[]),
-    ("sha", Stable, &["sse2"]),
-    ("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]),
-    ("sm3", Unstable(sym::sha512_sm_x86), &["avx"]),
-    ("sm4", Unstable(sym::sha512_sm_x86), &["avx2"]),
-    ("soft-float", Forbidden { reason: "unsound because it changes float ABI" }, &[]),
-    ("sse", Stable, &[]),
-    ("sse2", Stable, &["sse"]),
-    ("sse3", Stable, &["sse2"]),
-    ("sse4.1", Stable, &["ssse3"]),
-    ("sse4.2", Stable, &["sse4.1"]),
-    ("sse4a", Unstable(sym::sse4a_target_feature), &["sse3"]),
-    ("ssse3", Stable, &["sse3"]),
-    ("tbm", Unstable(sym::tbm_target_feature), &[]),
-    ("vaes", Unstable(sym::avx512_target_feature), &["avx2", "aes"]),
-    ("vpclmulqdq", Unstable(sym::avx512_target_feature), &["avx", "pclmulqdq"]),
-    ("xop", Unstable(sym::xop_target_feature), &[/*"fma4", */ "avx", "sse4a"]),
-    ("xsave", Stable, &[]),
-    ("xsavec", Stable, &["xsave"]),
-    ("xsaveopt", Stable, &["xsave"]),
-    ("xsaves", Stable, &["xsave"]),
+    ("adx", STABLE, &[]),
+    ("aes", STABLE, &["sse2"]),
+    ("amx-bf16", unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+    ("amx-complex", unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+    ("amx-fp16", unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+    ("amx-int8", unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+    ("amx-tile", unstable(sym::x86_amx_intrinsics), &[]),
+    ("avx", STABLE, &["sse4.2"]),
+    ("avx2", STABLE, &["avx"]),
+    ("avx512bf16", unstable(sym::avx512_target_feature), &["avx512bw"]),
+    ("avx512bitalg", unstable(sym::avx512_target_feature), &["avx512bw"]),
+    ("avx512bw", unstable(sym::avx512_target_feature), &["avx512f"]),
+    ("avx512cd", unstable(sym::avx512_target_feature), &["avx512f"]),
+    ("avx512dq", unstable(sym::avx512_target_feature), &["avx512f"]),
+    ("avx512f", unstable(sym::avx512_target_feature), &["avx2", "fma", "f16c"]),
+    ("avx512fp16", unstable(sym::avx512_target_feature), &["avx512bw", "avx512vl", "avx512dq"]),
+    ("avx512ifma", unstable(sym::avx512_target_feature), &["avx512f"]),
+    ("avx512vbmi", unstable(sym::avx512_target_feature), &["avx512bw"]),
+    ("avx512vbmi2", unstable(sym::avx512_target_feature), &["avx512bw"]),
+    ("avx512vl", unstable(sym::avx512_target_feature), &["avx512f"]),
+    ("avx512vnni", unstable(sym::avx512_target_feature), &["avx512f"]),
+    ("avx512vp2intersect", unstable(sym::avx512_target_feature), &["avx512f"]),
+    ("avx512vpopcntdq", unstable(sym::avx512_target_feature), &["avx512f"]),
+    ("avxifma", unstable(sym::avx512_target_feature), &["avx2"]),
+    ("avxneconvert", unstable(sym::avx512_target_feature), &["avx2"]),
+    ("avxvnni", unstable(sym::avx512_target_feature), &["avx2"]),
+    ("avxvnniint16", unstable(sym::avx512_target_feature), &["avx2"]),
+    ("avxvnniint8", unstable(sym::avx512_target_feature), &["avx2"]),
+    ("bmi1", STABLE, &[]),
+    ("bmi2", STABLE, &[]),
+    ("cmpxchg16b", STABLE, &[]),
+    ("ermsb", unstable(sym::ermsb_target_feature), &[]),
+    ("f16c", STABLE, &["avx"]),
+    ("fma", STABLE, &["avx"]),
+    ("fxsr", STABLE, &[]),
+    ("gfni", unstable(sym::avx512_target_feature), &["sse2"]),
+    ("lahfsahf", unstable(sym::lahfsahf_target_feature), &[]),
+    ("lzcnt", STABLE, &[]),
+    ("movbe", STABLE, &[]),
+    ("pclmulqdq", STABLE, &["sse2"]),
+    ("popcnt", STABLE, &[]),
+    ("prfchw", unstable(sym::prfchw_target_feature), &[]),
+    ("rdrand", STABLE, &[]),
+    ("rdseed", STABLE, &[]),
+    ("rtm", unstable(sym::rtm_target_feature), &[]),
+    ("sha", STABLE, &["sse2"]),
+    ("sha512", unstable(sym::sha512_sm_x86), &["avx2"]),
+    ("sm3", unstable(sym::sha512_sm_x86), &["avx"]),
+    ("sm4", unstable(sym::sha512_sm_x86), &["avx2"]),
+    ("soft-float", Stability::Forbidden { reason: "unsound because it changes float ABI" }, &[]),
+    ("sse", STABLE, &[]),
+    ("sse2", STABLE, &["sse"]),
+    ("sse3", STABLE, &["sse2"]),
+    ("sse4.1", STABLE, &["ssse3"]),
+    ("sse4.2", STABLE, &["sse4.1"]),
+    ("sse4a", unstable(sym::sse4a_target_feature), &["sse3"]),
+    ("ssse3", STABLE, &["sse3"]),
+    ("tbm", unstable(sym::tbm_target_feature), &[]),
+    ("vaes", unstable(sym::avx512_target_feature), &["avx2", "aes"]),
+    ("vpclmulqdq", unstable(sym::avx512_target_feature), &["avx", "pclmulqdq"]),
+    (
+        "x87",
+        Stability::Unstable {
+            nightly_feature: sym::x87_target_feature,
+            allow_toggle: |target: &Target| {
+                // Only allow toggling this if the target has `soft-float` set. With `soft-float`,
+                // `fpregs` isn't needed so changing it cannot affect the ABI.
+                if target.has_feature("soft-float") {
+                    Ok(())
+                } else {
+                    Err("unsound on hard-float targets because it changes float ABI")
+                }
+            },
+        },
+        &[],
+    ),
+    ("xop", unstable(sym::xop_target_feature), &[/*"fma4", */ "avx", "sse4a"]),
+    ("xsave", STABLE, &[]),
+    ("xsavec", STABLE, &["xsave"]),
+    ("xsaveopt", STABLE, &["xsave"]),
+    ("xsaves", STABLE, &["xsave"]),
     // tidy-alphabetical-end
-    // FIXME: need to also forbid turning off `x87` on hardfloat targets
 ];
 
-const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const HEXAGON_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
-    ("hvx", Unstable(sym::hexagon_target_feature), &[]),
-    ("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]),
+    ("hvx", unstable(sym::hexagon_target_feature), &[]),
+    ("hvx-length128b", unstable(sym::hexagon_target_feature), &["hvx"]),
     // tidy-alphabetical-end
 ];
 
-const POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const POWERPC_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
-    ("altivec", Unstable(sym::powerpc_target_feature), &[]),
-    ("partword-atomics", Unstable(sym::powerpc_target_feature), &[]),
-    ("power10-vector", Unstable(sym::powerpc_target_feature), &["power9-vector"]),
-    ("power8-altivec", Unstable(sym::powerpc_target_feature), &["altivec"]),
-    ("power8-crypto", Unstable(sym::powerpc_target_feature), &["power8-altivec"]),
-    ("power8-vector", Unstable(sym::powerpc_target_feature), &["vsx", "power8-altivec"]),
-    ("power9-altivec", Unstable(sym::powerpc_target_feature), &["power8-altivec"]),
-    ("power9-vector", Unstable(sym::powerpc_target_feature), &["power8-vector", "power9-altivec"]),
-    ("quadword-atomics", Unstable(sym::powerpc_target_feature), &[]),
-    ("vsx", Unstable(sym::powerpc_target_feature), &["altivec"]),
+    ("altivec", unstable(sym::powerpc_target_feature), &[]),
+    ("partword-atomics", unstable(sym::powerpc_target_feature), &[]),
+    ("power10-vector", unstable(sym::powerpc_target_feature), &["power9-vector"]),
+    ("power8-altivec", unstable(sym::powerpc_target_feature), &["altivec"]),
+    ("power8-crypto", unstable(sym::powerpc_target_feature), &["power8-altivec"]),
+    ("power8-vector", unstable(sym::powerpc_target_feature), &["vsx", "power8-altivec"]),
+    ("power9-altivec", unstable(sym::powerpc_target_feature), &["power8-altivec"]),
+    ("power9-vector", unstable(sym::powerpc_target_feature), &["power8-vector", "power9-altivec"]),
+    ("quadword-atomics", unstable(sym::powerpc_target_feature), &[]),
+    ("vsx", unstable(sym::powerpc_target_feature), &["altivec"]),
     // tidy-alphabetical-end
 ];
 
-const MIPS_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const MIPS_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
-    ("fp64", Unstable(sym::mips_target_feature), &[]),
-    ("msa", Unstable(sym::mips_target_feature), &[]),
-    ("virt", Unstable(sym::mips_target_feature), &[]),
+    ("fp64", unstable(sym::mips_target_feature), &[]),
+    ("msa", unstable(sym::mips_target_feature), &[]),
+    ("virt", unstable(sym::mips_target_feature), &[]),
     // tidy-alphabetical-end
 ];
 
-const RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const RISCV_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
-    ("a", Stable, &["zaamo", "zalrsc"]),
-    ("c", Stable, &[]),
-    ("d", Unstable(sym::riscv_target_feature), &["f"]),
-    ("e", Unstable(sym::riscv_target_feature), &[]),
-    ("f", Unstable(sym::riscv_target_feature), &[]),
-    ("m", Stable, &[]),
-    ("relax", Unstable(sym::riscv_target_feature), &[]),
-    ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]),
-    ("v", Unstable(sym::riscv_target_feature), &[]),
-    ("zaamo", Unstable(sym::riscv_target_feature), &[]),
-    ("zabha", Unstable(sym::riscv_target_feature), &["zaamo"]),
-    ("zalrsc", Unstable(sym::riscv_target_feature), &[]),
-    ("zba", Stable, &[]),
-    ("zbb", Stable, &[]),
-    ("zbc", Stable, &[]),
-    ("zbkb", Stable, &[]),
-    ("zbkc", Stable, &[]),
-    ("zbkx", Stable, &[]),
-    ("zbs", Stable, &[]),
-    ("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]),
-    ("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]),
-    ("zfhmin", Unstable(sym::riscv_target_feature), &["f"]),
-    ("zfinx", Unstable(sym::riscv_target_feature), &[]),
-    ("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]),
-    ("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]),
-    ("zk", Stable, &["zkn", "zkr", "zkt"]),
-    ("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
-    ("zknd", Stable, &[]),
-    ("zkne", Stable, &[]),
-    ("zknh", Stable, &[]),
-    ("zkr", Stable, &[]),
-    ("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
-    ("zksed", Stable, &[]),
-    ("zksh", Stable, &[]),
-    ("zkt", Stable, &[]),
+    ("a", STABLE, &["zaamo", "zalrsc"]),
+    ("c", STABLE, &[]),
+    ("d", unstable(sym::riscv_target_feature), &["f"]),
+    ("e", unstable(sym::riscv_target_feature), &[]),
+    ("f", unstable(sym::riscv_target_feature), &[]),
+    ("m", STABLE, &[]),
+    ("relax", unstable(sym::riscv_target_feature), &[]),
+    ("unaligned-scalar-mem", unstable(sym::riscv_target_feature), &[]),
+    ("v", unstable(sym::riscv_target_feature), &[]),
+    ("zaamo", unstable(sym::riscv_target_feature), &[]),
+    ("zabha", unstable(sym::riscv_target_feature), &["zaamo"]),
+    ("zalrsc", unstable(sym::riscv_target_feature), &[]),
+    ("zba", STABLE, &[]),
+    ("zbb", STABLE, &[]),
+    ("zbc", STABLE, &[]),
+    ("zbkb", STABLE, &[]),
+    ("zbkc", STABLE, &[]),
+    ("zbkx", STABLE, &[]),
+    ("zbs", STABLE, &[]),
+    ("zdinx", unstable(sym::riscv_target_feature), &["zfinx"]),
+    ("zfh", unstable(sym::riscv_target_feature), &["zfhmin"]),
+    ("zfhmin", unstable(sym::riscv_target_feature), &["f"]),
+    ("zfinx", unstable(sym::riscv_target_feature), &[]),
+    ("zhinx", unstable(sym::riscv_target_feature), &["zhinxmin"]),
+    ("zhinxmin", unstable(sym::riscv_target_feature), &["zfinx"]),
+    ("zk", STABLE, &["zkn", "zkr", "zkt"]),
+    ("zkn", STABLE, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
+    ("zknd", STABLE, &[]),
+    ("zkne", STABLE, &[]),
+    ("zknh", STABLE, &[]),
+    ("zkr", STABLE, &[]),
+    ("zks", STABLE, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
+    ("zksed", STABLE, &[]),
+    ("zksh", STABLE, &[]),
+    ("zkt", STABLE, &[]),
     // tidy-alphabetical-end
 ];
 
-const WASM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const WASM_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
-    ("atomics", Unstable(sym::wasm_target_feature), &[]),
-    ("bulk-memory", Stable, &[]),
-    ("exception-handling", Unstable(sym::wasm_target_feature), &[]),
-    ("extended-const", Stable, &[]),
-    ("multivalue", Stable, &[]),
-    ("mutable-globals", Stable, &[]),
-    ("nontrapping-fptoint", Stable, &[]),
-    ("reference-types", Stable, &[]),
-    ("relaxed-simd", Stable, &["simd128"]),
-    ("sign-ext", Stable, &[]),
-    ("simd128", Stable, &[]),
-    ("tail-call", Stable, &[]),
-    ("wide-arithmetic", Unstable(sym::wasm_target_feature), &[]),
+    ("atomics", unstable(sym::wasm_target_feature), &[]),
+    ("bulk-memory", STABLE, &[]),
+    ("exception-handling", unstable(sym::wasm_target_feature), &[]),
+    ("extended-const", STABLE, &[]),
+    ("multivalue", STABLE, &[]),
+    ("mutable-globals", STABLE, &[]),
+    ("nontrapping-fptoint", STABLE, &[]),
+    ("reference-types", STABLE, &[]),
+    ("relaxed-simd", STABLE, &["simd128"]),
+    ("sign-ext", STABLE, &[]),
+    ("simd128", STABLE, &[]),
+    ("tail-call", STABLE, &[]),
+    ("wide-arithmetic", unstable(sym::wasm_target_feature), &[]),
     // tidy-alphabetical-end
 ];
 
-const BPF_FEATURES: &[(&str, Stability, ImpliedFeatures)] =
-    &[("alu32", Unstable(sym::bpf_target_feature), &[])];
+const BPF_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] =
+    &[("alu32", unstable(sym::bpf_target_feature), &[])];
 
-const CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const CSKY_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
-    ("10e60", Unstable(sym::csky_target_feature), &["7e10"]),
-    ("2e3", Unstable(sym::csky_target_feature), &["e2"]),
-    ("3e3r1", Unstable(sym::csky_target_feature), &[]),
-    ("3e3r2", Unstable(sym::csky_target_feature), &["3e3r1", "doloop"]),
-    ("3e3r3", Unstable(sym::csky_target_feature), &["doloop"]),
-    ("3e7", Unstable(sym::csky_target_feature), &["2e3"]),
-    ("7e10", Unstable(sym::csky_target_feature), &["3e7"]),
-    ("cache", Unstable(sym::csky_target_feature), &[]),
-    ("doloop", Unstable(sym::csky_target_feature), &[]),
-    ("dsp1e2", Unstable(sym::csky_target_feature), &[]),
-    ("dspe60", Unstable(sym::csky_target_feature), &[]),
-    ("e1", Unstable(sym::csky_target_feature), &["elrw"]),
-    ("e2", Unstable(sym::csky_target_feature), &["e2"]),
-    ("edsp", Unstable(sym::csky_target_feature), &[]),
-    ("elrw", Unstable(sym::csky_target_feature), &[]),
-    ("float1e2", Unstable(sym::csky_target_feature), &[]),
-    ("float1e3", Unstable(sym::csky_target_feature), &[]),
-    ("float3e4", Unstable(sym::csky_target_feature), &[]),
-    ("float7e60", Unstable(sym::csky_target_feature), &[]),
-    ("floate1", Unstable(sym::csky_target_feature), &[]),
-    ("hard-tp", Unstable(sym::csky_target_feature), &[]),
-    ("high-registers", Unstable(sym::csky_target_feature), &[]),
-    ("hwdiv", Unstable(sym::csky_target_feature), &[]),
-    ("mp", Unstable(sym::csky_target_feature), &["2e3"]),
-    ("mp1e2", Unstable(sym::csky_target_feature), &["3e7"]),
-    ("nvic", Unstable(sym::csky_target_feature), &[]),
-    ("trust", Unstable(sym::csky_target_feature), &[]),
-    ("vdsp2e60f", Unstable(sym::csky_target_feature), &[]),
-    ("vdspv1", Unstable(sym::csky_target_feature), &[]),
-    ("vdspv2", Unstable(sym::csky_target_feature), &[]),
+    ("10e60", unstable(sym::csky_target_feature), &["7e10"]),
+    ("2e3", unstable(sym::csky_target_feature), &["e2"]),
+    ("3e3r1", unstable(sym::csky_target_feature), &[]),
+    ("3e3r2", unstable(sym::csky_target_feature), &["3e3r1", "doloop"]),
+    ("3e3r3", unstable(sym::csky_target_feature), &["doloop"]),
+    ("3e7", unstable(sym::csky_target_feature), &["2e3"]),
+    ("7e10", unstable(sym::csky_target_feature), &["3e7"]),
+    ("cache", unstable(sym::csky_target_feature), &[]),
+    ("doloop", unstable(sym::csky_target_feature), &[]),
+    ("dsp1e2", unstable(sym::csky_target_feature), &[]),
+    ("dspe60", unstable(sym::csky_target_feature), &[]),
+    ("e1", unstable(sym::csky_target_feature), &["elrw"]),
+    ("e2", unstable(sym::csky_target_feature), &["e2"]),
+    ("edsp", unstable(sym::csky_target_feature), &[]),
+    ("elrw", unstable(sym::csky_target_feature), &[]),
+    ("float1e2", unstable(sym::csky_target_feature), &[]),
+    ("float1e3", unstable(sym::csky_target_feature), &[]),
+    ("float3e4", unstable(sym::csky_target_feature), &[]),
+    ("float7e60", unstable(sym::csky_target_feature), &[]),
+    ("floate1", unstable(sym::csky_target_feature), &[]),
+    ("hard-tp", unstable(sym::csky_target_feature), &[]),
+    ("high-registers", unstable(sym::csky_target_feature), &[]),
+    ("hwdiv", unstable(sym::csky_target_feature), &[]),
+    ("mp", unstable(sym::csky_target_feature), &["2e3"]),
+    ("mp1e2", unstable(sym::csky_target_feature), &["3e7"]),
+    ("nvic", unstable(sym::csky_target_feature), &[]),
+    ("trust", unstable(sym::csky_target_feature), &[]),
+    ("vdsp2e60f", unstable(sym::csky_target_feature), &[]),
+    ("vdspv1", unstable(sym::csky_target_feature), &[]),
+    ("vdspv2", unstable(sym::csky_target_feature), &[]),
     // tidy-alphabetical-end
     //fpu
     // tidy-alphabetical-start
-    ("fdivdu", Unstable(sym::csky_target_feature), &[]),
-    ("fpuv2_df", Unstable(sym::csky_target_feature), &[]),
-    ("fpuv2_sf", Unstable(sym::csky_target_feature), &[]),
-    ("fpuv3_df", Unstable(sym::csky_target_feature), &[]),
-    ("fpuv3_hf", Unstable(sym::csky_target_feature), &[]),
-    ("fpuv3_hi", Unstable(sym::csky_target_feature), &[]),
-    ("fpuv3_sf", Unstable(sym::csky_target_feature), &[]),
-    ("hard-float", Unstable(sym::csky_target_feature), &[]),
-    ("hard-float-abi", Unstable(sym::csky_target_feature), &[]),
+    ("fdivdu", unstable(sym::csky_target_feature), &[]),
+    ("fpuv2_df", unstable(sym::csky_target_feature), &[]),
+    ("fpuv2_sf", unstable(sym::csky_target_feature), &[]),
+    ("fpuv3_df", unstable(sym::csky_target_feature), &[]),
+    ("fpuv3_hf", unstable(sym::csky_target_feature), &[]),
+    ("fpuv3_hi", unstable(sym::csky_target_feature), &[]),
+    ("fpuv3_sf", unstable(sym::csky_target_feature), &[]),
+    ("hard-float", unstable(sym::csky_target_feature), &[]),
+    ("hard-float-abi", unstable(sym::csky_target_feature), &[]),
     // tidy-alphabetical-end
 ];
 
-const LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const LOONGARCH_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
-    ("d", Unstable(sym::loongarch_target_feature), &["f"]),
-    ("f", Unstable(sym::loongarch_target_feature), &[]),
-    ("frecipe", Unstable(sym::loongarch_target_feature), &[]),
-    ("lasx", Unstable(sym::loongarch_target_feature), &["lsx"]),
-    ("lbt", Unstable(sym::loongarch_target_feature), &[]),
-    ("lsx", Unstable(sym::loongarch_target_feature), &["d"]),
-    ("lvz", Unstable(sym::loongarch_target_feature), &[]),
-    ("relax", Unstable(sym::loongarch_target_feature), &[]),
-    ("ual", Unstable(sym::loongarch_target_feature), &[]),
+    ("d", unstable(sym::loongarch_target_feature), &["f"]),
+    ("f", unstable(sym::loongarch_target_feature), &[]),
+    ("frecipe", unstable(sym::loongarch_target_feature), &[]),
+    ("lasx", unstable(sym::loongarch_target_feature), &["lsx"]),
+    ("lbt", unstable(sym::loongarch_target_feature), &[]),
+    ("lsx", unstable(sym::loongarch_target_feature), &["d"]),
+    ("lvz", unstable(sym::loongarch_target_feature), &[]),
+    ("relax", unstable(sym::loongarch_target_feature), &[]),
+    ("ual", unstable(sym::loongarch_target_feature), &[]),
     // tidy-alphabetical-end
 ];
 
-const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const IBMZ_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
-    ("backchain", Unstable(sym::s390x_target_feature), &[]),
-    ("vector", Unstable(sym::s390x_target_feature), &[]),
+    ("backchain", unstable(sym::s390x_target_feature), &[]),
+    ("vector", unstable(sym::s390x_target_feature), &[]),
     // tidy-alphabetical-end
 ];
 
-const SPARC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const SPARC_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
-    ("leoncasa", Unstable(sym::sparc_target_feature), &[]),
-    ("v8plus", Unstable(sym::sparc_target_feature), &[]),
-    ("v9", Unstable(sym::sparc_target_feature), &[]),
+    ("leoncasa", unstable(sym::sparc_target_feature), &[]),
+    ("v8plus", unstable(sym::sparc_target_feature), &[]),
+    ("v9", unstable(sym::sparc_target_feature), &[]),
     // tidy-alphabetical-end
 ];
 
@@ -570,7 +672,7 @@ const SPARC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
 /// primitives may be documented.
 ///
 /// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator!
-pub fn all_rust_features() -> impl Iterator<Item = (&'static str, Stability)> {
+pub fn all_rust_features() -> impl Iterator<Item = (&'static str, StabilityUncomputed)> {
     std::iter::empty()
         .chain(ARM_FEATURES.iter())
         .chain(AARCH64_FEATURES.iter())
@@ -614,8 +716,10 @@ const CSKY_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(
 const LOONGARCH_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
     &[(128, "lsx"), (256, "lasx")];
 
-impl super::spec::Target {
-    pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] {
+impl Target {
+    pub fn rust_target_features(
+        &self,
+    ) -> &'static [(&'static str, StabilityUncomputed, ImpliedFeatures)] {
         match &*self.arch {
             "arm" => ARM_FEATURES,
             "aarch64" | "arm64ec" => AARCH64_FEATURES,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index f856a8d7abb..5a62a4c3bd5 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -63,10 +63,11 @@ use rustc_hir::{self as hir};
 use rustc_macros::extension;
 use rustc_middle::bug;
 use rustc_middle::dep_graph::DepContext;
+use rustc_middle::traits::PatternOriginExpr;
 use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeErrorToStringExt};
 use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, with_forced_trimmed_paths};
 use rustc_middle::ty::{
-    self, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
+    self, List, ParamEnv, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
     TypeVisitableExt,
 };
 use rustc_span::def_id::LOCAL_CRATE;
@@ -77,7 +78,7 @@ use crate::error_reporting::TypeErrCtxt;
 use crate::errors::{ObligationCauseFailureCode, TypeErrorAdditionalDiags};
 use crate::infer;
 use crate::infer::relate::{self, RelateResult, TypeRelation};
-use crate::infer::{InferCtxt, TypeTrace, ValuePairs};
+use crate::infer::{InferCtxt, InferCtxtExt as _, TypeTrace, ValuePairs};
 use crate::solve::deeply_normalize_for_diagnostics;
 use crate::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
@@ -433,15 +434,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         cause: &ObligationCause<'tcx>,
         exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
         terr: TypeError<'tcx>,
+        param_env: Option<ParamEnv<'tcx>>,
     ) {
         match *cause.code() {
-            ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
-                let ty = self.resolve_vars_if_possible(root_ty);
-                if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)))
-                {
+            ObligationCauseCode::Pattern {
+                origin_expr: Some(origin_expr),
+                span: Some(span),
+                root_ty,
+            } => {
+                let expected_ty = self.resolve_vars_if_possible(root_ty);
+                if !matches!(
+                    expected_ty.kind(),
+                    ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_))
+                ) {
                     // don't show type `_`
                     if span.desugaring_kind() == Some(DesugaringKind::ForLoop)
-                        && let ty::Adt(def, args) = ty.kind()
+                        && let ty::Adt(def, args) = expected_ty.kind()
                         && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
                     {
                         err.span_label(
@@ -449,22 +457,48 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             format!("this is an iterator with items of type `{}`", args.type_at(0)),
                         );
                     } else {
-                        err.span_label(span, format!("this expression has type `{ty}`"));
+                        err.span_label(span, format!("this expression has type `{expected_ty}`"));
                     }
                 }
                 if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
-                    && ty.boxed_ty() == Some(found)
-                    && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+                    && let Ok(mut peeled_snippet) =
+                        self.tcx.sess.source_map().span_to_snippet(origin_expr.peeled_span)
                 {
-                    err.span_suggestion(
-                        span,
-                        "consider dereferencing the boxed value",
-                        format!("*{snippet}"),
-                        Applicability::MachineApplicable,
-                    );
+                    // Parentheses are needed for cases like as casts.
+                    // We use the peeled_span for deref suggestions.
+                    // It's also safe to use for box, since box only triggers if there
+                    // wasn't a reference to begin with.
+                    if origin_expr.peeled_prefix_suggestion_parentheses {
+                        peeled_snippet = format!("({peeled_snippet})");
+                    }
+
+                    // Try giving a box suggestion first, as it is a special case of the
+                    // deref suggestion.
+                    if expected_ty.boxed_ty() == Some(found) {
+                        err.span_suggestion_verbose(
+                            span,
+                            "consider dereferencing the boxed value",
+                            format!("*{peeled_snippet}"),
+                            Applicability::MachineApplicable,
+                        );
+                    } else if let Some(param_env) = param_env
+                        && let Some(prefix) = self.should_deref_suggestion_on_mismatch(
+                            param_env,
+                            found,
+                            expected_ty,
+                            origin_expr,
+                        )
+                    {
+                        err.span_suggestion_verbose(
+                            span,
+                            "consider dereferencing to access the inner value using the Deref trait",
+                            format!("{prefix}{peeled_snippet}"),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
                 }
             }
-            ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
+            ObligationCauseCode::Pattern { origin_expr: None, span: Some(span), .. } => {
                 err.span_label(span, "expected due to this");
             }
             ObligationCauseCode::BlockTailExpression(
@@ -618,6 +652,45 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
+    /// Determines whether deref_to == <deref_from as Deref>::Target, and if so,
+    /// returns a prefix that should be added to deref_from as a suggestion.
+    fn should_deref_suggestion_on_mismatch(
+        &self,
+        param_env: ParamEnv<'tcx>,
+        deref_to: Ty<'tcx>,
+        deref_from: Ty<'tcx>,
+        origin_expr: PatternOriginExpr,
+    ) -> Option<String> {
+        // origin_expr contains stripped away versions of our expression.
+        // We'll want to use that to avoid suggesting things like *&x.
+        // However, the type that we have access to hasn't been stripped away,
+        // so we need to ignore the first n dereferences, where n is the number
+        // that's been stripped away in origin_expr.
+
+        // Find a way to autoderef from deref_from to deref_to.
+        let Some((num_derefs, (after_deref_ty, _))) = (self.autoderef_steps)(deref_from)
+            .into_iter()
+            .enumerate()
+            .find(|(_, (ty, _))| self.infcx.can_eq(param_env, *ty, deref_to))
+        else {
+            return None;
+        };
+
+        if num_derefs <= origin_expr.peeled_count {
+            return None;
+        }
+
+        let deref_part = "*".repeat(num_derefs - origin_expr.peeled_count);
+
+        // If the user used a reference in the original expression, they probably
+        // want the suggestion to still give a reference.
+        if deref_from.is_ref() && !after_deref_ty.is_ref() {
+            Some(format!("&{deref_part}"))
+        } else {
+            Some(deref_part)
+        }
+    }
+
     /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
     /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
     /// populate `other_value` with `other_ty`.
@@ -1406,8 +1479,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             Variable(ty::error::ExpectedFound<Ty<'a>>),
             Fixed(&'static str),
         }
-        let (expected_found, exp_found, is_simple_error, values) = match values {
-            None => (None, Mismatch::Fixed("type"), false, None),
+        let (expected_found, exp_found, is_simple_error, values, param_env) = match values {
+            None => (None, Mismatch::Fixed("type"), false, None, None),
             Some(ty::ParamEnvAnd { param_env, value: values }) => {
                 let mut values = self.resolve_vars_if_possible(values);
                 if self.next_trait_solver() {
@@ -1459,7 +1532,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     diag.downgrade_to_delayed_bug();
                     return;
                 };
-                (Some(vals), exp_found, is_simple_error, Some(values))
+                (Some(vals), exp_found, is_simple_error, Some(values), Some(param_env))
             }
         };
 
@@ -1791,7 +1864,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
         // It reads better to have the error origin as the final
         // thing.
-        self.note_error_origin(diag, cause, exp_found, terr);
+        self.note_error_origin(diag, cause, exp_found, terr, param_env);
 
         debug!(?diag);
     }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
index fc2d0ba36f0..08775df5ac9 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
@@ -210,7 +210,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
             {
                 ObligationCauseCode::Pattern { span: Some(then_span), origin_expr, .. } => {
-                    origin_expr.then_some(ConsiderAddingAwait::FutureSugg {
+                    origin_expr.is_some().then_some(ConsiderAddingAwait::FutureSugg {
                         span: then_span.shrink_to_hi(),
                     })
                 }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 94682f501a8..cc8941b9224 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -20,7 +20,8 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{
-    CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node, is_range_literal,
+    CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node, expr_needs_parens,
+    is_range_literal,
 };
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
 use rustc_middle::hir::map;
@@ -1391,13 +1392,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         let Some(expr) = expr_finder.result else {
                             return false;
                         };
-                        let needs_parens = match expr.kind {
-                            // parenthesize if needed (Issue #46756)
-                            hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
-                            // parenthesize borrows of range literals (Issue #54505)
-                            _ if is_range_literal(expr) => true,
-                            _ => false,
-                        };
+                        let needs_parens = expr_needs_parens(expr);
 
                         let span = if needs_parens { span } else { span.shrink_to_lo() };
                         let suggestions = if !needs_parens {
diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs
index 07fb2efb7fe..b17a489a857 100644
--- a/compiler/rustc_trait_selection/src/traits/effects.rs
+++ b/compiler/rustc_trait_selection/src/traits/effects.rs
@@ -128,7 +128,9 @@ fn evaluate_host_effect_from_selection_candiate<'tcx>(
             Err(_) => Err(EvaluationFailure::NoSolution),
             Ok(Some(source)) => match source {
                 ImplSource::UserDefined(impl_) => {
-                    if tcx.constness(impl_.impl_def_id) != hir::Constness::Const {
+                    if tcx.impl_trait_header(impl_.impl_def_id).unwrap().constness
+                        != hir::Constness::Const
+                    {
                         return Err(EvaluationFailure::NoSolution);
                     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
index dc3f5544613..254dee794f1 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
@@ -3,7 +3,7 @@ use rustc_infer::traits::Obligation;
 use rustc_middle::traits::query::NoSolution;
 pub use rustc_middle::traits::query::type_op::AscribeUserType;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
-use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserArgs, UserSelfTy, UserType};
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserArgs, UserSelfTy, UserTypeKind};
 use rustc_span::{DUMMY_SP, Span};
 use tracing::{debug, instrument};
 
@@ -46,12 +46,18 @@ pub fn type_op_ascribe_user_type_with_span<'tcx>(
     let (param_env, AscribeUserType { mir_ty, user_ty }) = key.into_parts();
     debug!("type_op_ascribe_user_type: mir_ty={:?} user_ty={:?}", mir_ty, user_ty);
     let span = span.unwrap_or(DUMMY_SP);
-    match user_ty {
-        UserType::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?,
-        UserType::TypeOf(def_id, user_args) => {
+    match user_ty.kind {
+        UserTypeKind::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?,
+        UserTypeKind::TypeOf(def_id, user_args) => {
             relate_mir_and_user_args(ocx, param_env, span, mir_ty, def_id, user_args)?
         }
     };
+
+    // Enforce any bounds that come from impl trait in bindings.
+    ocx.register_obligations(user_ty.bounds.iter().map(|clause| {
+        Obligation::new(ocx.infcx.tcx, ObligationCause::dummy_with_span(span), param_env, clause)
+    }));
+
     Ok(())
 }
 
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index f96487cc53c..dfd090b3956 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -5,8 +5,8 @@ use serde::Serialize;
 use crate::compiler_interface::with;
 use crate::mir::pretty::function_body;
 use crate::ty::{
-    AdtDef, ClosureDef, CoroutineDef, GenericArgs, MirConst, Movability, Region, RigidTy, Ty,
-    TyConst, TyKind, VariantIdx,
+    AdtDef, ClosureDef, CoroutineClosureDef, CoroutineDef, GenericArgs, MirConst, Movability,
+    Region, RigidTy, Ty, TyConst, TyKind, VariantIdx,
 };
 use crate::{Error, Opaque, Span, Symbol};
 
@@ -617,6 +617,9 @@ impl Rvalue {
                 AggregateKind::Coroutine(def, ref args, mov) => {
                     Ok(Ty::new_coroutine(def, args.clone(), mov))
                 }
+                AggregateKind::CoroutineClosure(def, ref args) => {
+                    Ok(Ty::new_coroutine_closure(def, args.clone()))
+                }
                 AggregateKind::RawPtr(ty, mutability) => Ok(Ty::new_ptr(ty, mutability)),
             },
             Rvalue::ShallowInitBox(_, ty) => Ok(Ty::new_box(*ty)),
@@ -633,6 +636,7 @@ pub enum AggregateKind {
     Closure(ClosureDef, GenericArgs),
     // FIXME(stable_mir): Movability here is redundant
     Coroutine(CoroutineDef, GenericArgs, Movability),
+    CoroutineClosure(CoroutineClosureDef, GenericArgs),
     RawPtr(Ty, Mutability),
 }
 
diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs
index 01a50d46b2d..93ed32e258a 100644
--- a/compiler/stable_mir/src/mir/pretty.rs
+++ b/compiler/stable_mir/src/mir/pretty.rs
@@ -410,6 +410,10 @@ fn pretty_aggregate<W: Write>(
             write!(writer, "{{coroutine@{}}}(", def.span().diagnostic())?;
             ")"
         }
+        AggregateKind::CoroutineClosure(def, _) => {
+            write!(writer, "{{coroutine-closure@{}}}(", def.span().diagnostic())?;
+            ")"
+        }
         AggregateKind::RawPtr(ty, mutability) => {
             write!(
                 writer,
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index 9ce72f155f9..d7eb435e13f 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -63,6 +63,11 @@ impl Ty {
         Ty::from_rigid_kind(RigidTy::Coroutine(def, args, mov))
     }
 
+    /// Create a new closure type.
+    pub fn new_coroutine_closure(def: CoroutineClosureDef, args: GenericArgs) -> Ty {
+        Ty::from_rigid_kind(RigidTy::CoroutineClosure(def, args))
+    }
+
     /// Create a new box type that represents `Box<T>`, for the given inner type `T`.
     pub fn new_box(inner_ty: Ty) -> Ty {
         with(|cx| cx.new_box_ty(inner_ty))
@@ -550,6 +555,7 @@ pub enum RigidTy {
     Closure(ClosureDef, GenericArgs),
     // FIXME(stable_mir): Movability here is redundant
     Coroutine(CoroutineDef, GenericArgs, Movability),
+    CoroutineClosure(CoroutineClosureDef, GenericArgs),
     Dynamic(Vec<Binder<ExistentialPredicate>>, Region, DynKind),
     Never,
     Tuple(Vec<Ty>),
@@ -742,6 +748,11 @@ crate_def! {
 
 crate_def! {
     #[derive(Serialize)]
+    pub CoroutineClosureDef;
+}
+
+crate_def! {
+    #[derive(Serialize)]
     pub ParamDef;
 }
 
diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs
index 48260285408..3533ed2e851 100644
--- a/compiler/stable_mir/src/visitor.rs
+++ b/compiler/stable_mir/src/visitor.rs
@@ -168,6 +168,7 @@ impl Visitable for RigidTy {
             | RigidTy::Closure(_, args)
             | RigidTy::Coroutine(_, args, _)
             | RigidTy::CoroutineWitness(_, args)
+            | RigidTy::CoroutineClosure(_, args)
             | RigidTy::FnDef(_, args) => args.visit(visitor),
             RigidTy::FnPtr(sig) => sig.visit(visitor),
             RigidTy::Dynamic(pred, r, _) => {
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 91549f49f9f..9dbea57fa1f 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -2,7 +2,7 @@
 #![stable(feature = "error_in_core", since = "1.81.0")]
 
 use crate::any::TypeId;
-use crate::fmt::{Debug, Display, Formatter, Result};
+use crate::fmt::{self, Debug, Display, Formatter};
 
 /// `Error` is a trait representing the basic expectations for error values,
 /// i.e., values of type `E` in [`Result<T, E>`].
@@ -857,7 +857,7 @@ impl<'a> Request<'a> {
 
 #[unstable(feature = "error_generic_member_access", issue = "99301")]
 impl<'a> Debug for Request<'a> {
-    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         f.debug_struct("Request").finish_non_exhaustive()
     }
 }
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index af6f0da88de..94341a4da66 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -19,7 +19,7 @@ pub struct Placeholder {
 }
 
 impl Placeholder {
-    #[inline(always)]
+    #[inline]
     pub const fn new(
         position: usize,
         fill: char,
@@ -95,7 +95,7 @@ pub struct Argument<'a> {
 
 #[rustc_diagnostic_item = "ArgumentMethods"]
 impl Argument<'_> {
-    #[inline(always)]
+    #[inline]
     fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> {
         Argument {
             // INVARIANT: this creates an `ArgumentType<'a>` from a `&'a T` and
@@ -109,47 +109,47 @@ impl Argument<'_> {
         }
     }
 
-    #[inline(always)]
+    #[inline]
     pub fn new_display<T: Display>(x: &T) -> Argument<'_> {
         Self::new(x, Display::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_debug<T: Debug>(x: &T) -> Argument<'_> {
         Self::new(x, Debug::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_debug_noop<T: Debug>(x: &T) -> Argument<'_> {
         Self::new(x, |_, _| Ok(()))
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_octal<T: Octal>(x: &T) -> Argument<'_> {
         Self::new(x, Octal::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_lower_hex<T: LowerHex>(x: &T) -> Argument<'_> {
         Self::new(x, LowerHex::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_upper_hex<T: UpperHex>(x: &T) -> Argument<'_> {
         Self::new(x, UpperHex::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_pointer<T: Pointer>(x: &T) -> Argument<'_> {
         Self::new(x, Pointer::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_binary<T: Binary>(x: &T) -> Argument<'_> {
         Self::new(x, Binary::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_lower_exp<T: LowerExp>(x: &T) -> Argument<'_> {
         Self::new(x, LowerExp::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn new_upper_exp<T: UpperExp>(x: &T) -> Argument<'_> {
         Self::new(x, UpperExp::fmt)
     }
-    #[inline(always)]
+    #[inline]
     pub fn from_usize(x: &usize) -> Argument<'_> {
         Argument { ty: ArgumentType::Count(*x) }
     }
@@ -164,7 +164,7 @@ impl Argument<'_> {
     // it here is an explicit CFI violation.
     #[allow(inline_no_sanitize)]
     #[no_sanitize(cfi, kcfi)]
-    #[inline(always)]
+    #[inline]
     pub(super) unsafe fn fmt(&self, f: &mut Formatter<'_>) -> Result {
         match self.ty {
             // SAFETY:
@@ -180,7 +180,7 @@ impl Argument<'_> {
         }
     }
 
-    #[inline(always)]
+    #[inline]
     pub(super) fn as_usize(&self) -> Option<usize> {
         match self.ty {
             ArgumentType::Count(count) => Some(count),
@@ -198,7 +198,7 @@ impl Argument<'_> {
     /// let f = format_args!("{}", "a");
     /// println!("{f}");
     /// ```
-    #[inline(always)]
+    #[inline]
     pub fn none() -> [Self; 0] {
         []
     }
@@ -215,7 +215,7 @@ pub struct UnsafeArg {
 impl UnsafeArg {
     /// See documentation where `UnsafeArg` is required to know when it is safe to
     /// create and use `UnsafeArg`.
-    #[inline(always)]
+    #[inline]
     pub unsafe fn new() -> Self {
         Self { _private: () }
     }
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index c59e4414d37..9c054b99a27 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -310,6 +310,8 @@ pub fn spin_loop() {
 /// behavior in the calling code. This property makes `black_box` useful for writing code in which
 /// certain optimizations are not desired, such as benchmarks.
 ///
+/// <div class="warning">
+///
 /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
 /// extent to which it can block optimisations may vary depending upon the platform and code-gen
 /// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the
@@ -317,6 +319,8 @@ pub fn spin_loop() {
 /// This also means that this function does not offer any guarantees for cryptographic or security
 /// purposes.
 ///
+/// </div>
+///
 /// [`std::convert::identity`]: crate::convert::identity
 ///
 /// # When is this useful?
@@ -357,7 +361,7 @@ pub fn spin_loop() {
 /// ```
 /// use std::hint::black_box;
 ///
-/// // Same `contains` function
+/// // Same `contains` function.
 /// fn contains(haystack: &[&str], needle: &str) -> bool {
 ///     haystack.iter().any(|x| x == &needle)
 /// }
@@ -366,8 +370,13 @@ pub fn spin_loop() {
 ///     let haystack = vec!["abc", "def", "ghi", "jkl", "mno"];
 ///     let needle = "ghi";
 ///     for _ in 0..10 {
-///         // Adjust our benchmark loop contents
-///         black_box(contains(black_box(&haystack), black_box(needle)));
+///         // Force the compiler to run `contains`, even though it is a pure function whose
+///         // results are unused.
+///         black_box(contains(
+///             // Prevent the compiler from making assumptions about the input.
+///             black_box(&haystack),
+///             black_box(needle),
+///         ));
 ///     }
 /// }
 /// ```
@@ -382,6 +391,83 @@ pub fn spin_loop() {
 ///
 /// This makes our benchmark much more realistic to how the function would actually be used, where
 /// arguments are usually not known at compile time and the result is used in some way.
+///
+/// # How to use this
+///
+/// In practice, `black_box` serves two purposes:
+///
+/// 1. It prevents the compiler from making optimizations related to the value returned by `black_box`
+/// 2. It forces the value passed to `black_box` to be calculated, even if the return value of `black_box` is unused
+///
+/// ```
+/// use std::hint::black_box;
+///
+/// let zero = 0;
+/// let five = 5;
+///
+/// // The compiler will see this and remove the `* five` call, because it knows that multiplying
+/// // any integer by 0 will result in 0.
+/// let c = zero * five;
+///
+/// // Adding `black_box` here disables the compiler's ability to reason about the first operand in the multiplication.
+/// // It is forced to assume that it can be any possible number, so it cannot remove the `* five`
+/// // operation.
+/// let c = black_box(zero) * five;
+/// ```
+///
+/// While most cases will not be as clear-cut as the above example, it still illustrates how
+/// `black_box` can be used. When benchmarking a function, you usually want to wrap its inputs in
+/// `black_box` so the compiler cannot make optimizations that would be unrealistic in real-life
+/// use.
+///
+/// ```
+/// use std::hint::black_box;
+///
+/// // This is a simple function that increments its input by 1. Note that it is pure, meaning it
+/// // has no side-effects. This function has no effect if its result is unused. (An example of a
+/// // function *with* side-effects is `println!()`.)
+/// fn increment(x: u8) -> u8 {
+///     x + 1
+/// }
+///
+/// // Here, we call `increment` but discard its result. The compiler, seeing this and knowing that
+/// // `increment` is pure, will eliminate this function call entirely. This may not be desired,
+/// // though, especially if we're trying to track how much time `increment` takes to execute.
+/// let _ = increment(black_box(5));
+///
+/// // Here, we force `increment` to be executed. This is because the compiler treats `black_box`
+/// // as if it has side-effects, and thus must compute its input.
+/// let _ = black_box(increment(black_box(5)));
+/// ```
+///
+/// There may be additional situations where you want to wrap the result of a function in
+/// `black_box` to force its execution. This is situational though, and may not have any effect
+/// (such as when the function returns a zero-sized type such as [`()` unit][unit]).
+///
+/// Note that `black_box` has no effect on how its input is treated, only its output. As such,
+/// expressions passed to `black_box` may still be optimized:
+///
+/// ```
+/// use std::hint::black_box;
+///
+/// // The compiler sees this...
+/// let y = black_box(5 * 10);
+///
+/// // ...as this. As such, it will likely simplify `5 * 10` to just `50`.
+/// let _0 = 5 * 10;
+/// let y = black_box(_0);
+/// ```
+///
+/// In the above example, the `5 * 10` expression is considered distinct from the `black_box` call,
+/// and thus is still optimized by the compiler. You can prevent this by moving the multiplication
+/// operation outside of `black_box`:
+///
+/// ```
+/// use std::hint::black_box;
+///
+/// // No assumptions can be made about either operand, so the multiplication is not optimized out.
+/// let y = black_box(5) * black_box(10);
+/// ```
 #[inline]
 #[stable(feature = "bench_black_box", since = "1.66.0")]
 #[rustc_const_unstable(feature = "const_black_box", issue = "none")]
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index c3c7288e389..8ab1c26f95e 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -493,15 +493,64 @@ impl Extend<()> for () {
 }
 
 macro_rules! spec_tuple_impl {
-    ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), ) => {
-        spec_tuple_impl!($trait_name, $default_fn_name, #[doc(fake_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for 1- and 3- through 12-ary tuples were stabilized after 2-tuples, in RUSTC_CURRENT_VERSION."] => ($ty_name, $var_name, $extend_ty_name, $cnt),);
+    (
+        (
+            $ty_name:ident, $var_name:ident, $extend_ty_name: ident,
+            $trait_name:ident, $default_fn_name:ident, $cnt:tt
+        ),
+    ) => {
+        spec_tuple_impl!(
+            $trait_name,
+            $default_fn_name,
+            #[doc(fake_variadic)]
+            #[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for \
+                     1- and 3- through 12-ary tuples were stabilized after 2-tuples, in \
+                     CURRENT_RUSTC_VERSION."]
+            => ($ty_name, $var_name, $extend_ty_name, $cnt),
+        );
     };
-    ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), $(($ty_names:ident, $var_names:ident,  $extend_ty_names:ident, $trait_names:ident, $default_fn_names:ident, $cnts:tt),)*) => {
-
-        spec_tuple_impl!($(($ty_names, $var_names, $extend_ty_names, $trait_names, $default_fn_names, $cnts),)*);
-        spec_tuple_impl!($trait_name, $default_fn_name, #[doc(hidden)] => ($ty_name, $var_name, $extend_ty_name, $cnt), $(($ty_names, $var_names, $extend_ty_names, $cnts),)*);
+    (
+        (
+            $ty_name:ident, $var_name:ident, $extend_ty_name: ident,
+            $trait_name:ident, $default_fn_name:ident, $cnt:tt
+        ),
+        $(
+            (
+                $ty_names:ident, $var_names:ident,  $extend_ty_names:ident,
+                $trait_names:ident, $default_fn_names:ident, $cnts:tt
+            ),
+        )*
+    ) => {
+        spec_tuple_impl!(
+            $(
+                (
+                    $ty_names, $var_names, $extend_ty_names,
+                    $trait_names, $default_fn_names, $cnts
+                ),
+            )*
+        );
+        spec_tuple_impl!(
+            $trait_name,
+            $default_fn_name,
+            #[doc(hidden)]
+            => (
+                $ty_name, $var_name, $extend_ty_name, $cnt
+            ),
+            $(
+                (
+                    $ty_names, $var_names, $extend_ty_names, $cnts
+                ),
+            )*
+        );
     };
-    ($trait_name:ident, $default_fn_name:ident, #[$meta:meta] $(#[$doctext:meta])? => $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt),)*) => {
+    (
+        $trait_name:ident, $default_fn_name:ident, #[$meta:meta]
+        $(#[$doctext:meta])? => $(
+            (
+                $ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt
+            ),
+        )*
+    ) => {
         #[$meta]
         $(#[$doctext])?
         #[stable(feature = "extend_for_tuple", since = "1.56.0")]
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index fde6887c5ab..d45cb01910f 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -354,6 +354,8 @@ pub mod random;
 pub mod range;
 pub mod result;
 pub mod sync;
+#[unstable(feature = "unsafe_binders", issue = "130516")]
+pub mod unsafe_binder;
 
 pub mod fmt;
 pub mod hash;
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index bc4c4e168a3..51ab2054b3b 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -200,7 +200,7 @@
 //!
 //! But it *is* still sound to:
 //!
-//! * Create a pointer without provenance from just an address (see [`ptr::dangling`]). Such a
+//! * Create a pointer without provenance from just an address (see [`without_provenance`]). Such a
 //!   pointer cannot be used for memory accesses (except for zero-sized accesses). This can still be
 //!   useful for sentinel values like `null` *or* to represent a tagged pointer that will never be
 //!   dereferenceable. In general, it is always sound for an integer to pretend to be a pointer "for
@@ -314,8 +314,8 @@
 //! }
 //! ```
 //!
-//! (Yes, if you've been using AtomicUsize for pointers in concurrent datastructures, you should
-//! be using AtomicPtr instead. If that messes up the way you atomically manipulate pointers,
+//! (Yes, if you've been using [`AtomicUsize`] for pointers in concurrent datastructures, you should
+//! be using [`AtomicPtr`] instead. If that messes up the way you atomically manipulate pointers,
 //! we would like to know why, and what needs to be done to fix it.)
 //!
 //! Situations where a valid pointer *must* be created from just an address, such as baremetal code
@@ -381,7 +381,8 @@
 //! [`with_addr`]: pointer::with_addr
 //! [`map_addr`]: pointer::map_addr
 //! [`addr`]: pointer::addr
-//! [`ptr::dangling`]: core::ptr::dangling
+//! [`AtomicUsize`]: crate::sync::atomic::AtomicUsize
+//! [`AtomicPtr`]: crate::sync::atomic::AtomicPtr
 //! [`expose_provenance`]: pointer::expose_provenance
 //! [`with_exposed_provenance`]: with_exposed_provenance
 //! [Miri]: https://github.com/rust-lang/miri
diff --git a/library/core/src/unsafe_binder.rs b/library/core/src/unsafe_binder.rs
new file mode 100644
index 00000000000..98f53e07d9d
--- /dev/null
+++ b/library/core/src/unsafe_binder.rs
@@ -0,0 +1,25 @@
+//! Operators used to turn types into unsafe binders and back.
+
+/// Unwrap an unsafe binder into its underlying type.
+#[allow_internal_unstable(builtin_syntax)]
+#[unstable(feature = "unsafe_binders", issue = "130516")]
+pub macro unwrap_binder {
+    ($expr:expr) => {
+        builtin # unwrap_binder ( $expr )
+    },
+    ($expr:expr ; $ty:ty) => {
+        builtin # unwrap_binder ( $expr, $ty )
+    },
+}
+
+/// Wrap a type into an unsafe binder.
+#[allow_internal_unstable(builtin_syntax)]
+#[unstable(feature = "unsafe_binders", issue = "130516")]
+pub macro wrap_binder {
+    ($expr:expr) => {
+        builtin # wrap_binder ( $expr )
+    },
+    ($expr:expr ; $ty:ty) => {
+        builtin # wrap_binder ( $expr, $ty )
+    },
+}
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 047f5b0c4c5..1cbf51463ea 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -544,6 +544,8 @@ pub use core::u64;
 #[stable(feature = "i128", since = "1.26.0")]
 #[allow(deprecated, deprecated_in_future)]
 pub use core::u128;
+#[unstable(feature = "unsafe_binders", issue = "130516")]
+pub use core::unsafe_binder;
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated, deprecated_in_future)]
 pub use core::usize;
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 5b277a982ee..35e920ab344 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2327,7 +2327,9 @@ impl Path {
             // FIXME: Allow Redox prefixes
             self.has_root() || has_redox_scheme(self.as_u8_slice())
         } else {
-            self.has_root() && (cfg!(any(unix, target_os = "wasi")) || self.prefix().is_some())
+            self.has_root()
+                && (cfg!(any(unix, target_os = "hermit", target_os = "wasi"))
+                    || self.prefix().is_some())
         }
     }
 
diff --git a/library/std/src/pipe.rs b/library/std/src/pipe.rs
index 891032e94a6..06f3fd9fdff 100644
--- a/library/std/src/pipe.rs
+++ b/library/std/src/pipe.rs
@@ -1,20 +1,66 @@
-//! Module for anonymous pipe
+//!  A cross-platform anonymous pipe.
 //!
-//! ```
-//! #![feature(anonymous_pipe)]
+//! This module provides support for anonymous OS pipes, like [pipe] on Linux or [CreatePipe] on
+//! Windows.
+//!
+//! # Behavior
+//!
+//! A pipe is a synchronous, unidirectional data channel between two or more processes, like an
+//! interprocess [`mpsc`](crate::sync::mpsc) provided by the OS. In particular:
+//!
+//! * A read on a [`PipeReader`] blocks until the pipe is non-empty.
+//! * A write on a [`PipeWriter`] blocks when the pipe is full.
+//! * When all copies of a [`PipeWriter`] are closed, a read on the corresponding [`PipeReader`]
+//!   returns EOF.
+//! * [`PipeReader`] can be shared, but only one process will consume the data in the pipe.
+//!
+//! # Capacity
+//!
+//! Pipe capacity is platform dependent. To quote the Linux [man page]:
+//!
+//! > Different implementations have different limits for the pipe capacity. Applications should
+//! > not rely on a particular capacity: an application should be designed so that a reading process
+//! > consumes data as soon as it is available, so that a writing process does not remain blocked.
 //!
+//! # Examples
+//!
+//! ```no_run
+//! #![feature(anonymous_pipe)]
 //! # #[cfg(miri)] fn main() {}
 //! # #[cfg(not(miri))]
 //! # fn main() -> std::io::Result<()> {
-//! let (reader, writer) = std::pipe::pipe()?;
+//! # use std::process::Command;
+//! # use std::io::{Read, Write};
+//! let (ping_rx, mut ping_tx) = std::pipe::pipe()?;
+//! let (mut pong_rx, pong_tx) = std::pipe::pipe()?;
+//!
+//! // Spawn a process that echoes its input.
+//! let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;
+//!
+//! ping_tx.write_all(b"hello")?;
+//! // Close to unblock echo_server's reader.
+//! drop(ping_tx);
+//!
+//! let mut buf = String::new();
+//! // Block until echo_server's writer is closed.
+//! pong_rx.read_to_string(&mut buf)?;
+//! assert_eq!(&buf, "hello");
+//!
+//! echo_server.wait()?;
 //! # Ok(())
 //! # }
 //! ```
-
+//! [pipe]: https://man7.org/linux/man-pages/man2/pipe.2.html
+//! [CreatePipe]: https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe
+//! [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html
 use crate::io;
 use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
 
 /// Create anonymous pipe that is close-on-exec and blocking.
+///
+/// # Examples
+///
+/// See the [module-level](crate::pipe) documentation for examples.
 #[unstable(feature = "anonymous_pipe", issue = "127154")]
 #[inline]
 pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
@@ -33,6 +79,58 @@ pub struct PipeWriter(pub(crate) AnonPipe);
 
 impl PipeReader {
     /// Create a new [`PipeReader`] instance that shares the same underlying file description.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(anonymous_pipe)]
+    /// # #[cfg(miri)] fn main() {}
+    /// # #[cfg(not(miri))]
+    /// # fn main() -> std::io::Result<()> {
+    /// # use std::fs;
+    /// # use std::io::Write;
+    /// # use std::process::Command;
+    /// const NUM_SLOT: u8 = 2;
+    /// const NUM_PROC: u8 = 5;
+    /// const OUTPUT: &str = "work.txt";
+    ///
+    /// let mut jobs = vec![];
+    /// let (reader, mut writer) = std::pipe::pipe()?;
+    ///
+    /// // Write NUM_SLOT characters the the pipe.
+    /// writer.write_all(&[b'|'; NUM_SLOT as usize])?;
+    ///
+    /// // Spawn several processes that read a character from the pipe, do some work, then
+    /// // write back to the pipe. When the pipe is empty, the processes block, so only
+    /// // NUM_SLOT processes can be working at any given time.
+    /// for _ in 0..NUM_PROC {
+    ///     jobs.push(
+    ///         Command::new("bash")
+    ///             .args(["-c",
+    ///                 &format!(
+    ///                      "read -n 1\n\
+    ///                       echo -n 'x' >> '{OUTPUT}'\n\
+    ///                       echo -n '|'",
+    ///                 ),
+    ///             ])
+    ///             .stdin(reader.try_clone()?)
+    ///             .stdout(writer.try_clone()?)
+    ///             .spawn()?,
+    ///     );
+    /// }
+    ///
+    /// // Wait for all jobs to finish.
+    /// for mut job in jobs {
+    ///     job.wait()?;
+    /// }
+    ///
+    /// // Check our work and clean up.
+    /// let xs = fs::read_to_string(OUTPUT)?;
+    /// fs::remove_file(OUTPUT)?;
+    /// assert_eq!(xs, "x".repeat(NUM_PROC.into()));
+    /// # Ok(())
+    /// # }
+    /// ```
     #[unstable(feature = "anonymous_pipe", issue = "127154")]
     pub fn try_clone(&self) -> io::Result<Self> {
         self.0.try_clone().map(Self)
@@ -41,6 +139,38 @@ impl PipeReader {
 
 impl PipeWriter {
     /// Create a new [`PipeWriter`] instance that shares the same underlying file description.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(anonymous_pipe)]
+    /// # #[cfg(miri)] fn main() {}
+    /// # #[cfg(not(miri))]
+    /// # fn main() -> std::io::Result<()> {
+    /// # use std::process::Command;
+    /// # use std::io::Read;
+    /// let (mut reader, writer) = std::pipe::pipe()?;
+    ///
+    /// // Spawn a process that writes to stdout and stderr.
+    /// let mut peer = Command::new("bash")
+    ///     .args([
+    ///         "-c",
+    ///         "echo -n foo\n\
+    ///          echo -n bar >&2"
+    ///     ])
+    ///     .stdout(writer.try_clone()?)
+    ///     .stderr(writer)
+    ///     .spawn()?;
+    ///
+    /// // Read and check the result.
+    /// let mut msg = String::new();
+    /// reader.read_to_string(&mut msg)?;
+    /// assert_eq!(&msg, "foobar");
+    ///
+    /// peer.wait()?;
+    /// # Ok(())
+    /// # }
+    /// ```
     #[unstable(feature = "anonymous_pipe", issue = "127154")]
     pub fn try_clone(&self) -> io::Result<Self> {
         self.0.try_clone().map(Self)
diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs
index 11862a07608..88fc4068719 100644
--- a/library/std/src/sys/pal/hermit/fs.rs
+++ b/library/std/src/sys/pal/hermit/fs.rs
@@ -3,7 +3,7 @@ use super::hermit_abi::{
     self, DT_DIR, DT_LNK, DT_REG, DT_UNKNOWN, O_APPEND, O_CREAT, O_DIRECTORY, O_EXCL, O_RDONLY,
     O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, dirent64, stat as stat_struct,
 };
-use crate::ffi::{CStr, OsStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString, c_char};
 use crate::io::{self, BorrowedCursor, Error, ErrorKind, IoSlice, IoSliceMut, SeekFrom};
 use crate::os::hermit::ffi::OsStringExt;
 use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
@@ -204,7 +204,7 @@ impl Iterator for ReadDir {
                 // the size of dirent64. The file name is always a C string and terminated by `\0`.
                 // Consequently, we are able to ignore the last byte.
                 let name_bytes =
-                    unsafe { CStr::from_ptr(&dir.d_name as *const _ as *const i8).to_bytes() };
+                    unsafe { CStr::from_ptr(&dir.d_name as *const _ as *const c_char).to_bytes() };
                 let entry = DirEntry {
                     root: self.inner.root.clone(),
                     ino: dir.d_ino,
@@ -445,7 +445,7 @@ impl DirBuilder {
 
     pub fn mkdir(&self, path: &Path) -> io::Result<()> {
         run_path_with_cstr(path, &|path| {
-            cvt(unsafe { hermit_abi::mkdir(path.as_ptr(), self.mode.into()) }).map(|_| ())
+            cvt(unsafe { hermit_abi::mkdir(path.as_ptr().cast(), self.mode.into()) }).map(|_| ())
         })
     }
 
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index f03fca60344..d833c9d632c 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -85,7 +85,7 @@ pub unsafe extern "C" fn runtime_entry(
     }
 
     // initialize environment
-    os::init_environment(env as *const *const i8);
+    os::init_environment(env);
 
     let result = unsafe { main(argc as isize, argv) };
 
diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs
index f8ea80afa43..791cdb1e57e 100644
--- a/library/std/src/sys/pal/hermit/os.rs
+++ b/library/std/src/sys/pal/hermit/os.rs
@@ -3,7 +3,7 @@ use core::slice::memchr;
 use super::hermit_abi;
 use crate::collections::HashMap;
 use crate::error::Error as StdError;
-use crate::ffi::{CStr, OsStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString, c_char};
 use crate::marker::PhantomData;
 use crate::os::hermit::ffi::OsStringExt;
 use crate::path::{self, PathBuf};
@@ -70,7 +70,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 static ENV: Mutex<Option<HashMap<OsString, OsString>>> = Mutex::new(None);
 
-pub fn init_environment(env: *const *const i8) {
+pub fn init_environment(env: *const *const c_char) {
     let mut guard = ENV.lock().unwrap();
     let map = guard.insert(HashMap::new());
 
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 0cacd6e4f37..928023bd60b 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1892,12 +1892,6 @@ impl Step for Assemble {
             });
         }
 
-        let lld_install = if builder.config.lld_enabled {
-            Some(builder.ensure(llvm::Lld { target: target_compiler.host }))
-        } else {
-            None
-        };
-
         let stage = target_compiler.stage;
         let host = target_compiler.host;
         let (host_info, dir_name) = if build_compiler.host == host {
@@ -1958,22 +1952,11 @@ impl Step for Assemble {
 
         copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
 
-        if let Some(lld_install) = lld_install {
-            let src_exe = exe("lld", target_compiler.host);
-            let dst_exe = exe("rust-lld", target_compiler.host);
-            builder.copy_link(&lld_install.join("bin").join(src_exe), &libdir_bin.join(dst_exe));
-            let self_contained_lld_dir = libdir_bin.join("gcc-ld");
-            t!(fs::create_dir_all(&self_contained_lld_dir));
-            let lld_wrapper_exe = builder.ensure(crate::core::build_steps::tool::LldWrapper {
-                compiler: build_compiler,
-                target: target_compiler.host,
+        if builder.config.lld_enabled {
+            builder.ensure(crate::core::build_steps::tool::LldWrapper {
+                build_compiler,
+                target_compiler,
             });
-            for name in crate::LLD_FILE_NAMES {
-                builder.copy_link(
-                    &lld_wrapper_exe,
-                    &self_contained_lld_dir.join(exe(name, target_compiler.host)),
-                );
-            }
         }
 
         if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 0c739115165..89b2d73f74a 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -471,7 +471,7 @@ impl Step for Rustc {
                 }
             }
 
-            {
+            if builder.config.llvm_enabled(compiler.host) && builder.config.llvm_tools_enabled {
                 let src_dir = builder.sysroot_target_bindir(compiler, host);
                 let llvm_objcopy = exe("llvm-objcopy", compiler.host);
                 let rust_objcopy = exe("rust-objcopy", compiler.host);
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 3cfbef27f87..04f1e10f493 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -1,8 +1,8 @@
 use std::path::PathBuf;
 use std::{env, fs};
 
-use crate::core::build_steps::compile;
 use crate::core::build_steps::toolstate::ToolState;
+use crate::core::build_steps::{compile, llvm};
 use crate::core::builder;
 use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step};
 use crate::core::config::TargetSelection;
@@ -722,21 +722,27 @@ impl Step for Cargo {
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct LldWrapper {
-    pub compiler: Compiler,
-    pub target: TargetSelection,
+    pub build_compiler: Compiler,
+    pub target_compiler: Compiler,
 }
 
 impl Step for LldWrapper {
-    type Output = PathBuf;
+    type Output = ();
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         run.never()
     }
 
-    fn run(self, builder: &Builder<'_>) -> PathBuf {
-        builder.ensure(ToolBuild {
-            compiler: self.compiler,
-            target: self.target,
+    fn run(self, builder: &Builder<'_>) {
+        if builder.config.dry_run() {
+            return;
+        }
+
+        let target = self.target_compiler.host;
+
+        let executable = builder.ensure(ToolBuild {
+            compiler: self.build_compiler,
+            target,
             tool: "lld-wrapper",
             mode: Mode::ToolStd,
             path: "src/tools/lld-wrapper",
@@ -744,7 +750,22 @@ impl Step for LldWrapper {
             extra_features: Vec::new(),
             allow_features: "",
             cargo_args: Vec::new(),
-        })
+        });
+
+        let libdir_bin = builder.sysroot_target_bindir(self.target_compiler, target);
+        t!(fs::create_dir_all(&libdir_bin));
+
+        let lld_install = builder.ensure(llvm::Lld { target });
+        let src_exe = exe("lld", target);
+        let dst_exe = exe("rust-lld", target);
+
+        builder.copy_link(&lld_install.join("bin").join(src_exe), &libdir_bin.join(dst_exe));
+        let self_contained_lld_dir = libdir_bin.join("gcc-ld");
+        t!(fs::create_dir_all(&self_contained_lld_dir));
+
+        for name in crate::LLD_FILE_NAMES {
+            builder.copy_link(&executable, &self_contained_lld_dir.join(exe(name, target)));
+        }
     }
 }
 
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 6e848628e5c..96d3162a8c5 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -1203,6 +1203,11 @@ impl Builder<'_> {
             // even if we're not going to output debuginfo for the crate we're currently building,
             // so that it'll be available when downstream consumers of std try to use it.
             rustflags.arg("-Zinline-mir-preserve-debug");
+
+            // FIXME: always pass this after the next `#[cfg(bootstrap)]` update.
+            if compiler.stage != 0 {
+                rustflags.arg("-Zmir_strip_debuginfo=locals-in-tiny-functions");
+            }
         }
 
         Cargo {
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index c6800aedca9..22d361ff091 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -1320,7 +1320,31 @@ impl Config {
 
         // Set flags.
         config.paths = std::mem::take(&mut flags.paths);
-        config.skip = flags.skip.into_iter().chain(flags.exclude).collect();
+        config.skip = flags
+            .skip
+            .into_iter()
+            .chain(flags.exclude)
+            .map(|p| {
+                let p = if cfg!(windows) {
+                    PathBuf::from(p.to_str().unwrap().replace('/', "\\"))
+                } else {
+                    p
+                };
+
+                // Jump to top-level project path to support passing paths
+                // from sub directories.
+                let top_level_path = config.src.join(&p);
+                if !config.src.join(&top_level_path).exists() {
+                    eprintln!("WARNING: '{}' does not exist.", top_level_path.display());
+                }
+
+                // Never return top-level path here as it would break `--skip`
+                // logic on rustc's internal test framework which is utilized
+                // by compiletest.
+                p
+            })
+            .collect();
+
         config.include_default_paths = flags.include_default_paths;
         config.rustc_error_format = flags.rustc_error_format;
         config.json_output = flags.json_output;
diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs
index 0df00469452..4aec554b432 100644
--- a/src/bootstrap/src/utils/cc_detect.rs
+++ b/src/bootstrap/src/utils/cc_detect.rs
@@ -44,6 +44,16 @@ fn cc2ar(cc: &Path, target: TargetSelection) -> Option<PathBuf> {
         Some(PathBuf::from("ar"))
     } else if target.contains("vxworks") {
         Some(PathBuf::from("wr-ar"))
+    } else if target.contains("-nto-") {
+        if target.starts_with("i586") {
+            Some(PathBuf::from("ntox86-ar"))
+        } else if target.starts_with("aarch64") {
+            Some(PathBuf::from("ntoaarch64-ar"))
+        } else if target.starts_with("x86_64") {
+            Some(PathBuf::from("ntox86_64-ar"))
+        } else {
+            panic!("Unknown architecture, cannot determine archiver for Neutrino QNX");
+        }
     } else if target.contains("android") || target.contains("-wasi") {
         Some(cc.parent().unwrap().join(PathBuf::from("llvm-ar")))
     } else {
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 c40de76abbf..03ec77f507e 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
@@ -90,9 +90,9 @@ RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc sun
 COPY host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/
 RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh
 
-RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-23/wasi-sdk-23.0-x86_64-linux.tar.gz | \
+RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz | \
   tar -xz
-ENV WASI_SDK_PATH=/tmp/wasi-sdk-23.0-x86_64-linux
+ENV WASI_SDK_PATH=/tmp/wasi-sdk-25.0-x86_64-linux
 
 COPY scripts/freebsd-toolchain.sh /tmp/
 RUN /tmp/freebsd-toolchain.sh i686
diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile
index c2f5a87b123..8d2e45ae497 100644
--- a/src/ci/docker/host-x86_64/test-various/Dockerfile
+++ b/src/ci/docker/host-x86_64/test-various/Dockerfile
@@ -40,9 +40,9 @@ WORKDIR /
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-23/wasi-sdk-23.0-x86_64-linux.tar.gz | \
+RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz | \
   tar -xz
-ENV WASI_SDK_PATH=/wasi-sdk-23.0-x86_64-linux
+ENV WASI_SDK_PATH=/wasi-sdk-25.0-x86_64-linux
 
 ENV RUST_CONFIGURE_ARGS \
   --musl-root-x86_64=/usr/local/x86_64-linux-musl \
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index f3d8a4edd6c..2341d25ff09 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -75,6 +75,7 @@
     - [s390x-unknown-linux-gnu](platform-support/s390x-unknown-linux-gnu.md)
     - [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md)
     - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
+    - [sparcv9-sun-solaris](platform-support/solaris.md)
     - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
     - [\*-nto-qnx-\*](platform-support/nto-qnx.md)
     - [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
@@ -93,6 +94,7 @@
     - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
     - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)
     - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
+    - [x86_64-pc-solaris](platform-support/solaris.md)
     - [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md)
     - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
     - [xtensa-\*-none-elf](platform-support/xtensa.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 3b82d123276..c4efe27efc2 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -180,7 +180,7 @@ target | std | notes
 `riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA)
 `riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA)
 `sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4, glibc 2.23)
-`sparcv9-sun-solaris` | ✓ | SPARC Solaris 11, illumos
+[`sparcv9-sun-solaris`](platform-support/solaris.md) | ✓ | SPARC V9 Solaris 11.4
 [`thumbv6m-none-eabi`](platform-support/thumbv6m-none-eabi.md) | * | Bare Armv6-M
 [`thumbv7em-none-eabi`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M
 [`thumbv7em-none-eabihf`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M, hardfloat
@@ -201,7 +201,7 @@ target | std | notes
 [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX
 [`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia
 [`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android
-`x86_64-pc-solaris` | ✓ | 64-bit Solaris 11, illumos
+[`x86_64-pc-solaris`](platform-support/solaris.md) | ✓ | 64-bit x86 Solaris 11.4
 [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | 64-bit x86 MinGW (Windows 10+), LLVM ABI
 `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27)
 [`x86_64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | x86_64 OpenHarmony
@@ -343,7 +343,7 @@ target | std | host | notes
 [`powerpc-unknown-openbsd`](platform-support/powerpc-unknown-openbsd.md) | * |  |
 [`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ |  |
 [`powerpc-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  |
-`powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2)
+`powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv2)
 `powerpc64le-unknown-freebsd` | ✓ | ✓ | PPC64LE FreeBSD
 `powerpc-unknown-freebsd` | ? |   | PowerPC FreeBSD
 `powerpc64-unknown-linux-musl` | ? |  | 64-bit PowerPC Linux with musl 1.2.3
diff --git a/src/doc/rustc/src/platform-support/solaris.md b/src/doc/rustc/src/platform-support/solaris.md
new file mode 100644
index 00000000000..1e0a241f840
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/solaris.md
@@ -0,0 +1,32 @@
+# sparcv9-sun-solaris
+# x86_64-pc-solaris
+
+**Tier: 2**
+
+Rust for Solaris operating system.
+
+## Target maintainers
+
+- Petr Sumbera `sumbera@volny.cz`, https://github.com/psumbera
+
+## Requirements
+
+Binary built for this target is expected to run on sparcv9 or x86_64, and Solaris 11.4.
+
+## Testing
+
+For testing you can download Oracle Solaris 11.4 CBE release from:
+
+  https://www.oracle.com/uk/solaris/solaris11/downloads/solaris-downloads.html
+
+Solaris CBE release is also available for GitHub CI:
+
+  https://github.com/vmactions/solaris-vm
+
+Latest Solaris 11.4 SRU can be tested at Compile farm project:
+
+  https://portal.cfarm.net/machines/list/ (cfarm215, cfarm215)
+
+There are no official Rust binaries for Solaris available for Rustup yet. But you can eventually download unofficial from:
+
+  https://github.com/psumbera/solaris-rust
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 50dfe0a1b56..25f88c8797f 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1839,8 +1839,15 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
             DynTrait(bounds, lifetime)
         }
         TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
+        TyKind::UnsafeBinder(..) => {
+            unimplemented!("unsafe binders are not supported yet")
+        }
         // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
-        TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) | TyKind::InferDelegation(..) => Infer,
+        TyKind::Infer
+        | TyKind::Err(_)
+        | TyKind::Typeof(..)
+        | TyKind::InferDelegation(..)
+        | TyKind::TraitAscription(_) => Infer,
     }
 }
 
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 91b31f31ab1..2c26ffa76f6 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -423,6 +423,14 @@ pub(crate) fn build_index(
                     }
                     Some(path)
                 });
+            } else if let Some(parent_idx) = item.parent_idx {
+                let i = <isize as TryInto<usize>>::try_into(parent_idx).unwrap();
+                item.path = {
+                    let p = &crate_paths[i].1;
+                    join_with_double_colon(&p[..p.len() - 1])
+                };
+                item.exact_path =
+                    crate_paths[i].2.as_ref().map(|xp| join_with_double_colon(&xp[..xp.len() - 1]));
             }
 
             // Omit the parent path if it is same to that of the prior item.
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index a384c286039..5d82b8e309a 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -846,11 +846,13 @@ fn main_args(
 
     let config = core::create_config(input, options, &render_options, using_internal_features);
 
+    let registered_lints = config.register_lints.is_some();
+
     interface::run_compiler(config, |compiler| {
         let sess = &compiler.sess;
 
         if sess.opts.describe_lints {
-            rustc_driver::describe_lints(sess);
+            rustc_driver::describe_lints(sess, registered_lints);
             return;
         }
 
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 20a443231846b81c7b909691ec3f15eb173f2b1
+Subproject 769f622e12db0001431d8ae36d1093fb8727c5d
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index c300f7cd665..e3959903fdd 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -814,11 +814,13 @@ impl TyCoercionStability {
                 | TyKind::Tup(_)
                 | TyKind::Path(_) => Self::Deref,
                 TyKind::OpaqueDef(..)
+                | TyKind::TraitAscription(..)
                 | TyKind::Infer
                 | TyKind::Typeof(..)
                 | TyKind::TraitObject(..)
                 | TyKind::InferDelegation(..)
                 | TyKind::Err(_) => Self::Reborrow,
+                TyKind::UnsafeBinder(..) => Self::None,
             };
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
index ed27e38ef2d..1dac7b971f9 100644
--- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
+++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs
@@ -63,7 +63,7 @@ impl_lint_pass!(DuplicateMod => [DUPLICATE_MOD]);
 
 impl EarlyLintPass for DuplicateMod {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans)) = &item.kind
+        if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind
             && let FileName::Real(real) = cx.sess().source_map().span_to_filename(mod_spans.inner_span)
             && let Some(local_path) = real.into_local_path()
             && let Ok(absolute_path) = local_path.canonicalize()
diff --git a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
index ffc76366983..dfea40db182 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
@@ -163,7 +163,7 @@ impl Visitor<'_> for NestingVisitor<'_, '_> {
         }
 
         match &item.kind {
-            ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _)) => {
+            ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _, _)) => {
                 self.nest_level += 1;
 
                 if !self.check_indent(item.span, item.id) {
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index ed9879de13b..b679fdfadc3 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -156,7 +156,8 @@ fn never_loop_expr<'tcx>(
         | ExprKind::Field(e, _)
         | ExprKind::AddrOf(_, _, e)
         | ExprKind::Repeat(e, _)
-        | ExprKind::DropTemps(e) => never_loop_expr(cx, e, local_labels, main_loop_id),
+        | ExprKind::DropTemps(e)
+        | ExprKind::UnsafeBinderCast(_, e, _) => never_loop_expr(cx, e, local_labels, main_loop_id),
         ExprKind::Let(let_expr) => never_loop_expr(cx, let_expr.init, local_labels, main_loop_id),
         ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(cx, es.iter(), local_labels, main_loop_id),
         ExprKind::MethodCall(_, receiver, es, _) => {
diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
index b12f575e81a..0e08e2eb83d 100644
--- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
@@ -6,8 +6,11 @@ use clippy_utils::source::SpanRangeExt;
 use clippy_utils::{is_from_proc_macro, path_to_local};
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Constness, Expr, ExprKind};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
 use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
 use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
 
 declare_clippy_lint! {
@@ -94,6 +97,44 @@ impl ManualFloatMethods {
     }
 }
 
+fn is_not_const(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+    match tcx.def_kind(def_id) {
+        DefKind::Mod
+        | DefKind::Struct
+        | DefKind::Union
+        | DefKind::Enum
+        | DefKind::Variant
+        | DefKind::Trait
+        | DefKind::TyAlias
+        | DefKind::ForeignTy
+        | DefKind::TraitAlias
+        | DefKind::AssocTy
+        | DefKind::Macro(..)
+        | DefKind::Field
+        | DefKind::LifetimeParam
+        | DefKind::ExternCrate
+        | DefKind::Use
+        | DefKind::ForeignMod
+        | DefKind::GlobalAsm
+        | DefKind::Impl { .. }
+        | DefKind::OpaqueTy
+        | DefKind::SyntheticCoroutineBody
+        | DefKind::TyParam => true,
+
+        DefKind::AnonConst
+        | DefKind::InlineConst
+        | DefKind::Const
+        | DefKind::ConstParam
+        | DefKind::Static { .. }
+        | DefKind::Ctor(..)
+        | DefKind::AssocConst => false,
+
+        DefKind::Fn
+        | DefKind::AssocFn
+        | DefKind::Closure => tcx.constness(def_id) == Constness::NotConst,
+    }
+}
+
 impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         if let ExprKind::Binary(kind, lhs, rhs) = expr.kind
@@ -105,7 +146,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
             && exprs.iter_mut().partition_in_place(|i| path_to_local(i).is_some()) == 2
             && !in_external_macro(cx.sess(), expr.span)
             && (
-                matches!(cx.tcx.constness(cx.tcx.hir().enclosing_body_owner(expr.hir_id)), Constness::NotConst)
+                is_not_const(cx.tcx, cx.tcx.hir().enclosing_body_owner(expr.hir_id).into())
                     || self.msrv.meets(msrvs::CONST_FLOAT_CLASSIFY)
             )
             && let [first, second, const_1, const_2] = exprs
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
index 3de51bc661e..5b9e9e70e47 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -3,13 +3,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::ty::is_copy;
 use clippy_utils::usage::mutated_variables;
 use clippy_utils::visitors::{Descend, for_each_expr_without_closures};
-use clippy_utils::{MaybePath, is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
+use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
 use rustc_lint::LateContext;
-use rustc_middle::query::Key;
 use rustc_middle::ty;
 use rustc_span::sym;
 
@@ -44,7 +43,6 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a
             if name == "filter_map"
                 && let hir::ExprKind::Call(expr, args) = body.value.kind
                 && is_res_lang_ctor(cx, path_res(cx, expr), OptionSome)
-                && arg_id.ty_def_id() == args[0].hir_id().ty_def_id()
                 && let hir::ExprKind::Path(_) = args[0].kind
             {
                 span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 311ed427cb9..521bf6a5fed 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -623,6 +623,9 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 kind!("DropTemps({expr})");
                 self.expr(expr);
             },
+            ExprKind::UnsafeBinderCast(..) => {
+                unimplemented!("unsafe binders are not implemented yet");
+            }
         }
     }
 
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 620a9b56eb5..12074dd16e6 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -379,7 +379,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         (Mod(lu, lmk), Mod(ru, rmk)) => {
             lu == ru
                 && match (lmk, rmk) {
-                    (ModKind::Loaded(litems, linline, _), ModKind::Loaded(ritems, rinline, _)) => {
+                    (ModKind::Loaded(litems, linline, _, _), ModKind::Loaded(ritems, rinline, _, _)) => {
                         linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind))
                     },
                     (ModKind::Unloaded, ModKind::Unloaded) => true,
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index 7f0363ac942..b5bb174e737 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -303,7 +303,8 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
                 | ExprKind::AddrOf(..)
                 | ExprKind::Repeat(..)
                 | ExprKind::Block(Block { stmts: [], .. }, _)
-                | ExprKind::OffsetOf(..) => (),
+                | ExprKind::OffsetOf(..)
+                | ExprKind::UnsafeBinderCast(..) => (),
 
                 // Assignment might be to a local defined earlier, so don't eagerly evaluate.
                 // Blocks with multiple statements might be expensive, so don't eagerly evaluate.
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index e318ad8671c..4b604f658b8 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -370,6 +370,10 @@ impl HirEqInterExpr<'_, '_, '_> {
                     && self.eq_expr(l_receiver, r_receiver)
                     && self.eq_exprs(l_args, r_args)
             },
+            (&ExprKind::UnsafeBinderCast(lkind, le, None), &ExprKind::UnsafeBinderCast(rkind, re, None)) =>
+                lkind == rkind && self.eq_expr(le, re),
+            (&ExprKind::UnsafeBinderCast(lkind, le, Some(lt)), &ExprKind::UnsafeBinderCast(rkind, re, Some(rt))) =>
+                lkind == rkind && self.eq_expr(le, re) && self.eq_ty(lt, rt),
             (&ExprKind::OffsetOf(l_container, l_fields), &ExprKind::OffsetOf(r_container, r_fields)) => {
                 self.eq_ty(l_container, r_container) && over(l_fields, r_fields, |l, r| l.name == r.name)
             },
@@ -424,6 +428,7 @@ impl HirEqInterExpr<'_, '_, '_> {
                 | &ExprKind::Type(..)
                 | &ExprKind::Unary(..)
                 | &ExprKind::Yield(..)
+                | &ExprKind::UnsafeBinderCast(..)
 
                 // --- Special cases that do not have a positive branch.
 
@@ -1032,6 +1037,13 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 std::mem::discriminant(&lop).hash(&mut self.s);
                 self.hash_expr(le);
             },
+            ExprKind::UnsafeBinderCast(kind, expr, ty) => {
+                std::mem::discriminant(&kind).hash(&mut self.s);
+                self.hash_expr(expr);
+                if let Some(ty) = ty {
+                    self.hash_ty(ty);
+                }
+            }
             ExprKind::Err(_) => {},
         }
     }
@@ -1241,11 +1253,15 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             TyKind::Typeof(anon_const) => {
                 self.hash_body(anon_const.body);
             },
+            TyKind::UnsafeBinder(binder) => {
+                self.hash_ty(binder.inner_ty);
+            }
             TyKind::Err(_)
             | TyKind::Infer
             | TyKind::Never
             | TyKind::InferDelegation(..)
-            | TyKind::OpaqueDef(_) => {},
+            | TyKind::OpaqueDef(_)
+            | TyKind::TraitAscription(_) => {},
         }
     }
 
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 25ebe879192..088abd7c479 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -151,7 +151,8 @@ impl<'a> Sugg<'a> {
             | ExprKind::Become(..)
             | ExprKind::Struct(..)
             | ExprKind::Tup(..)
-            | ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)),
+            | ExprKind::Err(_)
+            | ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(get_snippet(expr.span)),
             ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
             ExprKind::Assign(lhs, rhs, _) => {
                 Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
@@ -226,7 +227,8 @@ impl<'a> Sugg<'a> {
             | ast::ExprKind::While(..)
             | ast::ExprKind::Await(..)
             | ast::ExprKind::Err(_)
-            | ast::ExprKind::Dummy => Sugg::NonParen(snippet(expr.span)),
+            | ast::ExprKind::Dummy
+            | ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)),
             ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
                 AssocOp::DotDot,
                 lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 351e619d7b1..ff58c6358ba 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -694,6 +694,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
             | ExprKind::Continue(_)
             | ExprKind::InlineAsm(_)
             | ExprKind::OffsetOf(..)
+            | ExprKind::UnsafeBinderCast(..)
             | ExprKind::Err(_) => (),
         }
         ControlFlow::Continue(())
diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr
index 062bf25ea62..ee2868869de 100644
--- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr
+++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr
@@ -20,7 +20,6 @@ LL | |     fn clone_self(&self) -> Self {
 LL | |         Self {
 LL | |             a: true,
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
@@ -32,7 +31,6 @@ LL | |     fn default() -> Self {
 LL | |         Self {
 LL | |             a: true,
 ...  |
-LL | |     }
 LL | | }
    | |_^
 
diff --git a/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr b/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr
index ccdaecdd481..9cf6fc66757 100644
--- a/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr
+++ b/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr
@@ -66,8 +66,7 @@ error: this block is too nested
 LL |                   if true {
    |  _________________________^
 LL | |                     if true {
-LL | |
-LL | |                     }
+...  |
 LL | |                 }
    | |_________________^
    |
diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr
index a44c810b135..9677beeb2c2 100644
--- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr
+++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr
@@ -286,7 +286,6 @@ LL | |         if unsafe { true } {
 LL | |             todo!();
 LL | |         } else {
 ...  |
-LL | |         }
 LL | |     };
    | |______^
    |
diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr
index db5ea5b6289..0eccdd42800 100644
--- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr
+++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr
@@ -294,7 +294,6 @@ LL | |         if unsafe { true } {
 LL | |             todo!();
 LL | |         } else {
 ...  |
-LL | |         }
 LL | |     };
    | |______^
    |
diff --git a/src/tools/clippy/tests/ui/async_yields_async.stderr b/src/tools/clippy/tests/ui/async_yields_async.stderr
index c900a9d7421..474914299d0 100644
--- a/src/tools/clippy/tests/ui/async_yields_async.stderr
+++ b/src/tools/clippy/tests/ui/async_yields_async.stderr
@@ -80,7 +80,6 @@ error: an async construct yields a type which is itself awaitable
 LL |       let _m = async || {
    |  _______________________-
 LL | |         println!("I'm bored");
-LL | |         // Some more stuff
 ...  |
 LL | |         CustomFutureType
    | |         ^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr
index 2adaecc96d6..d271381adea 100644
--- a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr
+++ b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr
@@ -44,7 +44,6 @@ LL | |         if {
 LL | |             if s == "43" {
 LL | |                 return Some(43);
 ...  |
-LL | |         }
 LL | |     });
    | |______^
    |
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr
index 68ebb6ad781..36b17773973 100644
--- a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr
@@ -115,8 +115,7 @@ error: all if blocks contain the same code at the end
   --> tests/ui/branches_sharing_code/shared_at_bottom.rs:183:5
    |
 LL | /         x << 2
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -131,8 +130,7 @@ error: all if blocks contain the same code at the end
   --> tests/ui/branches_sharing_code/shared_at_bottom.rs:192:5
    |
 LL | /         x * 4
-LL | |
-LL | |
+...  |
 LL | |     }
    | |_____^
    |
diff --git a/src/tools/clippy/tests/ui/collapsible_else_if.stderr b/src/tools/clippy/tests/ui/collapsible_else_if.stderr
index 395c2dcf68d..45566a78bd8 100644
--- a/src/tools/clippy/tests/ui/collapsible_else_if.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_else_if.stderr
@@ -43,9 +43,7 @@ LL |       } else {
    |  ____________^
 LL | |         if y == "world" {
 LL | |             println!("world")
-LL | |         }
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
@@ -66,9 +64,7 @@ LL |       } else {
    |  ____________^
 LL | |         if let Some(42) = Some(42) {
 LL | |             println!("world")
-LL | |         }
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
@@ -89,9 +85,7 @@ LL |       } else {
    |  ____________^
 LL | |         if let Some(42) = Some(42) {
 LL | |             println!("world")
-LL | |         }
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
@@ -112,9 +106,7 @@ LL |       } else {
    |  ____________^
 LL | |         if x == "hello" {
 LL | |             println!("world")
-LL | |         }
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
@@ -135,9 +127,7 @@ LL |       } else {
    |  ____________^
 LL | |         if let Some(42) = Some(42) {
 LL | |             println!("world")
-LL | |         }
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
diff --git a/src/tools/clippy/tests/ui/copy_iterator.stderr b/src/tools/clippy/tests/ui/copy_iterator.stderr
index 990b1ce628d..2f6378a85fe 100644
--- a/src/tools/clippy/tests/ui/copy_iterator.stderr
+++ b/src/tools/clippy/tests/ui/copy_iterator.stderr
@@ -6,7 +6,6 @@ LL | |
 LL | |
 LL | |     type Item = u8;
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
diff --git a/src/tools/clippy/tests/ui/crashes/ice-360.stderr b/src/tools/clippy/tests/ui/crashes/ice-360.stderr
index 50b245c65cd..9961eb21485 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-360.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-360.stderr
@@ -2,11 +2,7 @@ error: this loop never actually loops
   --> tests/ui/crashes/ice-360.rs:5:5
    |
 LL | /     loop {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |
 LL | |     }
    | |_____^
    |
@@ -16,11 +12,7 @@ error: this loop could be written as a `while let` loop
   --> tests/ui/crashes/ice-360.rs:5:5
    |
 LL | /     loop {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |
 LL | |     }
    | |_____^ help: try: `while let Some(ele) = iter.next() { .. }`
    |
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr
index 7d7922ae8ca..bcc8684f7c2 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr
+++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr
@@ -2,8 +2,7 @@ error: this looks like you are trying to swap `a` and `b`
   --> tests/ui/crate_level_checks/no_std_swap.rs:12:5
    |
 LL | /     a = b;
-LL | |
-LL | |
+...  |
 LL | |     b = a;
    | |_________^ help: try: `core::mem::swap(&mut a, &mut b)`
    |
diff --git a/src/tools/clippy/tests/ui/derivable_impls.stderr b/src/tools/clippy/tests/ui/derivable_impls.stderr
index c22569145bd..0caea892358 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.stderr
+++ b/src/tools/clippy/tests/ui/derivable_impls.stderr
@@ -6,7 +6,6 @@ LL | |     fn default() -> Self {
 LL | |         Self {
 LL | |             a: false,
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
diff --git a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr
index 2852e26680f..c5d5f3d3759 100644
--- a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr
+++ b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr
@@ -99,8 +99,7 @@ LL | /     /// for OldA
 LL | |     // struct OldA;
 LL | |
 LL | |     /// Docs
-LL | |     /// for OldB
-LL | |     // struct OldB;
+...  |
 LL | |
    | |_^
 ...
diff --git a/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr
index 75fc23e9e7e..a95306e2fa3 100644
--- a/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr
+++ b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr
@@ -103,8 +103,7 @@ error: empty lines after outer attribute
   --> tests/ui/empty_line_after/outer_attribute.rs:64:1
    |
 LL | / #[allow(unused)]
-LL | |
-LL | | // This comment is isolated
+...  |
 LL | |
    | |_^
 LL |   pub fn isolated_comment() {}
diff --git a/src/tools/clippy/tests/ui/entry.stderr b/src/tools/clippy/tests/ui/entry.stderr
index fb467676606..4b6bd3b4a25 100644
--- a/src/tools/clippy/tests/ui/entry.stderr
+++ b/src/tools/clippy/tests/ui/entry.stderr
@@ -16,8 +16,7 @@ LL | /     if !m.contains_key(&k) {
 LL | |         if true {
 LL | |             m.insert(k, v);
 LL | |         } else {
-LL | |             m.insert(k, v2);
-LL | |         }
+...  |
 LL | |     }
    | |_____^
    |
@@ -63,7 +62,6 @@ LL | |         if true {
 LL | |             m.insert(k, v);
 LL | |         } else {
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
@@ -154,7 +152,6 @@ LL | |         foo();
 LL | |         match 0 {
 LL | |             0 if false => {
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
diff --git a/src/tools/clippy/tests/ui/enum_variants.stderr b/src/tools/clippy/tests/ui/enum_variants.stderr
index aaac3cbb82d..ecca6c833ac 100644
--- a/src/tools/clippy/tests/ui/enum_variants.stderr
+++ b/src/tools/clippy/tests/ui/enum_variants.stderr
@@ -13,7 +13,6 @@ error: all variants have the same prefix: `c`
 LL | / enum Foo {
 LL | |
 LL | |     cFoo,
-LL | |
 ...  |
 LL | |     cBaz,
 LL | | }
@@ -45,9 +44,7 @@ error: all variants have the same prefix: `Food`
 LL | / enum Food {
 LL | |
 LL | |     FoodGood,
-LL | |
 ...  |
-LL | |
 LL | | }
    | |_^
    |
diff --git a/src/tools/clippy/tests/ui/fallible_impl_from.stderr b/src/tools/clippy/tests/ui/fallible_impl_from.stderr
index 62496148924..cc3739031b7 100644
--- a/src/tools/clippy/tests/ui/fallible_impl_from.stderr
+++ b/src/tools/clippy/tests/ui/fallible_impl_from.stderr
@@ -29,7 +29,6 @@ LL | |
 LL | |     fn from(i: usize) -> Invalid {
 LL | |         if i != 42 {
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
@@ -49,7 +48,6 @@ LL | |
 LL | |     fn from(s: Option<String>) -> Invalid {
 LL | |         let s = s.unwrap();
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
@@ -76,7 +74,6 @@ LL | |
 LL | |     fn from(s: &'a mut <Box<u32> as ProjStrTrait>::ProjString) -> Invalid {
 LL | |         if s.parse::<u32>().ok().unwrap() != 42 {
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
diff --git a/src/tools/clippy/tests/ui/if_same_then_else2.stderr b/src/tools/clippy/tests/ui/if_same_then_else2.stderr
index 93507eb2c6f..369d6f66737 100644
--- a/src/tools/clippy/tests/ui/if_same_then_else2.stderr
+++ b/src/tools/clippy/tests/ui/if_same_then_else2.stderr
@@ -7,7 +7,6 @@ LL | |         for _ in &[42] {
 LL | |             let foo: &Option<_> = &Some::<u8>(42);
 LL | |             if foo.is_some() {
 ...  |
-LL | |         }
 LL | |     } else {
    | |_____^
    |
@@ -20,7 +19,6 @@ LL | |         for _ in &[42] {
 LL | |             let bar: &Option<_> = &Some::<u8>(42);
 LL | |             if bar.is_some() {
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    = note: `-D clippy::if-same-then-else` implied by `-D warnings`
diff --git a/src/tools/clippy/tests/ui/infinite_loops.stderr b/src/tools/clippy/tests/ui/infinite_loops.stderr
index 7635a7442f4..3b5705d5f21 100644
--- a/src/tools/clippy/tests/ui/infinite_loops.stderr
+++ b/src/tools/clippy/tests/ui/infinite_loops.stderr
@@ -20,7 +20,6 @@ error: infinite loop detected
 LL | /     loop {
 LL | |
 LL | |         loop {
-LL | |
 ...  |
 LL | |         do_something();
 LL | |     }
@@ -37,9 +36,7 @@ error: infinite loop detected
 LL | /         loop {
 LL | |
 LL | |             loop {
-LL | |
-LL | |                 do_something();
-LL | |             }
+...  |
 LL | |         }
    | |_________^
    |
@@ -79,8 +76,7 @@ error: infinite loop detected
 LL | /     loop {
 LL | |         fn inner_fn() -> ! {
 LL | |             std::process::exit(0);
-LL | |         }
-LL | |         do_something();
+...  |
 LL | |     }
    | |_____^
    |
@@ -97,7 +93,6 @@ LL | |
 LL | |         loop {
 LL | |             if cond {
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
@@ -114,7 +109,6 @@ LL | |
 LL | |         'inner: loop {
 LL | |             loop {
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
@@ -145,7 +139,6 @@ LL | |
 LL | |             'inner: loop {
 LL | |                 loop {
 ...  |
-LL | |             }
 LL | |         }
    | |_________^
    |
@@ -162,7 +155,6 @@ LL | |
 LL | |         match opt {
 LL | |             Some(v) => {
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
@@ -279,7 +271,6 @@ LL | |
 LL | |         'inner: loop {
 LL | |             loop {
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
diff --git a/src/tools/clippy/tests/ui/into_iter_without_iter.stderr b/src/tools/clippy/tests/ui/into_iter_without_iter.stderr
index 533a7f68593..cde1b60c2ab 100644
--- a/src/tools/clippy/tests/ui/into_iter_without_iter.stderr
+++ b/src/tools/clippy/tests/ui/into_iter_without_iter.stderr
@@ -6,7 +6,6 @@ LL | |
 LL | |     type IntoIter = std::slice::Iter<'a, u8>;
 LL | |     type Item = &'a u8;
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
@@ -30,7 +29,6 @@ LL | |
 LL | |     type IntoIter = std::slice::IterMut<'a, u8>;
 LL | |     type Item = &'a mut u8;
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
@@ -52,7 +50,6 @@ LL | |
 LL | |     type IntoIter = std::slice::Iter<'a, T>;
 LL | |     type Item = &'a T;
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
@@ -74,7 +71,6 @@ LL | |
 LL | |     type IntoIter = std::slice::IterMut<'a, T>;
 LL | |     type Item = &'a mut T;
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
@@ -96,7 +92,6 @@ LL | |
 LL | |     type IntoIter = std::slice::IterMut<'a, T>;
 LL | |     type Item = &'a mut T;
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
@@ -117,8 +112,7 @@ LL | /         impl<'a> IntoIterator for &'a Issue12037 {
 LL | |             type IntoIter = std::slice::Iter<'a, u8>;
 LL | |             type Item = &'a u8;
 LL | |             fn into_iter(self) -> Self::IntoIter {
-LL | |                 todo!()
-LL | |             }
+...  |
 LL | |         }
    | |_________^
 ...
diff --git a/src/tools/clippy/tests/ui/manual_find.stderr b/src/tools/clippy/tests/ui/manual_find.stderr
index eb55a0c11f2..a4e7878a247 100644
--- a/src/tools/clippy/tests/ui/manual_find.stderr
+++ b/src/tools/clippy/tests/ui/manual_find.stderr
@@ -6,7 +6,6 @@ LL | |
 LL | |
 LL | |         if s == String::new() {
 ...  |
-LL | |     }
 LL | |     None
    | |________^ help: replace with an iterator: `strings.into_iter().find(|s| s == String::new())`
    |
@@ -22,7 +21,6 @@ LL | |
 LL | |
 LL | |         if s == String::new() {
 ...  |
-LL | |     }
 LL | |     None
    | |________^ help: replace with an iterator: `arr.into_iter().map(|(s, _)| s).find(|s| s == String::new())`
    |
diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.stderr b/src/tools/clippy/tests/ui/manual_find_fixable.stderr
index c3f48fb9f98..5ed8be1b3ee 100644
--- a/src/tools/clippy/tests/ui/manual_find_fixable.stderr
+++ b/src/tools/clippy/tests/ui/manual_find_fixable.stderr
@@ -4,8 +4,7 @@ error: manual implementation of `Iterator::find`
 LL | /     for &v in ARRAY {
 LL | |         if v == n {
 LL | |             return Some(v);
-LL | |         }
-LL | |     }
+...  |
 LL | |     None
    | |________^ help: replace with an iterator: `ARRAY.iter().find(|&&v| v == n).copied()`
    |
@@ -18,8 +17,7 @@ error: manual implementation of `Iterator::find`
 LL | /     for (a, _) in arr {
 LL | |         if a % 2 == 0 {
 LL | |             return Some(a);
-LL | |         }
-LL | |     }
+...  |
 LL | |     None
    | |________^ help: replace with an iterator: `arr.into_iter().map(|(a, _)| a).find(|&a| a % 2 == 0)`
 
@@ -29,8 +27,7 @@ error: manual implementation of `Iterator::find`
 LL | /     for el in arr {
 LL | |         if el.name.len() == 10 {
 LL | |             return Some(el);
-LL | |         }
-LL | |     }
+...  |
 LL | |     None
    | |________^ help: replace with an iterator: `arr.into_iter().find(|el| el.name.len() == 10)`
    |
@@ -42,8 +39,7 @@ error: manual implementation of `Iterator::find`
 LL | /     for Tuple(a, _) in arr {
 LL | |         if a >= 3 {
 LL | |             return Some(a);
-LL | |         }
-LL | |     }
+...  |
 LL | |     None
    | |________^ help: replace with an iterator: `arr.into_iter().map(|Tuple(a, _)| a).find(|&a| a >= 3)`
 
@@ -53,8 +49,7 @@ error: manual implementation of `Iterator::find`
 LL | /     for el in arr {
 LL | |         if el.should_keep() {
 LL | |             return Some(el);
-LL | |         }
-LL | |     }
+...  |
 LL | |     None
    | |________^ help: replace with an iterator: `arr.into_iter().find(|el| el.should_keep())`
    |
@@ -66,8 +61,7 @@ error: manual implementation of `Iterator::find`
 LL | /     for el in arr {
 LL | |         if f(el) == 20 {
 LL | |             return Some(el);
-LL | |         }
-LL | |     }
+...  |
 LL | |     None
    | |________^ help: replace with an iterator: `arr.into_iter().find(|&el| f(el) == 20)`
 
@@ -77,8 +71,7 @@ error: manual implementation of `Iterator::find`
 LL | /     for &el in arr.values() {
 LL | |         if f(el) {
 LL | |             return Some(el);
-LL | |         }
-LL | |     }
+...  |
 LL | |     None
    | |________^ help: replace with an iterator: `arr.values().find(|&&el| f(el)).copied()`
 
@@ -88,8 +81,7 @@ error: manual implementation of `Iterator::find`
 LL | /     for el in arr {
 LL | |         if el.is_true {
 LL | |             return Some(el);
-LL | |         }
-LL | |     }
+...  |
 LL | |     None
    | |________^ help: replace with an iterator: `arr.into_iter().find(|el| el.is_true)`
    |
@@ -101,8 +93,7 @@ error: manual implementation of `Iterator::find`
 LL | /     for (_, &x) in v {
 LL | |         if x > 10 {
 LL | |             return Some(x);
-LL | |         }
-LL | |     }
+...  |
 LL | |     None
    | |________^ help: replace with an iterator: `v.into_iter().map(|(_, &x)| x).find(|&x| x > 10)`
 
@@ -112,8 +103,7 @@ error: manual implementation of `Iterator::find`
 LL | /     for &(_, &x) in v {
 LL | |         if x > 10 {
 LL | |             return Some(x);
-LL | |         }
-LL | |     }
+...  |
 LL | |     None
    | |________^ help: replace with an iterator: `v.iter().map(|&(_, &x)| x).find(|&x| x > 10)`
 
@@ -123,8 +113,7 @@ error: manual implementation of `Iterator::find`
 LL | /     for x in arr {
 LL | |         if x >= 5 {
 LL | |             return Some(x);
-LL | |         }
-LL | |     }
+...  |
 LL | |     return None;
    | |________________^ help: replace with an iterator: `arr.into_iter().find(|&x| x >= 5)`
 
@@ -134,8 +123,7 @@ error: manual implementation of `Iterator::find`
 LL | /         for x in arr {
 LL | |             if x < 1 {
 LL | |                 return Some(x);
-LL | |             }
-LL | |         }
+...  |
 LL | |         None
    | |____________^ help: replace with an iterator: `arr.into_iter().find(|&x| x < 1)`
 
diff --git a/src/tools/clippy/tests/ui/manual_flatten.stderr b/src/tools/clippy/tests/ui/manual_flatten.stderr
index 3b64d9ef859..cf1b0a1c8bb 100644
--- a/src/tools/clippy/tests/ui/manual_flatten.stderr
+++ b/src/tools/clippy/tests/ui/manual_flatten.stderr
@@ -184,7 +184,6 @@ LL | |
 LL | |         Some(1),
 LL | |         Some(2),
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr
index 55a410982ad..dcd5d456111 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else.stderr
@@ -148,7 +148,6 @@ LL | |
 LL | |         v_some
 LL | |     } else {
 ...  |
-LL | |         }
 LL | |     };
    | |______^
    |
@@ -175,7 +174,6 @@ LL | |
 LL | |         v_some
 LL | |     } else {
 ...  |
-LL | |         }
 LL | |     };
    | |______^
    |
@@ -197,7 +195,6 @@ LL | |
 LL | |         v_some
 LL | |     } else {
 ...  |
-LL | |         }
 LL | |     };
    | |______^
    |
@@ -306,7 +303,6 @@ LL | |
 LL | |         v_some
 LL | |     } else {
 ...  |
-LL | |         }
 LL | |     };
    | |______^
    |
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.stderr b/src/tools/clippy/tests/ui/manual_unwrap_or.stderr
index c93a8952a08..a5a64ecb9a3 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.stderr
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.stderr
@@ -36,7 +36,6 @@ LL | |         Some(i) => i,
 LL | |         None => {
 LL | |             42 + 42
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -130,7 +129,6 @@ LL | |         Ok(i) => i,
 LL | |         Err(_) => {
 LL | |             42 + 42
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
index 128c95146aa..095bee52d6d 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
@@ -77,9 +77,6 @@ error: called `map(..).flatten()` on `Option`
    |
 LL |           .map(|_| {
    |  __________^
-LL | | // we need some newlines
-LL | | // so that the span is big enough
-LL | | // for a split output of the diagnostic
 ...  |
 LL | |         })
 LL | |         .flatten();
diff --git a/src/tools/clippy/tests/ui/match_bool.stderr b/src/tools/clippy/tests/ui/match_bool.stderr
index 1303e082daf..fb24e67ecee 100644
--- a/src/tools/clippy/tests/ui/match_bool.stderr
+++ b/src/tools/clippy/tests/ui/match_bool.stderr
@@ -75,9 +75,6 @@ error: you seem to be trying to match on a boolean expression
   --> tests/ui/match_bool.rs:36:5
    |
 LL | /     match test && test {
-LL | |
-LL | |
-LL | |
 ...  |
 LL | |         _ => (),
 LL | |     };
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
index 201b977e558..ffe5772ece9 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
@@ -68,8 +68,7 @@ LL |           let _ans = match x {
    |  ____________________^
 LL | |             E::A(_) => {
 LL | |                 true
-LL | |             }
-LL | |             E::B(_) => true,
+...  |
 LL | |             _ => false,
 LL | |         };
    | |_________^ help: try: `matches!(x, E::A(_) | E::B(_))`
diff --git a/src/tools/clippy/tests/ui/missing_doc.stderr b/src/tools/clippy/tests/ui/missing_doc.stderr
index 133c76ac9d4..6554eed1610 100644
--- a/src/tools/clippy/tests/ui/missing_doc.stderr
+++ b/src/tools/clippy/tests/ui/missing_doc.stderr
@@ -72,7 +72,6 @@ LL | |     /// dox
 LL | |     pub fn documented() {}
 LL | |     pub fn undocumented1() {}
 ...  |
-LL | |     }
 LL | | }
    | |_^
 
diff --git a/src/tools/clippy/tests/ui/missing_doc_crate_missing.stderr b/src/tools/clippy/tests/ui/missing_doc_crate_missing.stderr
index a421fb986d3..d6a4342c503 100644
--- a/src/tools/clippy/tests/ui/missing_doc_crate_missing.stderr
+++ b/src/tools/clippy/tests/ui/missing_doc_crate_missing.stderr
@@ -2,9 +2,7 @@ error: missing documentation for the crate
   --> tests/ui/missing_doc_crate_missing.rs:1:1
    |
 LL | / #![warn(clippy::missing_docs_in_private_items)]
-LL | |
-LL | |
-LL | |
+...  |
 LL | | fn main() {}
    | |____________^
    |
diff --git a/src/tools/clippy/tests/ui/missing_fields_in_debug.stderr b/src/tools/clippy/tests/ui/missing_fields_in_debug.stderr
index 8c1810909dd..5e51194c4b3 100644
--- a/src/tools/clippy/tests/ui/missing_fields_in_debug.stderr
+++ b/src/tools/clippy/tests/ui/missing_fields_in_debug.stderr
@@ -6,7 +6,6 @@ LL | |
 LL | |     // unused field: hidden
 LL | |     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
@@ -28,7 +27,6 @@ LL | |
 LL | |     // unused fields: hidden, hidden2, hidden4
 LL | |     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
@@ -58,7 +56,6 @@ LL | |
 LL | |     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
 LL | |         let mut f = formatter.debug_struct("MultiExprDebugImpl");
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
diff --git a/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr b/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr
index 9d3f639efbf..682140a1dfd 100644
--- a/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/needless_for_each_unfixable.stderr
@@ -6,7 +6,6 @@ LL | |
 LL | |
 LL | |         if *v == 10 {
 ...  |
-LL | |         }
 LL | |     });
    | |_______^
    |
diff --git a/src/tools/clippy/tests/ui/needless_if.stderr b/src/tools/clippy/tests/ui/needless_if.stderr
index 9beae596ee3..cbfeb979d2f 100644
--- a/src/tools/clippy/tests/ui/needless_if.stderr
+++ b/src/tools/clippy/tests/ui/needless_if.stderr
@@ -34,7 +34,6 @@ error: this `if` branch is empty
 LL | /     if {
 LL | |         if let true = true
 LL | |             && true
-LL | |         {
 ...  |
 LL | |     } && true
 LL | |     {}
diff --git a/src/tools/clippy/tests/ui/never_loop.stderr b/src/tools/clippy/tests/ui/never_loop.stderr
index 440a2b5aaba..dab3488af10 100644
--- a/src/tools/clippy/tests/ui/never_loop.stderr
+++ b/src/tools/clippy/tests/ui/never_loop.stderr
@@ -2,9 +2,6 @@ error: this loop never actually loops
   --> tests/ui/never_loop.rs:12:5
    |
 LL | /     loop {
-LL | |
-LL | |
-LL | |         // clippy::never_loop
 ...  |
 LL | |         break;
 LL | |     }
@@ -75,7 +72,6 @@ LL | |
 LL | |         // never loops
 LL | |         match x {
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
@@ -126,7 +122,6 @@ LL | |
 LL | |         'b: {
 LL | |             break 'b 'c: {
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
 
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr
index 37ef791edb0..32ff2276323 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.stderr
+++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr
@@ -115,8 +115,7 @@ LL |       let _ = if let Some(x) = arg {
    |  _____________^
 LL | |         x
 LL | |     } else {
-LL | |         // map_or_else must be suggested
-LL | |         side_effect()
+...  |
 LL | |     };
    | |_____^ help: try: `arg.map_or_else(side_effect, |x| x)`
 
diff --git a/src/tools/clippy/tests/ui/question_mark.stderr b/src/tools/clippy/tests/ui/question_mark.stderr
index 0a48c4e80cb..06a8bd0de34 100644
--- a/src/tools/clippy/tests/ui/question_mark.stderr
+++ b/src/tools/clippy/tests/ui/question_mark.stderr
@@ -183,8 +183,7 @@ error: this block may be rewritten with the `?` operator
    |
 LL | /             if a.is_none() {
 LL | |                 return None;
-LL | |                 // do lint here, the outer `try` is not relevant here
-LL | |                 // https://github.com/rust-lang/rust-clippy/pull/11001#issuecomment-1610636867
+...  |
 LL | |             }
    | |_____________^ help: replace it with: `a?;`
 
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.stderr b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr
index 2d7da4f394d..7d7e3ac7d0a 100644
--- a/src/tools/clippy/tests/ui/significant_drop_tightening.stderr
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr
@@ -5,8 +5,7 @@ LL |   pub fn complex_return_triggers_the_lint() -> i32 {
    |  __________________________________________________-
 LL | |     fn foo() -> i32 {
 LL | |         1
-LL | |     }
-LL | |     let mutex = Mutex::new(1);
+...  |
 LL | |     let lock = mutex.lock().unwrap();
    | |         ^^^^
 ...  |
diff --git a/src/tools/clippy/tests/ui/single_match.stderr b/src/tools/clippy/tests/ui/single_match.stderr
index 9240b09c50a..dd03737279a 100644
--- a/src/tools/clippy/tests/ui/single_match.stderr
+++ b/src/tools/clippy/tests/ui/single_match.stderr
@@ -22,10 +22,7 @@ error: you seem to be trying to use `match` for destructuring a single pattern.
   --> tests/ui/single_match.rs:23:5
    |
 LL | /     match x {
-LL | |         // Note the missing block braces.
-LL | |         // We suggest `if let Some(y) = x { .. }` because the macro
-LL | |         // is expanded before we can do anything.
-LL | |         Some(y) => println!("{:?}", y),
+...  |
 LL | |         _ => (),
 LL | |     }
    | |_____^ help: try: `if let Some(y) = x { println!("{:?}", y) }`
diff --git a/src/tools/clippy/tests/ui/single_match_else.stderr b/src/tools/clippy/tests/ui/single_match_else.stderr
index a2801751a43..aa494520b84 100644
--- a/src/tools/clippy/tests/ui/single_match_else.stderr
+++ b/src/tools/clippy/tests/ui/single_match_else.stderr
@@ -68,8 +68,7 @@ LL | /     match Result::<i32, &Infallible>::Ok(1) {
 LL | |         Ok(a) => println!("${:?}", a),
 LL | |         Err(_) => {
 LL | |             println!("else block");
-LL | |             return;
-LL | |         }
+...  |
 LL | |     }
    | |_____^
    |
@@ -88,8 +87,7 @@ LL | /     match Cow::from("moo") {
 LL | |         Cow::Owned(a) => println!("${:?}", a),
 LL | |         Cow::Borrowed(_) => {
 LL | |             println!("else block");
-LL | |             return;
-LL | |         }
+...  |
 LL | |     }
    | |_____^
    |
diff --git a/src/tools/clippy/tests/ui/temporary_assignment.stderr b/src/tools/clippy/tests/ui/temporary_assignment.stderr
index 8c284594075..7e6529cb213 100644
--- a/src/tools/clippy/tests/ui/temporary_assignment.stderr
+++ b/src/tools/clippy/tests/ui/temporary_assignment.stderr
@@ -13,8 +13,7 @@ error: assignment to temporary
 LL | /     MultiStruct {
 LL | |
 LL | |         structure: Struct { field: 0 },
-LL | |     }
-LL | |     .structure
+...  |
 LL | |     .field = 1;
    | |______________^
 
diff --git a/src/tools/clippy/tests/ui/unit_cmp.stderr b/src/tools/clippy/tests/ui/unit_cmp.stderr
index f9473d3be26..9e067edb846 100644
--- a/src/tools/clippy/tests/ui/unit_cmp.stderr
+++ b/src/tools/clippy/tests/ui/unit_cmp.stderr
@@ -34,7 +34,6 @@ LL | |
 LL | |         {
 LL | |             true;
 ...  |
-LL | |         }
 LL | |     );
    | |_____^
 
@@ -46,7 +45,6 @@ LL | |
 LL | |         {
 LL | |             true;
 ...  |
-LL | |         }
 LL | |     );
    | |_____^
 
@@ -58,7 +56,6 @@ LL | |
 LL | |         {
 LL | |             true;
 ...  |
-LL | |         }
 LL | |     );
    | |_____^
 
@@ -70,7 +67,6 @@ LL | |
 LL | |         {
 LL | |             true;
 ...  |
-LL | |         }
 LL | |     );
    | |_____^
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
index bcdf65b217e..35a2144c389 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
@@ -434,11 +434,7 @@ error: unnecessary closure used to substitute value for `Result::Err`
    |
 LL |       let _: Result<usize, usize> = res.
    |  ___________________________________^
-LL | |     // some lines
-LL | |     // some lines
-LL | |     // some lines
 ...  |
-LL | |     // some lines
 LL | |     or_else(|_| Ok(ext_str.some_field));
    | |_______________________________________^
    |
diff --git a/src/tools/clippy/tests/ui/unnecessary_wraps.stderr b/src/tools/clippy/tests/ui/unnecessary_wraps.stderr
index 59986d895b3..b304d4dce6e 100644
--- a/src/tools/clippy/tests/ui/unnecessary_wraps.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_wraps.stderr
@@ -6,7 +6,6 @@ LL | |
 LL | |
 LL | |     if a && b {
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
@@ -112,7 +111,6 @@ LL | |
 LL | |     if a && b {
 LL | |         return Some(());
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
@@ -139,7 +137,6 @@ LL | |
 LL | |     if a && b {
 LL | |         return Ok(());
 ...  |
-LL | |     }
 LL | | }
    | |_^
    |
diff --git a/src/tools/clippy/tests/ui/unwrap_in_result.stderr b/src/tools/clippy/tests/ui/unwrap_in_result.stderr
index 752177aaca5..201d4ae36ae 100644
--- a/src/tools/clippy/tests/ui/unwrap_in_result.stderr
+++ b/src/tools/clippy/tests/ui/unwrap_in_result.stderr
@@ -6,7 +6,6 @@ LL | |
 LL | |         // checks whether a string represents a number divisible by 3
 LL | |         let i = i_str.parse::<i32>().unwrap();
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
    |
diff --git a/src/tools/clippy/tests/ui/vec_init_then_push.stderr b/src/tools/clippy/tests/ui/vec_init_then_push.stderr
index 58720c9a181..f35625c9b08 100644
--- a/src/tools/clippy/tests/ui/vec_init_then_push.stderr
+++ b/src/tools/clippy/tests/ui/vec_init_then_push.stderr
@@ -2,8 +2,7 @@ error: calls to `push` immediately after creation
   --> tests/ui/vec_init_then_push.rs:5:5
    |
 LL | /     let mut def_err: Vec<u32> = Default::default();
-LL | |
-LL | |
+...  |
 LL | |     def_err.push(0);
    | |____________________^ help: consider using the `vec![]` macro: `let def_err: Vec<u32> = vec![..];`
    |
diff --git a/src/tools/clippy/tests/ui/while_let_loop.stderr b/src/tools/clippy/tests/ui/while_let_loop.stderr
index 5212d4fdcc7..10c2311d82f 100644
--- a/src/tools/clippy/tests/ui/while_let_loop.stderr
+++ b/src/tools/clippy/tests/ui/while_let_loop.stderr
@@ -6,7 +6,6 @@ LL | |
 LL | |
 LL | |         if let Some(_x) = y {
 ...  |
-LL | |         }
 LL | |     }
    | |_____^ help: try: `while let Some(_x) = y { .. }`
    |
@@ -45,7 +44,6 @@ LL | |
 LL | |         let x = match y {
 LL | |             Some(x) => x,
 ...  |
-LL | |         }
 LL | |     }
    | |_____^ help: try: `while let Some(x) = y { .. }`
 
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index ff62667f9b8..68131efa387 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-f4f0fafd0c7849e162eddbc69fa5fe82dbec28c7
+7caf35b2e5401d7740fdc567fdc388059208150b
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 7a85b4a4a6f..ea11093a17a 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -149,10 +149,9 @@ pub fn iter_exported_symbols<'tcx>(
     let dependency_formats = tcx.dependency_formats(());
     // Find the dependencies of the executable we are running.
     let dependency_format = dependency_formats
-        .iter()
-        .find(|(crate_type, _)| *crate_type == CrateType::Executable)
+        .get(&CrateType::Executable)
         .expect("interpreting a non-executable crate");
-    for cnum in dependency_format.1.iter().enumerate().filter_map(|(num, &linkage)| {
+    for cnum in dependency_format.iter().enumerate().filter_map(|(num, &linkage)| {
         // We add 1 to the number because that's what rustc also does everywhere it
         // calls `CrateNum::new`...
         #[expect(clippy::arithmetic_side_effects)]
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 7cc22f83a24..ac26feb345c 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -1571,8 +1571,12 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
         res
     }
 
-    fn after_local_read(ecx: &InterpCx<'tcx, Self>, local: mir::Local) -> InterpResult<'tcx> {
-        if let Some(data_race) = &ecx.frame().extra.data_race {
+    fn after_local_read(
+        ecx: &InterpCx<'tcx, Self>,
+        frame: &Frame<'tcx, Provenance, FrameExtra<'tcx>>,
+        local: mir::Local,
+    ) -> InterpResult<'tcx> {
+        if let Some(data_race) = &frame.extra.data_race {
             data_race.local_read(local, &ecx.machine);
         }
         interp_ok(())
diff --git a/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr
index 23a9f8f9c28..6540543d8da 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr
+++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr
@@ -24,8 +24,7 @@ note: inside `main`
 LL | /     thread::spawn(|| {
 LL | |         unsafe {
 LL | |             assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), WAIT_OBJECT_0);
-LL | |         }
-LL | |     })
+...  |
 LL | |     .join()
    | |___________^
 
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
index d9ab782986f..2875a5be285 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
@@ -14,7 +14,6 @@ LL | |         let _unit: ();
 LL | |         {
 LL | |             let non_copy = S(42);
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
 help: <TAG> is this argument
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
index 677952b39da..c699987b796 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
@@ -16,7 +16,6 @@ LL | |         let _unit: ();
 LL | |         {
 LL | |             let non_copy = S(42);
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
 help: the protected tag <TAG> was created here, in the initial state Reserved
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
index efdd6129d74..f20ec00f97b 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
@@ -14,7 +14,6 @@ LL | |         let _unit: ();
 LL | |         {
 LL | |             let non_copy = S(42);
 ...  |
-LL | |
 LL | |     }
    | |_____^
 help: <TAG> is this argument
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
index 5746ad1e13d..8996c3643db 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
@@ -16,7 +16,6 @@ LL | |         let _unit: ();
 LL | |         {
 LL | |             let non_copy = S(42);
 ...  |
-LL | |
 LL | |     }
    | |_____^
 help: the protected tag <TAG> was created here, in the initial state Reserved
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr
index b009b0901c4..47e5ee48292 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr
@@ -14,7 +14,6 @@ LL | |         {
 LL | |             let x = 0;
 LL | |             let ptr = &raw mut x;
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
 help: <TAG> is this argument
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr
index 6d2cbe9b7cd..7eb237ca1a7 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr
@@ -16,7 +16,6 @@ LL | |         {
 LL | |             let x = 0;
 LL | |             let ptr = &raw mut x;
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
 help: the protected tag <TAG> was created here, in the initial state Reserved
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr
index 54f9a7aebd6..813042f06a6 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr
@@ -14,7 +14,6 @@ LL | |         {
 LL | |             let _x = 0;
 LL | |             let ptr = &raw mut _x;
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
 help: <TAG> is this argument
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr
index 693534be2e0..5090ec06b78 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr
@@ -16,7 +16,6 @@ LL | |         {
 LL | |             let _x = 0;
 LL | |             let ptr = &raw mut _x;
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
 help: the protected tag <TAG> was created here, in the initial state Reserved
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr
index 520937beaeb..a6a0362a226 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr
@@ -14,7 +14,6 @@ LL | |         {
 LL | |             let _x = 0;
 LL | |             let ptr = &raw mut _x;
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
 help: <TAG> is this argument
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr
index a879189d0c1..26a54fe8748 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr
@@ -16,7 +16,6 @@ LL | |         {
 LL | |             let _x = 0;
 LL | |             let ptr = &raw mut _x;
 ...  |
-LL | |         }
 LL | |     }
    | |_____^
 help: the protected tag <TAG> was created here, in the initial state Reserved
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index 77c9818b66b..16b7e7aa709 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -413,7 +413,8 @@ pub(crate) fn format_expr(
         ast::ExprKind::FormatArgs(..)
         | ast::ExprKind::Type(..)
         | ast::ExprKind::IncludedBytes(..)
-        | ast::ExprKind::OffsetOf(..) => {
+        | ast::ExprKind::OffsetOf(..)
+        | ast::ExprKind::UnsafeBinderCast(..) => {
             // These don't normally occur in the AST because macros aren't expanded. However,
             // rustfmt tries to parse macro arguments when formatting macros, so it's not totally
             // impossible for rustfmt to come across one of these nodes when formatting a file.
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index 18932587f1f..c3debc2f4f0 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -3597,7 +3597,7 @@ pub(crate) fn rewrite_extern_crate(
 pub(crate) fn is_mod_decl(item: &ast::Item) -> bool {
     !matches!(
         item.kind,
-        ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _))
+        ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _))
     )
 }
 
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index 493b04f16c6..a40ee7f66a9 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -316,12 +316,11 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
             self.directory = directory;
         }
         match (sub_mod.ast_mod_kind, sub_mod.items) {
-            (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => {
+            (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _, _))), _) => {
                 self.visit_mod_from_ast(items)
             }
-            (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => {
-                self.visit_mod_outside_ast(items)
-            }
+            (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _, _))), _)
+            | (_, Cow::Owned(items)) => self.visit_mod_outside_ast(items),
             (_, _) => Ok(()),
         }
     }
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index dd4a788c002..f8b713117f4 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -1016,6 +1016,31 @@ impl Rewrite for ast::Ty {
                 let pat = pat.rewrite_result(context, shape)?;
                 Ok(format!("{ty} is {pat}"))
             }
+            ast::TyKind::UnsafeBinder(ref binder) => {
+                let mut result = String::new();
+                if let Some(ref lifetime_str) =
+                    rewrite_bound_params(context, shape, &binder.generic_params)
+                {
+                    result.push_str("unsafe<");
+                    result.push_str(lifetime_str);
+                    result.push_str("> ");
+                }
+
+                let inner_ty_shape = if context.use_block_indent() {
+                    shape
+                        .offset_left(result.len())
+                        .max_width_error(shape.width, self.span())?
+                } else {
+                    shape
+                        .visual_indent(result.len())
+                        .sub_width(result.len())
+                        .max_width_error(shape.width, self.span())?
+                };
+
+                let rewrite = binder.inner_ty.rewrite_result(context, inner_ty_shape)?;
+                result.push_str(&rewrite);
+                Ok(result)
+            }
         }
     }
 }
diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs
index 0ca34a79491..ba4a4c045f1 100644
--- a/src/tools/rustfmt/src/utils.rs
+++ b/src/tools/rustfmt/src/utils.rs
@@ -504,6 +504,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr
         | ast::ExprKind::IncludedBytes(..)
         | ast::ExprKind::InlineAsm(..)
         | ast::ExprKind::OffsetOf(..)
+        | ast::ExprKind::UnsafeBinderCast(..)
         | ast::ExprKind::Let(..)
         | ast::ExprKind::Path(..)
         | ast::ExprKind::Range(..)
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 9b116b620b7..805e13b7803 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -927,7 +927,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         let ident_str = rewrite_ident(&self.get_context(), ident).to_owned();
         self.push_str(&ident_str);
 
-        if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans) = mod_kind {
+        if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans, _) = mod_kind {
             let ast::ModSpans {
                 inner_span,
                 inject_use_span: _,
diff --git a/src/tools/rustfmt/tests/source/unsafe-binders.rs b/src/tools/rustfmt/tests/source/unsafe-binders.rs
new file mode 100644
index 00000000000..ccf7c8bb9af
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/unsafe-binders.rs
@@ -0,0 +1,11 @@
+fn foo() -> unsafe<'a>
+&'a () {}
+
+struct Foo {
+    x: unsafe<'a>
+&'a (),
+}
+
+struct Bar(unsafe<'a> &'a ());
+
+impl Trait for unsafe<'a> &'a () {}
diff --git a/src/tools/rustfmt/tests/target/unsafe-binders.rs b/src/tools/rustfmt/tests/target/unsafe-binders.rs
new file mode 100644
index 00000000000..9d308f4a894
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/unsafe-binders.rs
@@ -0,0 +1,9 @@
+fn foo() -> unsafe<'a> &'a () {}
+
+struct Foo {
+    x: unsafe<'a> &'a (),
+}
+
+struct Bar(unsafe<'a> &'a ());
+
+impl Trait for unsafe<'a> &'a () {}
diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs
index e62adfa0ba6..0b2229ba7d1 100644
--- a/tests/codegen/mem-replace-big-type.rs
+++ b/tests/codegen/mem-replace-big-type.rs
@@ -25,9 +25,10 @@ pub fn replace_big(dst: &mut Big, src: Big) -> Big {
 // CHECK-NOT: call void @llvm.memcpy
 
 // For a large type, we expect exactly three `memcpy`s
-// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret([56 x i8])
+// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}(ptr
+// CHECK-SAME: sret([56 x i8]){{.+}}[[RESULT:%.+]], ptr{{.+}}%dest, ptr{{.+}}%src)
 // CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %result, ptr align 8 %dest, i{{.*}} 56, i1 false)
+// CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 [[RESULT]], ptr align 8 %dest, i{{.*}} 56, i1 false)
 // CHECK-NOT: call void @llvm.memcpy
 // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %dest, ptr align 8 %src, i{{.*}} 56, i1 false)
 // CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/crashes/123861.rs b/tests/crashes/123861.rs
deleted file mode 100644
index 60245960af0..00000000000
--- a/tests/crashes/123861.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-//@ known-bug: #123861
-//@ needs-rustc-debug-assertions
-
-struct _;
-fn mainIterator<_ = _> {}
diff --git a/tests/crashes/132765.rs b/tests/crashes/132765.rs
new file mode 100644
index 00000000000..01e8fdaacff
--- /dev/null
+++ b/tests/crashes/132765.rs
@@ -0,0 +1,12 @@
+//@ known-bug: #132765
+
+trait LendingIterator {
+    type Item<'q>;
+    fn for_each(&self, _f: Box<fn(Self::Item<'_>)>) {}
+}
+
+fn f(_: ()) {}
+
+fn main() {
+    LendingIterator::for_each(&(), f);
+}
diff --git a/tests/crashes/132766.rs b/tests/crashes/132766.rs
new file mode 100644
index 00000000000..5f5117d77a5
--- /dev/null
+++ b/tests/crashes/132766.rs
@@ -0,0 +1,9 @@
+//@ known-bug: #132766
+
+trait Trait {}
+impl<'a> Trait for () {
+    fn pass2<'a>() -> impl Trait2 {}
+}
+
+trait Trait2 {}
+impl Trait2 for () {}
diff --git a/tests/crashes/132882.rs b/tests/crashes/132882.rs
new file mode 100644
index 00000000000..6b5e4dba803
--- /dev/null
+++ b/tests/crashes/132882.rs
@@ -0,0 +1,13 @@
+//@ known-bug: #132882
+
+use std::ops::Add;
+
+pub trait Numoid
+where
+    for<N: Numoid> &'a Self: Add<Self>,
+{
+}
+
+pub fn compute<N: Numoid>(a: N) -> N {
+    &a + a
+}
diff --git a/tests/crashes/132981.rs b/tests/crashes/132981.rs
new file mode 100644
index 00000000000..8ff4fa36fd0
--- /dev/null
+++ b/tests/crashes/132981.rs
@@ -0,0 +1,7 @@
+//@ known-bug: #132981
+//@compile-flags: -Clink-dead-code=true --crate-type lib
+//@ only-x86_64
+//@ ignore-windows
+
+#![feature(rust_cold_cc)]
+pub extern "rust-cold" fn foo(_: [usize; 3]) {}
diff --git a/tests/crashes/133063.rs b/tests/crashes/133063.rs
new file mode 100644
index 00000000000..132b5486170
--- /dev/null
+++ b/tests/crashes/133063.rs
@@ -0,0 +1,8 @@
+//@ known-bug: #133063
+
+fn foo(x: !) {
+    match x {
+        (! | !) if false => {}
+        _ => {}
+    }
+}
diff --git a/tests/crashes/133066.rs b/tests/crashes/133066.rs
new file mode 100644
index 00000000000..732ebb7079f
--- /dev/null
+++ b/tests/crashes/133066.rs
@@ -0,0 +1,12 @@
+//@ known-bug: #133066
+trait Owner {
+    const C<const N: u32>: u32;
+}
+
+impl Owner for () {;}
+
+fn take0<const N: u64>(_: impl Owner<C<N> = { N }>) {}
+
+fn main() {
+    take0::<f32, >(());
+}
diff --git a/tests/crashes/133199.rs b/tests/crashes/133199.rs
new file mode 100644
index 00000000000..76535fa83a6
--- /dev/null
+++ b/tests/crashes/133199.rs
@@ -0,0 +1,11 @@
+//@ known-bug: #133199
+//@ aux-build: aux133199.rs
+
+extern crate aux133199;
+
+use aux133199::FixedBitSet;
+
+fn main() {
+    FixedBitSet::<7>::new();
+    //~^ ERROR
+}
diff --git a/tests/crashes/133275-1.rs b/tests/crashes/133275-1.rs
new file mode 100644
index 00000000000..73c04f5d6e4
--- /dev/null
+++ b/tests/crashes/133275-1.rs
@@ -0,0 +1,13 @@
+//@ known-bug: #133275
+#![feature(const_trait_impl)]
+#![feature(associated_type_defaults)]
+
+#[const_trait]
+trait Foo3<T>
+where
+    Self::Baz: Clone,
+{
+    type Baz = T;
+}
+
+pub fn main() {}
diff --git a/tests/crashes/133275-2.rs b/tests/crashes/133275-2.rs
new file mode 100644
index 00000000000..a774b3cdb69
--- /dev/null
+++ b/tests/crashes/133275-2.rs
@@ -0,0 +1,15 @@
+//@ known-bug: #133275
+#![feature(const_trait_impl)]
+#[const_trait]
+pub trait Owo<X = <IntEnum as Uwu>::T> {}
+
+#[const_trait]
+trait Foo3<T>
+where
+    Self::Bar: Clone,
+    Self::Baz: Clone,
+{
+    type Bar = Vec<Self::Baz>;
+    type Baz = T;
+    //~^ ERROR the trait bound `T: Clone` is not satisfied
+}
diff --git a/tests/crashes/133426.rs b/tests/crashes/133426.rs
new file mode 100644
index 00000000000..307a94c0f6c
--- /dev/null
+++ b/tests/crashes/133426.rs
@@ -0,0 +1,12 @@
+//@ known-bug: #133426
+
+fn a(
+    _: impl Iterator<
+        Item = [(); {
+                   match *todo!() { ! };
+               }],
+    >,
+) {
+}
+
+fn b(_: impl Iterator<Item = { match 0 { ! } }>) {}
diff --git a/tests/crashes/133597.rs b/tests/crashes/133597.rs
new file mode 100644
index 00000000000..f716d5e7bc7
--- /dev/null
+++ b/tests/crashes/133597.rs
@@ -0,0 +1,11 @@
+//@ known-bug: #133597
+
+pub trait Foo2 {
+    fn boxed<'a: 'a>() -> impl Sized + FnOnce<()>;
+}
+
+impl Foo2 for () {}
+
+
+fn f() -> impl FnOnce<()> { || () }
+fn main() { () = f(); }
diff --git a/tests/crashes/133639.rs b/tests/crashes/133639.rs
new file mode 100644
index 00000000000..d522b0730cf
--- /dev/null
+++ b/tests/crashes/133639.rs
@@ -0,0 +1,33 @@
+//@ known-bug: #133639
+
+#![feature(with_negative_coherence)]
+#![feature(min_specialization)]
+#![feature(generic_const_exprs)]
+
+#![crate_type = "lib"]
+use std::str::FromStr;
+
+struct a<const b: bool>;
+
+trait c {}
+
+impl<const d: u32> FromStr for e<d>
+where
+    a<{ d <= 2 }>: c,
+{
+    type Err = ();
+    fn from_str(f: &str) -> Result<Self, Self::Err> {
+        unimplemented!()
+    }
+}
+struct e<const d: u32>;
+
+impl<const d: u32> FromStr for e<d>
+where
+    a<{ d <= 2 }>: c,
+{
+    type Err = ();
+    fn from_str(f: &str) -> Result<Self, Self::Err> {
+        unimplemented!()
+    }
+}
diff --git a/tests/crashes/133808.rs b/tests/crashes/133808.rs
new file mode 100644
index 00000000000..9c6a23d1e35
--- /dev/null
+++ b/tests/crashes/133808.rs
@@ -0,0 +1,15 @@
+//@ known-bug: #133808
+
+#![feature(generic_const_exprs, transmutability)]
+
+mod assert {
+    use std::mem::TransmuteFrom;
+
+    pub fn is_transmutable<Src, Dst>()
+    where
+        Dst: TransmuteFrom<Src>,
+    {
+    }
+}
+
+pub fn main() {}
diff --git a/tests/crashes/133868.rs b/tests/crashes/133868.rs
new file mode 100644
index 00000000000..dc25cb9df28
--- /dev/null
+++ b/tests/crashes/133868.rs
@@ -0,0 +1,13 @@
+//@ known-bug: #133868
+
+trait Foo {
+    type Assoc;
+}
+
+trait Bar {
+    fn method() -> impl Sized;
+}
+impl<T> Bar for T where <T as Foo>::Assoc: Sized
+{
+    fn method() {}
+}
diff --git a/tests/crashes/133965.rs b/tests/crashes/133965.rs
new file mode 100644
index 00000000000..69f533ccbe9
--- /dev/null
+++ b/tests/crashes/133965.rs
@@ -0,0 +1,9 @@
+//@ known-bug: #133965
+//@ needs-rustc-debug-assertions
+
+struct NonGeneric {}
+
+#[derive(Default)]
+struct NonGeneric<'a, const N: usize> {}
+
+pub fn main() {}
diff --git a/tests/crashes/133966.rs b/tests/crashes/133966.rs
new file mode 100644
index 00000000000..25a881ae99b
--- /dev/null
+++ b/tests/crashes/133966.rs
@@ -0,0 +1,3 @@
+//@ known-bug: #133966
+pub struct Data([[&'static str]; 5_i32]);
+const _: &'static Data = unsafe { &*(&[] as *const Data) };
diff --git a/tests/crashes/134005.rs b/tests/crashes/134005.rs
new file mode 100644
index 00000000000..c1f4c758a14
--- /dev/null
+++ b/tests/crashes/134005.rs
@@ -0,0 +1,5 @@
+//@ known-bug: #134005
+
+fn main() {
+    let _ = [std::ops::Add::add, std::ops::Mul::mul, main as fn(_, &_)];
+}
diff --git a/tests/crashes/134061.rs b/tests/crashes/134061.rs
new file mode 100644
index 00000000000..e00eb7603fe
--- /dev/null
+++ b/tests/crashes/134061.rs
@@ -0,0 +1,4 @@
+//@ known-bug: #134061
+//@ needs-rustc-debug-assertions
+
+const x: () = |&'a
diff --git a/tests/crashes/134217.rs b/tests/crashes/134217.rs
new file mode 100644
index 00000000000..1b14c660e8b
--- /dev/null
+++ b/tests/crashes/134217.rs
@@ -0,0 +1,9 @@
+//@ known-bug: #134217
+
+impl<A> std::ops::CoerceUnsized<A> for A {}
+
+fn main() {
+    if let _ = true
+        && true
+    {}
+}
diff --git a/tests/crashes/auxiliary/aux133199.rs b/tests/crashes/auxiliary/aux133199.rs
new file mode 100644
index 00000000000..40765d92fbf
--- /dev/null
+++ b/tests/crashes/auxiliary/aux133199.rs
@@ -0,0 +1,13 @@
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+pub struct FixedBitSet<const N: usize>;
+
+impl<const N: usize> FixedBitSet<N>
+where
+    [u8; N.div_ceil(8)]: Sized,
+{
+    pub fn new() -> Self {
+        todo!()
+    }
+}
diff --git a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir
index a467987e886..8d9176ef301 100644
--- a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir
+++ b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir
@@ -7,8 +7,7 @@ fn main() -> () {
     let mut _5: u32;
     let mut _6: *mut usize;
     let _7: usize;
-    let mut _8: usize;
-    let mut _9: bool;
+    let mut _8: bool;
     scope 1 {
         debug x => _1;
         let mut _2: usize;
@@ -41,9 +40,8 @@ fn main() -> () {
         StorageDead(_6);
         StorageLive(_7);
         _7 = copy _2;
-        _8 = Len(_1);
-        _9 = Lt(copy _7, copy _8);
-        assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind unreachable];
+        _8 = Lt(copy _7, const 3_usize);
+        assert(move _8, "index out of bounds: the length is {} but the index is {}", const 3_usize, copy _7) -> [success: bb2, unwind unreachable];
     }
 
     bb2: {
diff --git a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir
index bd7365543bd..e1df0e3e2a3 100644
--- a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir
+++ b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir
@@ -7,8 +7,7 @@ fn main() -> () {
     let mut _5: u32;
     let mut _6: *mut usize;
     let _7: usize;
-    let mut _8: usize;
-    let mut _9: bool;
+    let mut _8: bool;
     scope 1 {
         debug x => _1;
         let mut _2: usize;
@@ -41,9 +40,8 @@ fn main() -> () {
         StorageDead(_6);
         StorageLive(_7);
         _7 = copy _2;
-        _8 = Len(_1);
-        _9 = Lt(copy _7, copy _8);
-        assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind continue];
+        _8 = Lt(copy _7, const 3_usize);
+        assert(move _8, "index out of bounds: the length is {} but the index is {}", const 3_usize, copy _7) -> [success: bb2, unwind continue];
     }
 
     bb2: {
diff --git a/tests/mir-opt/building/index_array_and_slice.index_array.built.after.mir b/tests/mir-opt/building/index_array_and_slice.index_array.built.after.mir
new file mode 100644
index 00000000000..d28a2031013
--- /dev/null
+++ b/tests/mir-opt/building/index_array_and_slice.index_array.built.after.mir
@@ -0,0 +1,31 @@
+// MIR for `index_array` after built
+
+fn index_array(_1: &[i32; 7], _2: usize) -> &i32 {
+    debug array => _1;
+    debug index => _2;
+    let mut _0: &i32;
+    let _3: &i32;
+    let _4: usize;
+    let mut _5: bool;
+
+    bb0: {
+        StorageLive(_3);
+        StorageLive(_4);
+        _4 = copy _2;
+        FakeRead(ForIndex, (*_1));
+        _5 = Lt(copy _4, const 7_usize);
+        assert(move _5, "index out of bounds: the length is {} but the index is {}", const 7_usize, copy _4) -> [success: bb1, unwind: bb2];
+    }
+
+    bb1: {
+        _3 = &(*_1)[_4];
+        _0 = &(*_3);
+        StorageDead(_4);
+        StorageDead(_3);
+        return;
+    }
+
+    bb2 (cleanup): {
+        resume;
+    }
+}
diff --git a/tests/mir-opt/building/index_array_and_slice.index_const_generic_array.built.after.mir b/tests/mir-opt/building/index_array_and_slice.index_const_generic_array.built.after.mir
new file mode 100644
index 00000000000..e9627532c38
--- /dev/null
+++ b/tests/mir-opt/building/index_array_and_slice.index_const_generic_array.built.after.mir
@@ -0,0 +1,31 @@
+// MIR for `index_const_generic_array` after built
+
+fn index_const_generic_array(_1: &[i32; N], _2: usize) -> &i32 {
+    debug array => _1;
+    debug index => _2;
+    let mut _0: &i32;
+    let _3: &i32;
+    let _4: usize;
+    let mut _5: bool;
+
+    bb0: {
+        StorageLive(_3);
+        StorageLive(_4);
+        _4 = copy _2;
+        FakeRead(ForIndex, (*_1));
+        _5 = Lt(copy _4, const N);
+        assert(move _5, "index out of bounds: the length is {} but the index is {}", const N, copy _4) -> [success: bb1, unwind: bb2];
+    }
+
+    bb1: {
+        _3 = &(*_1)[_4];
+        _0 = &(*_3);
+        StorageDead(_4);
+        StorageDead(_3);
+        return;
+    }
+
+    bb2 (cleanup): {
+        resume;
+    }
+}
diff --git a/tests/mir-opt/building/index_array_and_slice.index_custom.built.after.mir b/tests/mir-opt/building/index_array_and_slice.index_custom.built.after.mir
new file mode 100644
index 00000000000..00f2b7e07d5
--- /dev/null
+++ b/tests/mir-opt/building/index_array_and_slice.index_custom.built.after.mir
@@ -0,0 +1,34 @@
+// MIR for `index_custom` after built
+
+fn index_custom(_1: &WithSliceTail, _2: usize) -> &i32 {
+    debug custom => _1;
+    debug index => _2;
+    let mut _0: &i32;
+    let _3: &i32;
+    let _4: usize;
+    let mut _5: *const [i32];
+    let mut _6: usize;
+    let mut _7: bool;
+
+    bb0: {
+        StorageLive(_3);
+        StorageLive(_4);
+        _4 = copy _2;
+        _5 = &raw const ((*_1).1: [i32]);
+        _6 = PtrMetadata(move _5);
+        _7 = Lt(copy _4, copy _6);
+        assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _4) -> [success: bb1, unwind: bb2];
+    }
+
+    bb1: {
+        _3 = &((*_1).1: [i32])[_4];
+        _0 = &(*_3);
+        StorageDead(_4);
+        StorageDead(_3);
+        return;
+    }
+
+    bb2 (cleanup): {
+        resume;
+    }
+}
diff --git a/tests/mir-opt/building/index_array_and_slice.index_mut_slice.built.after.mir b/tests/mir-opt/building/index_array_and_slice.index_mut_slice.built.after.mir
new file mode 100644
index 00000000000..cb0b2f600c8
--- /dev/null
+++ b/tests/mir-opt/building/index_array_and_slice.index_mut_slice.built.after.mir
@@ -0,0 +1,34 @@
+// MIR for `index_mut_slice` after built
+
+fn index_mut_slice(_1: &mut [i32], _2: usize) -> &i32 {
+    debug slice => _1;
+    debug index => _2;
+    let mut _0: &i32;
+    let _3: &i32;
+    let _4: usize;
+    let mut _5: *const [i32];
+    let mut _6: usize;
+    let mut _7: bool;
+
+    bb0: {
+        StorageLive(_3);
+        StorageLive(_4);
+        _4 = copy _2;
+        _5 = &raw const (*_1);
+        _6 = PtrMetadata(move _5);
+        _7 = Lt(copy _4, copy _6);
+        assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _4) -> [success: bb1, unwind: bb2];
+    }
+
+    bb1: {
+        _3 = &(*_1)[_4];
+        _0 = &(*_3);
+        StorageDead(_4);
+        StorageDead(_3);
+        return;
+    }
+
+    bb2 (cleanup): {
+        resume;
+    }
+}
diff --git a/tests/mir-opt/building/index_array_and_slice.index_slice.built.after.mir b/tests/mir-opt/building/index_array_and_slice.index_slice.built.after.mir
new file mode 100644
index 00000000000..0911df59049
--- /dev/null
+++ b/tests/mir-opt/building/index_array_and_slice.index_slice.built.after.mir
@@ -0,0 +1,32 @@
+// MIR for `index_slice` after built
+
+fn index_slice(_1: &[i32], _2: usize) -> &i32 {
+    debug slice => _1;
+    debug index => _2;
+    let mut _0: &i32;
+    let _3: &i32;
+    let _4: usize;
+    let mut _5: usize;
+    let mut _6: bool;
+
+    bb0: {
+        StorageLive(_3);
+        StorageLive(_4);
+        _4 = copy _2;
+        _5 = PtrMetadata(copy _1);
+        _6 = Lt(copy _4, copy _5);
+        assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind: bb2];
+    }
+
+    bb1: {
+        _3 = &(*_1)[_4];
+        _0 = &(*_3);
+        StorageDead(_4);
+        StorageDead(_3);
+        return;
+    }
+
+    bb2 (cleanup): {
+        resume;
+    }
+}
diff --git a/tests/mir-opt/building/index_array_and_slice.rs b/tests/mir-opt/building/index_array_and_slice.rs
new file mode 100644
index 00000000000..16d0b983132
--- /dev/null
+++ b/tests/mir-opt/building/index_array_and_slice.rs
@@ -0,0 +1,71 @@
+//@ compile-flags: -C opt-level=0
+
+// EMIT_MIR index_array_and_slice.index_array.built.after.mir
+fn index_array(array: &[i32; 7], index: usize) -> &i32 {
+    // CHECK: bb0:
+    // CHECK: [[LT:_.+]] = Lt(copy _2, const 7_usize);
+    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const 7_usize, copy _2) -> [success: bb1, unwind
+
+    // CHECK: bb1:
+    // CHECK: _0 = &(*_1)[_2];
+    &array[index]
+}
+
+// EMIT_MIR index_array_and_slice.index_const_generic_array.built.after.mir
+fn index_const_generic_array<const N: usize>(array: &[i32; N], index: usize) -> &i32 {
+    // CHECK: bb0:
+    // CHECK: [[LT:_.+]] = Lt(copy _2, const N);
+    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const N, copy _2) -> [success: bb1, unwind
+
+    // CHECK: bb1:
+    // CHECK: _0 = &(*_1)[_2];
+    &array[index]
+}
+
+// EMIT_MIR index_array_and_slice.index_slice.built.after.mir
+fn index_slice(slice: &[i32], index: usize) -> &i32 {
+    // CHECK: bb0:
+    // CHECK: [[LEN:_.+]] = PtrMetadata(copy _1);
+    // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]);
+    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1,
+
+    // CHECK: bb1:
+    // CHECK: _0 = &(*_1)[_2];
+    &slice[index]
+}
+
+// EMIT_MIR index_array_and_slice.index_mut_slice.built.after.mir
+fn index_mut_slice(slice: &mut [i32], index: usize) -> &i32 {
+    // While the filecheck here is identical to the above test, the emitted MIR is different.
+    // This cannot `copy _1` in the *built* MIR, only in the *runtime* MIR.
+
+    // CHECK: bb0:
+    // CHECK: [[LEN:_.+]] = PtrMetadata(copy _1);
+    // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]);
+    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1,
+
+    // CHECK: bb1:
+    // CHECK: _0 = &(*_1)[_2];
+    &slice[index]
+}
+
+struct WithSliceTail(f64, [i32]);
+
+// EMIT_MIR index_array_and_slice.index_custom.built.after.mir
+fn index_custom(custom: &WithSliceTail, index: usize) -> &i32 {
+    // CHECK: bb0:
+    // CHECK: [[PTR:_.+]] = &raw const ((*_1).1: [i32]);
+    // CHECK: [[LEN:_.+]] = PtrMetadata(move [[PTR]]);
+    // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]);
+    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1,
+
+    // CHECK: bb1:
+    // CHECK: _0 = &((*_1).1: [i32])[_2];
+    &custom.1[index]
+}
+
+fn main() {
+    index_array(&[1, 2, 3, 4, 5, 6, 7], 3);
+    index_slice(&[1, 2, 3, 4, 5, 6, 7][..], 3);
+    _ = index_custom;
+}
diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff
index e754af95ce3..3a5a8d00991 100644
--- a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-abort.diff
@@ -6,8 +6,7 @@
       let _1: u32;
       let mut _2: [u32; 4];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable];
-+         _4 = const 4_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 4_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind unreachable];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff
index e15a35c7fe9..62d6e6007e5 100644
--- a/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/array_index.main.GVN.32bit.panic-unwind.diff
@@ -6,8 +6,7 @@
       let _1: u32;
       let mut _2: [u32; 4];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue];
-+         _4 = const 4_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 4_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind continue];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff
index e754af95ce3..3a5a8d00991 100644
--- a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-abort.diff
@@ -6,8 +6,7 @@
       let _1: u32;
       let mut _2: [u32; 4];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable];
-+         _4 = const 4_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 4_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind unreachable];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff
index e15a35c7fe9..62d6e6007e5 100644
--- a/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/array_index.main.GVN.64bit.panic-unwind.diff
@@ -6,8 +6,7 @@
       let _1: u32;
       let mut _2: [u32; 4];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue];
-+         _4 = const 4_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 4_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind continue];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff
index 15d30140367..be42c4d60c8 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff
@@ -30,19 +30,22 @@
           StorageDead(_2);
           StorageDead(_3);
           StorageLive(_5);
-          StorageLive(_6);
+-         StorageLive(_6);
++         nop;
           _6 = const 3_usize;
-          _7 = Len((*_1));
+-         _7 = PtrMetadata(copy _1);
 -         _8 = Lt(copy _6, copy _7);
 -         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable];
-+         _8 = Lt(const 3_usize, copy _7);
-+         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> [success: bb1, unwind unreachable];
++         _7 = const 3_usize;
++         _8 = const false;
++         assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> [success: bb1, unwind unreachable];
       }
   
       bb1: {
 -         _5 = copy (*_1)[_6];
+-         StorageDead(_6);
 +         _5 = copy (*_1)[3 of 4];
-          StorageDead(_6);
++         nop;
           _0 = const ();
           StorageDead(_5);
           StorageDead(_1);
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff
index dd411d84f9f..b51d0c0845f 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff
@@ -30,19 +30,22 @@
           StorageDead(_2);
           StorageDead(_3);
           StorageLive(_5);
-          StorageLive(_6);
+-         StorageLive(_6);
++         nop;
           _6 = const 3_usize;
-          _7 = Len((*_1));
+-         _7 = PtrMetadata(copy _1);
 -         _8 = Lt(copy _6, copy _7);
 -         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue];
-+         _8 = Lt(const 3_usize, copy _7);
-+         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> [success: bb1, unwind continue];
++         _7 = const 3_usize;
++         _8 = const false;
++         assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> [success: bb1, unwind continue];
       }
   
       bb1: {
 -         _5 = copy (*_1)[_6];
+-         StorageDead(_6);
 +         _5 = copy (*_1)[3 of 4];
-          StorageDead(_6);
++         nop;
           _0 = const ();
           StorageDead(_5);
           StorageDead(_1);
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff
index 15d30140367..be42c4d60c8 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff
@@ -30,19 +30,22 @@
           StorageDead(_2);
           StorageDead(_3);
           StorageLive(_5);
-          StorageLive(_6);
+-         StorageLive(_6);
++         nop;
           _6 = const 3_usize;
-          _7 = Len((*_1));
+-         _7 = PtrMetadata(copy _1);
 -         _8 = Lt(copy _6, copy _7);
 -         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable];
-+         _8 = Lt(const 3_usize, copy _7);
-+         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> [success: bb1, unwind unreachable];
++         _7 = const 3_usize;
++         _8 = const false;
++         assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> [success: bb1, unwind unreachable];
       }
   
       bb1: {
 -         _5 = copy (*_1)[_6];
+-         StorageDead(_6);
 +         _5 = copy (*_1)[3 of 4];
-          StorageDead(_6);
++         nop;
           _0 = const ();
           StorageDead(_5);
           StorageDead(_1);
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff
index dd411d84f9f..b51d0c0845f 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff
@@ -30,19 +30,22 @@
           StorageDead(_2);
           StorageDead(_3);
           StorageLive(_5);
-          StorageLive(_6);
+-         StorageLive(_6);
++         nop;
           _6 = const 3_usize;
-          _7 = Len((*_1));
+-         _7 = PtrMetadata(copy _1);
 -         _8 = Lt(copy _6, copy _7);
 -         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue];
-+         _8 = Lt(const 3_usize, copy _7);
-+         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> [success: bb1, unwind continue];
++         _7 = const 3_usize;
++         _8 = const false;
++         assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> [success: bb1, unwind continue];
       }
   
       bb1: {
 -         _5 = copy (*_1)[_6];
+-         StorageDead(_6);
 +         _5 = copy (*_1)[3 of 4];
-          StorageDead(_6);
++         nop;
           _0 = const ();
           StorageDead(_5);
           StorageDead(_1);
diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff
index 49ea51deed6..3569998b13f 100644
--- a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-abort.diff
@@ -6,8 +6,7 @@
       let _1: u8;
       let mut _2: [u8; 5000];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u8; 5000];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable];
-+         _4 = const 5000_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 5000_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind unreachable];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff
index 103bfbcaf64..50b31c9ac13 100644
--- a/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.32bit.panic-unwind.diff
@@ -6,8 +6,7 @@
       let _1: u8;
       let mut _2: [u8; 5000];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u8; 5000];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue];
-+         _4 = const 5000_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 5000_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind continue];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff
index 49ea51deed6..3569998b13f 100644
--- a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-abort.diff
@@ -6,8 +6,7 @@
       let _1: u8;
       let mut _2: [u8; 5000];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u8; 5000];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable];
-+         _4 = const 5000_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 5000_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind unreachable];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff
index 103bfbcaf64..50b31c9ac13 100644
--- a/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/large_array_index.main.GVN.64bit.panic-unwind.diff
@@ -6,8 +6,7 @@
       let _1: u8;
       let mut _2: [u8; 5000];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u8; 5000];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue];
-+         _4 = const 5000_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 5000_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind continue];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff
index f7c1c2da01f..a41668b6fa3 100644
--- a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-abort.diff
@@ -7,8 +7,7 @@
       let mut _2: u32;
       let mut _3: [u32; 8];
       let _4: usize;
-      let mut _5: usize;
-      let mut _6: bool;
+      let mut _5: bool;
       scope 1 {
           debug x => _1;
       }
@@ -20,11 +19,9 @@
           _3 = [const 42_u32; 8];
           StorageLive(_4);
           _4 = const 2_usize;
--         _5 = Len(_3);
--         _6 = Lt(copy _4, copy _5);
--         assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind unreachable];
-+         _5 = const 8_usize;
-+         _6 = const true;
+-         _5 = Lt(copy _4, const 8_usize);
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind unreachable];
++         _5 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff
index 436773c8556..2313084b49e 100644
--- a/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/repeat.main.GVN.32bit.panic-unwind.diff
@@ -7,8 +7,7 @@
       let mut _2: u32;
       let mut _3: [u32; 8];
       let _4: usize;
-      let mut _5: usize;
-      let mut _6: bool;
+      let mut _5: bool;
       scope 1 {
           debug x => _1;
       }
@@ -20,11 +19,9 @@
           _3 = [const 42_u32; 8];
           StorageLive(_4);
           _4 = const 2_usize;
--         _5 = Len(_3);
--         _6 = Lt(copy _4, copy _5);
--         assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue];
-+         _5 = const 8_usize;
-+         _6 = const true;
+-         _5 = Lt(copy _4, const 8_usize);
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind continue];
++         _5 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff
index f7c1c2da01f..a41668b6fa3 100644
--- a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-abort.diff
@@ -7,8 +7,7 @@
       let mut _2: u32;
       let mut _3: [u32; 8];
       let _4: usize;
-      let mut _5: usize;
-      let mut _6: bool;
+      let mut _5: bool;
       scope 1 {
           debug x => _1;
       }
@@ -20,11 +19,9 @@
           _3 = [const 42_u32; 8];
           StorageLive(_4);
           _4 = const 2_usize;
--         _5 = Len(_3);
--         _6 = Lt(copy _4, copy _5);
--         assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind unreachable];
-+         _5 = const 8_usize;
-+         _6 = const true;
+-         _5 = Lt(copy _4, const 8_usize);
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind unreachable];
++         _5 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff
index 436773c8556..2313084b49e 100644
--- a/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/repeat.main.GVN.64bit.panic-unwind.diff
@@ -7,8 +7,7 @@
       let mut _2: u32;
       let mut _3: [u32; 8];
       let _4: usize;
-      let mut _5: usize;
-      let mut _6: bool;
+      let mut _5: bool;
       scope 1 {
           debug x => _1;
       }
@@ -20,11 +19,9 @@
           _3 = [const 42_u32; 8];
           StorageLive(_4);
           _4 = const 2_usize;
--         _5 = Len(_3);
--         _6 = Lt(copy _4, copy _5);
--         assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue];
-+         _5 = const 8_usize;
-+         _6 = const true;
+-         _5 = Lt(copy _4, const 8_usize);
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind continue];
++         _5 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff
index 8a8ea5b7e20..0798b303929 100644
--- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff
@@ -30,11 +30,12 @@
           StorageDead(_3);
           StorageLive(_6);
           _6 = const 1_usize;
-          _7 = Len((*_2));
+-         _7 = PtrMetadata(copy _2);
 -         _8 = Lt(copy _6, copy _7);
 -         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable];
-+         _8 = Lt(const 1_usize, copy _7);
-+         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind unreachable];
++         _7 = const 3_usize;
++         _8 = const true;
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable];
       }
   
       bb1: {
diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff
index f0c844884f6..c0b3d4d3219 100644
--- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff
@@ -30,11 +30,12 @@
           StorageDead(_3);
           StorageLive(_6);
           _6 = const 1_usize;
-          _7 = Len((*_2));
+-         _7 = PtrMetadata(copy _2);
 -         _8 = Lt(copy _6, copy _7);
 -         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue];
-+         _8 = Lt(const 1_usize, copy _7);
-+         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind continue];
++         _7 = const 3_usize;
++         _8 = const true;
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue];
       }
   
       bb1: {
diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff
index 8a8ea5b7e20..0798b303929 100644
--- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff
@@ -30,11 +30,12 @@
           StorageDead(_3);
           StorageLive(_6);
           _6 = const 1_usize;
-          _7 = Len((*_2));
+-         _7 = PtrMetadata(copy _2);
 -         _8 = Lt(copy _6, copy _7);
 -         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable];
-+         _8 = Lt(const 1_usize, copy _7);
-+         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind unreachable];
++         _7 = const 3_usize;
++         _8 = const true;
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable];
       }
   
       bb1: {
diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff
index f0c844884f6..c0b3d4d3219 100644
--- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff
@@ -30,11 +30,12 @@
           StorageDead(_3);
           StorageLive(_6);
           _6 = const 1_usize;
-          _7 = Len((*_2));
+-         _7 = PtrMetadata(copy _2);
 -         _8 = Lt(copy _6, copy _7);
 -         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue];
-+         _8 = Lt(const 1_usize, copy _7);
-+         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 1_usize) -> [success: bb1, unwind continue];
++         _7 = const 3_usize;
++         _8 = const true;
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue];
       }
   
       bb1: {
diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff
index 6d967257df1..689083dfc1d 100644
--- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff
+++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-abort.diff
@@ -18,8 +18,7 @@
       let mut _15: !;
       let mut _17: i32;
       let _18: usize;
-      let mut _19: usize;
-      let mut _20: bool;
+      let mut _19: bool;
       scope 1 {
           debug sum => _1;
           let _2: [i32; 4];
@@ -92,11 +91,10 @@
           StorageLive(_17);
 -         StorageLive(_18);
 -         _18 = copy _16;
-          _19 = Len(_2);
--         _20 = Lt(copy _18, copy _19);
--         assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, copy _18) -> [success: bb8, unwind unreachable];
-+         _20 = Lt(copy _16, copy _19);
-+         assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, copy _16) -> [success: bb8, unwind unreachable];
+-         _19 = Lt(copy _18, const 4_usize);
+-         assert(move _19, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _18) -> [success: bb8, unwind unreachable];
++         _19 = Lt(copy _16, const 4_usize);
++         assert(move _19, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _16) -> [success: bb8, unwind unreachable];
       }
   
       bb7: {
diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff
index 3580c87c469..7f768a9f834 100644
--- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff
+++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.panic-unwind.diff
@@ -18,8 +18,7 @@
       let mut _15: !;
       let mut _17: i32;
       let _18: usize;
-      let mut _19: usize;
-      let mut _20: bool;
+      let mut _19: bool;
       scope 1 {
           debug sum => _1;
           let _2: [i32; 4];
@@ -92,11 +91,10 @@
           StorageLive(_17);
 -         StorageLive(_18);
 -         _18 = copy _16;
-          _19 = Len(_2);
--         _20 = Lt(copy _18, copy _19);
--         assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, copy _18) -> [success: bb8, unwind continue];
-+         _20 = Lt(copy _16, copy _19);
-+         assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, copy _16) -> [success: bb8, unwind continue];
+-         _19 = Lt(copy _18, const 4_usize);
+-         assert(move _19, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _18) -> [success: bb8, unwind continue];
++         _19 = Lt(copy _16, const 4_usize);
++         assert(move _19, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _16) -> [success: bb8, unwind continue];
       }
   
       bb7: {
diff --git a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-abort.diff
index a46daef435f..0275d7e8a0d 100644
--- a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-abort.diff
@@ -6,8 +6,7 @@
       let _1: u32;
       let mut _2: [u32; 4];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable];
-+         _4 = const 4_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 4_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind unreachable];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-unwind.diff
index 1a4e15b45fa..490ed4b55a1 100644
--- a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.32bit.panic-unwind.diff
@@ -6,8 +6,7 @@
       let _1: u32;
       let mut _2: [u32; 4];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue];
-+         _4 = const 4_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 4_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind continue];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-abort.diff
index a46daef435f..0275d7e8a0d 100644
--- a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-abort.diff
@@ -6,8 +6,7 @@
       let _1: u32;
       let mut _2: [u32; 4];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable];
-+         _4 = const 4_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 4_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind unreachable];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff
index 1a4e15b45fa..490ed4b55a1 100644
--- a/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/array_index.main.DataflowConstProp.64bit.panic-unwind.diff
@@ -6,8 +6,7 @@
       let _1: u32;
       let mut _2: [u32; 4];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue];
-+         _4 = const 4_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 4_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 4_usize, copy _3) -> [success: bb1, unwind continue];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> [success: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/array_index.rs b/tests/mir-opt/dataflow-const-prop/array_index.rs
index e442ef99f79..1aa8dcd28f4 100644
--- a/tests/mir-opt/dataflow-const-prop/array_index.rs
+++ b/tests/mir-opt/dataflow-const-prop/array_index.rs
@@ -11,9 +11,10 @@ fn main() {
 
     // CHECK:       [[array_lit]] = [const 0_u32, const 1_u32, const 2_u32, const 3_u32];
     // CHECK-NOT:   {{_.*}} = Len(
+    // CHECK-NOT:   {{_.*}} = PtrMetadata(
     // CHECK-NOT:   {{_.*}} = Lt(
     // CHECK-NOT:   assert(move _
-    // CHECK:       {{_.*}} = const 4_usize;
+    // CHECK:       {{_.*}} = const 2_usize;
     // CHECK:       {{_.*}} = const true;
     // CHECK:       assert(const true
     // CHECK:       [[x]] = copy [[array_lit]][2 of 3];
diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-abort.diff
index b7ff0b671f7..f0d59ef5923 100644
--- a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-abort.diff
@@ -6,8 +6,7 @@
       let _1: u8;
       let mut _2: [u8; 5000];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u8; 5000];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable];
-+         _4 = const 5000_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 5000_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind unreachable];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-unwind.diff
index af6e3626142..959c3e75214 100644
--- a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.32bit.panic-unwind.diff
@@ -6,8 +6,7 @@
       let _1: u8;
       let mut _2: [u8; 5000];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u8; 5000];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue];
-+         _4 = const 5000_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 5000_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind continue];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-abort.diff
index b7ff0b671f7..f0d59ef5923 100644
--- a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-abort.diff
@@ -6,8 +6,7 @@
       let _1: u8;
       let mut _2: [u8; 5000];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u8; 5000];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable];
-+         _4 = const 5000_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 5000_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind unreachable];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff
index af6e3626142..959c3e75214 100644
--- a/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/large_array_index.main.DataflowConstProp.64bit.panic-unwind.diff
@@ -6,8 +6,7 @@
       let _1: u8;
       let mut _2: [u8; 5000];
       let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
+      let mut _4: bool;
       scope 1 {
           debug x => _1;
       }
@@ -18,11 +17,9 @@
           _2 = [const 0_u8; 5000];
           StorageLive(_3);
           _3 = const 2_usize;
--         _4 = Len(_2);
--         _5 = Lt(copy _3, copy _4);
--         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue];
-+         _4 = const 5000_usize;
-+         _5 = const true;
+-         _4 = Lt(copy _3, const 5000_usize);
+-         assert(move _4, "index out of bounds: the length is {} but the index is {}", const 5000_usize, copy _3) -> [success: bb1, unwind continue];
++         _4 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> [success: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.rs b/tests/mir-opt/dataflow-const-prop/large_array_index.rs
index e9f2fa2badf..e490cfde247 100644
--- a/tests/mir-opt/dataflow-const-prop/large_array_index.rs
+++ b/tests/mir-opt/dataflow-const-prop/large_array_index.rs
@@ -10,7 +10,7 @@ fn main() {
 
     // CHECK: debug x => [[x:_.*]];
     // CHECK: [[array_lit:_.*]] = [const 0_u8; 5000];
-    // CHECK: {{_.*}} = const 5000_usize;
+    // CHECK: {{_.*}} = const 2_usize;
     // CHECK: {{_.*}} = const true;
     // CHECK: assert(const true
     // CHECK: [[x]] = copy [[array_lit]][2 of 3];
diff --git a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-abort.diff
index dfa541b1200..618121ea632 100644
--- a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-abort.diff
@@ -7,8 +7,7 @@
       let mut _2: u32;
       let mut _3: [u32; 8];
       let _4: usize;
-      let mut _5: usize;
-      let mut _6: bool;
+      let mut _5: bool;
       scope 1 {
           debug x => _1;
       }
@@ -20,11 +19,9 @@
           _3 = [const 42_u32; 8];
           StorageLive(_4);
           _4 = const 2_usize;
--         _5 = Len(_3);
--         _6 = Lt(copy _4, copy _5);
--         assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind unreachable];
-+         _5 = const 8_usize;
-+         _6 = const true;
+-         _5 = Lt(copy _4, const 8_usize);
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind unreachable];
++         _5 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-unwind.diff
index 9ede3c5f7ac..1788f58432b 100644
--- a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.32bit.panic-unwind.diff
@@ -7,8 +7,7 @@
       let mut _2: u32;
       let mut _3: [u32; 8];
       let _4: usize;
-      let mut _5: usize;
-      let mut _6: bool;
+      let mut _5: bool;
       scope 1 {
           debug x => _1;
       }
@@ -20,11 +19,9 @@
           _3 = [const 42_u32; 8];
           StorageLive(_4);
           _4 = const 2_usize;
--         _5 = Len(_3);
--         _6 = Lt(copy _4, copy _5);
--         assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue];
-+         _5 = const 8_usize;
-+         _6 = const true;
+-         _5 = Lt(copy _4, const 8_usize);
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind continue];
++         _5 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-abort.diff
index dfa541b1200..618121ea632 100644
--- a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-abort.diff
@@ -7,8 +7,7 @@
       let mut _2: u32;
       let mut _3: [u32; 8];
       let _4: usize;
-      let mut _5: usize;
-      let mut _6: bool;
+      let mut _5: bool;
       scope 1 {
           debug x => _1;
       }
@@ -20,11 +19,9 @@
           _3 = [const 42_u32; 8];
           StorageLive(_4);
           _4 = const 2_usize;
--         _5 = Len(_3);
--         _6 = Lt(copy _4, copy _5);
--         assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind unreachable];
-+         _5 = const 8_usize;
-+         _6 = const true;
+-         _5 = Lt(copy _4, const 8_usize);
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind unreachable];
++         _5 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff
index 9ede3c5f7ac..1788f58432b 100644
--- a/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/repeat.main.DataflowConstProp.64bit.panic-unwind.diff
@@ -7,8 +7,7 @@
       let mut _2: u32;
       let mut _3: [u32; 8];
       let _4: usize;
-      let mut _5: usize;
-      let mut _6: bool;
+      let mut _5: bool;
       scope 1 {
           debug x => _1;
       }
@@ -20,11 +19,9 @@
           _3 = [const 42_u32; 8];
           StorageLive(_4);
           _4 = const 2_usize;
--         _5 = Len(_3);
--         _6 = Lt(copy _4, copy _5);
--         assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind continue];
-+         _5 = const 8_usize;
-+         _6 = const true;
+-         _5 = Lt(copy _4, const 8_usize);
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", const 8_usize, copy _4) -> [success: bb1, unwind continue];
++         _5 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> [success: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/repeat.rs b/tests/mir-opt/dataflow-const-prop/repeat.rs
index 2067aa3d709..1bc2cb82a60 100644
--- a/tests/mir-opt/dataflow-const-prop/repeat.rs
+++ b/tests/mir-opt/dataflow-const-prop/repeat.rs
@@ -9,8 +9,9 @@ fn main() {
 
     // CHECK: [[array_lit:_.*]] = [const 42_u32; 8];
     // CHECK-NOT: {{_.*}} = Len(
+    // CHECK-NOT: {{_.*}} = PtrMetadata(
     // CHECK-NOT: {{_.*}} = Lt(
-    // CHECK: {{_.*}} = const 8_usize;
+    // CHECK: {{_.*}} = const 2_usize;
     // CHECK: {{_.*}} = const true;
     // CHECK: assert(const true
 
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff
deleted file mode 100644
index e71992316dc..00000000000
--- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff
+++ /dev/null
@@ -1,77 +0,0 @@
-- // MIR for `main` before DataflowConstProp
-+ // MIR for `main` after DataflowConstProp
-  
-  fn main() -> () {
-      let mut _0: ();
-      let _1: u32;
-      let mut _2: &[u32];
-      let mut _3: &[u32; 3];
-      let _4: &[u32; 3];
-      let _5: [u32; 3];
-      let _6: usize;
-      let mut _7: usize;
-      let mut _8: bool;
-      let mut _10: &[u32];
-      let _11: usize;
-      let mut _12: usize;
-      let mut _13: bool;
-      let mut _14: &[u32; 3];
-      scope 1 {
-          debug local => _1;
-          let _9: u32;
-          scope 2 {
-              debug constant => _9;
-          }
-      }
-  
-      bb0: {
-          StorageLive(_1);
-          StorageLive(_2);
-          StorageLive(_3);
-          StorageLive(_4);
-          _14 = const main::promoted[0];
-          _4 = copy _14;
-          _3 = copy _4;
-          _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
-          StorageDead(_3);
-          StorageLive(_6);
-          _6 = const 1_usize;
--         _7 = Len((*_2));
--         _8 = Lt(copy _6, copy _7);
--         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable];
-+         _7 = const 3_usize;
-+         _8 = const true;
-+         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable];
-      }
-  
-      bb1: {
--         _1 = copy (*_2)[_6];
-+         _1 = copy (*_2)[1 of 2];
-          StorageDead(_6);
-          StorageDead(_4);
-          StorageDead(_2);
-          StorageLive(_9);
-          StorageLive(_10);
-          _10 = const main::SLICE;
-          StorageLive(_11);
-          _11 = const 1_usize;
--         _12 = Len((*_10));
--         _13 = Lt(copy _11, copy _12);
--         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind unreachable];
-+         _12 = const 3_usize;
-+         _13 = const true;
-+         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind unreachable];
-      }
-  
-      bb2: {
--         _9 = copy (*_10)[_11];
-+         _9 = copy (*_10)[1 of 2];
-          StorageDead(_11);
-          StorageDead(_10);
-          _0 = const ();
-          StorageDead(_9);
-          StorageDead(_1);
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff
deleted file mode 100644
index 26de8595768..00000000000
--- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff
+++ /dev/null
@@ -1,77 +0,0 @@
-- // MIR for `main` before DataflowConstProp
-+ // MIR for `main` after DataflowConstProp
-  
-  fn main() -> () {
-      let mut _0: ();
-      let _1: u32;
-      let mut _2: &[u32];
-      let mut _3: &[u32; 3];
-      let _4: &[u32; 3];
-      let _5: [u32; 3];
-      let _6: usize;
-      let mut _7: usize;
-      let mut _8: bool;
-      let mut _10: &[u32];
-      let _11: usize;
-      let mut _12: usize;
-      let mut _13: bool;
-      let mut _14: &[u32; 3];
-      scope 1 {
-          debug local => _1;
-          let _9: u32;
-          scope 2 {
-              debug constant => _9;
-          }
-      }
-  
-      bb0: {
-          StorageLive(_1);
-          StorageLive(_2);
-          StorageLive(_3);
-          StorageLive(_4);
-          _14 = const main::promoted[0];
-          _4 = copy _14;
-          _3 = copy _4;
-          _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
-          StorageDead(_3);
-          StorageLive(_6);
-          _6 = const 1_usize;
--         _7 = Len((*_2));
--         _8 = Lt(copy _6, copy _7);
--         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue];
-+         _7 = const 3_usize;
-+         _8 = const true;
-+         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue];
-      }
-  
-      bb1: {
--         _1 = copy (*_2)[_6];
-+         _1 = copy (*_2)[1 of 2];
-          StorageDead(_6);
-          StorageDead(_4);
-          StorageDead(_2);
-          StorageLive(_9);
-          StorageLive(_10);
-          _10 = const main::SLICE;
-          StorageLive(_11);
-          _11 = const 1_usize;
--         _12 = Len((*_10));
--         _13 = Lt(copy _11, copy _12);
--         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind continue];
-+         _12 = const 3_usize;
-+         _13 = const true;
-+         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind continue];
-      }
-  
-      bb2: {
--         _9 = copy (*_10)[_11];
-+         _9 = copy (*_10)[1 of 2];
-          StorageDead(_11);
-          StorageDead(_10);
-          _0 = const ();
-          StorageDead(_9);
-          StorageDead(_1);
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff
deleted file mode 100644
index e71992316dc..00000000000
--- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff
+++ /dev/null
@@ -1,77 +0,0 @@
-- // MIR for `main` before DataflowConstProp
-+ // MIR for `main` after DataflowConstProp
-  
-  fn main() -> () {
-      let mut _0: ();
-      let _1: u32;
-      let mut _2: &[u32];
-      let mut _3: &[u32; 3];
-      let _4: &[u32; 3];
-      let _5: [u32; 3];
-      let _6: usize;
-      let mut _7: usize;
-      let mut _8: bool;
-      let mut _10: &[u32];
-      let _11: usize;
-      let mut _12: usize;
-      let mut _13: bool;
-      let mut _14: &[u32; 3];
-      scope 1 {
-          debug local => _1;
-          let _9: u32;
-          scope 2 {
-              debug constant => _9;
-          }
-      }
-  
-      bb0: {
-          StorageLive(_1);
-          StorageLive(_2);
-          StorageLive(_3);
-          StorageLive(_4);
-          _14 = const main::promoted[0];
-          _4 = copy _14;
-          _3 = copy _4;
-          _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
-          StorageDead(_3);
-          StorageLive(_6);
-          _6 = const 1_usize;
--         _7 = Len((*_2));
--         _8 = Lt(copy _6, copy _7);
--         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable];
-+         _7 = const 3_usize;
-+         _8 = const true;
-+         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable];
-      }
-  
-      bb1: {
--         _1 = copy (*_2)[_6];
-+         _1 = copy (*_2)[1 of 2];
-          StorageDead(_6);
-          StorageDead(_4);
-          StorageDead(_2);
-          StorageLive(_9);
-          StorageLive(_10);
-          _10 = const main::SLICE;
-          StorageLive(_11);
-          _11 = const 1_usize;
--         _12 = Len((*_10));
--         _13 = Lt(copy _11, copy _12);
--         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind unreachable];
-+         _12 = const 3_usize;
-+         _13 = const true;
-+         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind unreachable];
-      }
-  
-      bb2: {
--         _9 = copy (*_10)[_11];
-+         _9 = copy (*_10)[1 of 2];
-          StorageDead(_11);
-          StorageDead(_10);
-          _0 = const ();
-          StorageDead(_9);
-          StorageDead(_1);
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff
deleted file mode 100644
index 26de8595768..00000000000
--- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff
+++ /dev/null
@@ -1,77 +0,0 @@
-- // MIR for `main` before DataflowConstProp
-+ // MIR for `main` after DataflowConstProp
-  
-  fn main() -> () {
-      let mut _0: ();
-      let _1: u32;
-      let mut _2: &[u32];
-      let mut _3: &[u32; 3];
-      let _4: &[u32; 3];
-      let _5: [u32; 3];
-      let _6: usize;
-      let mut _7: usize;
-      let mut _8: bool;
-      let mut _10: &[u32];
-      let _11: usize;
-      let mut _12: usize;
-      let mut _13: bool;
-      let mut _14: &[u32; 3];
-      scope 1 {
-          debug local => _1;
-          let _9: u32;
-          scope 2 {
-              debug constant => _9;
-          }
-      }
-  
-      bb0: {
-          StorageLive(_1);
-          StorageLive(_2);
-          StorageLive(_3);
-          StorageLive(_4);
-          _14 = const main::promoted[0];
-          _4 = copy _14;
-          _3 = copy _4;
-          _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast));
-          StorageDead(_3);
-          StorageLive(_6);
-          _6 = const 1_usize;
--         _7 = Len((*_2));
--         _8 = Lt(copy _6, copy _7);
--         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue];
-+         _7 = const 3_usize;
-+         _8 = const true;
-+         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue];
-      }
-  
-      bb1: {
--         _1 = copy (*_2)[_6];
-+         _1 = copy (*_2)[1 of 2];
-          StorageDead(_6);
-          StorageDead(_4);
-          StorageDead(_2);
-          StorageLive(_9);
-          StorageLive(_10);
-          _10 = const main::SLICE;
-          StorageLive(_11);
-          _11 = const 1_usize;
--         _12 = Len((*_10));
--         _13 = Lt(copy _11, copy _12);
--         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind continue];
-+         _12 = const 3_usize;
-+         _13 = const true;
-+         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind continue];
-      }
-  
-      bb2: {
--         _9 = copy (*_10)[_11];
-+         _9 = copy (*_10)[1 of 2];
-          StorageDead(_11);
-          StorageDead(_10);
-          _0 = const ();
-          StorageDead(_9);
-          StorageDead(_1);
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.rs b/tests/mir-opt/dataflow-const-prop/slice_len.rs
deleted file mode 100644
index e0e68f9fde5..00000000000
--- a/tests/mir-opt/dataflow-const-prop/slice_len.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
-//@ test-mir-pass: DataflowConstProp
-//@ compile-flags: -Zmir-enable-passes=+InstSimplify-after-simplifycfg
-// EMIT_MIR_FOR_EACH_BIT_WIDTH
-
-// EMIT_MIR slice_len.main.DataflowConstProp.diff
-
-// CHECK-LABEL: fn main(
-fn main() {
-    // CHECK: debug local => [[local:_.*]];
-    // CHECK: debug constant => [[constant:_.*]];
-
-    // CHECK-NOT: {{_.*}} = Len(
-    // CHECK-NOT: {{_.*}} = Lt(
-    // CHECK-NOT: assert(move _
-    // CHECK: {{_.*}} = const 3_usize;
-    // CHECK: {{_.*}} = const true;
-    // CHECK: assert(const true,
-
-    // CHECK: [[local]] = copy (*{{_.*}})[1 of 2];
-    let local = (&[1u32, 2, 3] as &[u32])[1];
-
-    // CHECK-NOT: {{_.*}} = Len(
-    // CHECK-NOT: {{_.*}} = Lt(
-    // CHECK-NOT: assert(move _
-    const SLICE: &[u32] = &[1, 2, 3];
-    // CHECK: {{_.*}} = const 3_usize;
-    // CHECK: {{_.*}} = const true;
-    // CHECK: assert(const true,
-
-    // CHECK-NOT: [[constant]] = {{copy|move}} (*{{_.*}})[_
-    // CHECK: [[constant]] = copy (*{{_.*}})[1 of 2];
-    let constant = SLICE[1];
-}
diff --git a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff
index 3f052ee19fd..183b4d2599f 100644
--- a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff
+++ b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff
@@ -53,7 +53,7 @@
           StorageLive(_8);
 -         _8 = copy _2;
 +         _8 = const usize::MAX;
-          _9 = Len((*_1));
+          _9 = PtrMetadata(copy _1);
 -         _10 = Lt(copy _8, copy _9);
 -         assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind unreachable];
 +         _10 = Lt(const usize::MAX, copy _9);
@@ -72,7 +72,7 @@
           StorageDead(_5);
           StorageLive(_11);
           _11 = const 0_usize;
-          _12 = Len((*_1));
+          _12 = PtrMetadata(copy _1);
 -         _13 = Lt(copy _11, copy _12);
 -         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb5, unwind unreachable];
 +         _13 = Lt(const 0_usize, copy _12);
diff --git a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff
index 84b738c7804..03e8aa3bd9b 100644
--- a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff
+++ b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff
@@ -53,7 +53,7 @@
           StorageLive(_8);
 -         _8 = copy _2;
 +         _8 = const usize::MAX;
-          _9 = Len((*_1));
+          _9 = PtrMetadata(copy _1);
 -         _10 = Lt(copy _8, copy _9);
 -         assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind continue];
 +         _10 = Lt(const usize::MAX, copy _9);
@@ -72,7 +72,7 @@
           StorageDead(_5);
           StorageLive(_11);
           _11 = const 0_usize;
-          _12 = Len((*_1));
+          _12 = PtrMetadata(copy _1);
 -         _13 = Lt(copy _11, copy _12);
 -         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb5, unwind continue];
 +         _13 = Lt(const 0_usize, copy _12);
diff --git a/tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-abort.diff b/tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-abort.diff
new file mode 100644
index 00000000000..4b077f580f1
--- /dev/null
+++ b/tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-abort.diff
@@ -0,0 +1,72 @@
+- // MIR for `dedup_multiple_bounds_checks_lengths` before GVN
++ // MIR for `dedup_multiple_bounds_checks_lengths` after GVN
+  
+  fn dedup_multiple_bounds_checks_lengths(_1: &[i32]) -> [i32; 3] {
+      debug x => _1;
+      let mut _0: [i32; 3];
+      let mut _2: i32;
+      let _3: usize;
+      let mut _4: usize;
+      let mut _5: bool;
+      let mut _6: i32;
+      let _7: usize;
+      let mut _8: usize;
+      let mut _9: bool;
+      let mut _10: i32;
+      let _11: usize;
+      let mut _12: usize;
+      let mut _13: bool;
+  
+      bb0: {
+          StorageLive(_2);
+          StorageLive(_3);
+          _3 = const 42_usize;
+          _4 = PtrMetadata(copy _1);
+-         _5 = Lt(copy _3, copy _4);
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable];
++         _5 = Lt(const 42_usize, copy _4);
++         assert(move _5, "index out of bounds: the length is {} but the index is {}", copy _4, const 42_usize) -> [success: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+-         _2 = copy (*_1)[_3];
++         _2 = copy (*_1)[42 of 43];
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = const 13_usize;
+-         _8 = PtrMetadata(copy _1);
+-         _9 = Lt(copy _7, copy _8);
+-         assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind unreachable];
++         _8 = copy _4;
++         _9 = Lt(const 13_usize, copy _4);
++         assert(move _9, "index out of bounds: the length is {} but the index is {}", copy _4, const 13_usize) -> [success: bb2, unwind unreachable];
+      }
+  
+      bb2: {
+-         _6 = copy (*_1)[_7];
++         _6 = copy (*_1)[13 of 14];
+          StorageLive(_10);
+          StorageLive(_11);
+          _11 = const 7_usize;
+-         _12 = PtrMetadata(copy _1);
+-         _13 = Lt(copy _11, copy _12);
+-         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb3, unwind unreachable];
++         _12 = copy _4;
++         _13 = Lt(const 7_usize, copy _4);
++         assert(move _13, "index out of bounds: the length is {} but the index is {}", copy _4, const 7_usize) -> [success: bb3, unwind unreachable];
+      }
+  
+      bb3: {
+-         _10 = copy (*_1)[_11];
++         _10 = copy (*_1)[7 of 8];
+          _0 = [move _2, move _6, move _10];
+          StorageDead(_10);
+          StorageDead(_6);
+          StorageDead(_2);
+          StorageDead(_11);
+          StorageDead(_7);
+          StorageDead(_3);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..87e69d44006
--- /dev/null
+++ b/tests/mir-opt/gvn.dedup_multiple_bounds_checks_lengths.GVN.panic-unwind.diff
@@ -0,0 +1,72 @@
+- // MIR for `dedup_multiple_bounds_checks_lengths` before GVN
++ // MIR for `dedup_multiple_bounds_checks_lengths` after GVN
+  
+  fn dedup_multiple_bounds_checks_lengths(_1: &[i32]) -> [i32; 3] {
+      debug x => _1;
+      let mut _0: [i32; 3];
+      let mut _2: i32;
+      let _3: usize;
+      let mut _4: usize;
+      let mut _5: bool;
+      let mut _6: i32;
+      let _7: usize;
+      let mut _8: usize;
+      let mut _9: bool;
+      let mut _10: i32;
+      let _11: usize;
+      let mut _12: usize;
+      let mut _13: bool;
+  
+      bb0: {
+          StorageLive(_2);
+          StorageLive(_3);
+          _3 = const 42_usize;
+          _4 = PtrMetadata(copy _1);
+-         _5 = Lt(copy _3, copy _4);
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue];
++         _5 = Lt(const 42_usize, copy _4);
++         assert(move _5, "index out of bounds: the length is {} but the index is {}", copy _4, const 42_usize) -> [success: bb1, unwind continue];
+      }
+  
+      bb1: {
+-         _2 = copy (*_1)[_3];
++         _2 = copy (*_1)[42 of 43];
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = const 13_usize;
+-         _8 = PtrMetadata(copy _1);
+-         _9 = Lt(copy _7, copy _8);
+-         assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind continue];
++         _8 = copy _4;
++         _9 = Lt(const 13_usize, copy _4);
++         assert(move _9, "index out of bounds: the length is {} but the index is {}", copy _4, const 13_usize) -> [success: bb2, unwind continue];
+      }
+  
+      bb2: {
+-         _6 = copy (*_1)[_7];
++         _6 = copy (*_1)[13 of 14];
+          StorageLive(_10);
+          StorageLive(_11);
+          _11 = const 7_usize;
+-         _12 = PtrMetadata(copy _1);
+-         _13 = Lt(copy _11, copy _12);
+-         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb3, unwind continue];
++         _12 = copy _4;
++         _13 = Lt(const 7_usize, copy _4);
++         assert(move _13, "index out of bounds: the length is {} but the index is {}", copy _4, const 7_usize) -> [success: bb3, unwind continue];
+      }
+  
+      bb3: {
+-         _10 = copy (*_1)[_11];
++         _10 = copy (*_1)[7 of 8];
+          _0 = [move _2, move _6, move _10];
+          StorageDead(_10);
+          StorageDead(_6);
+          StorageDead(_2);
+          StorageDead(_11);
+          StorageDead(_7);
+          StorageDead(_3);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff
index d4b22d05f6c..7f44176b756 100644
--- a/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff
+++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff
@@ -10,13 +10,11 @@
       let _5: ();
       let mut _6: T;
       let _7: usize;
-      let mut _8: usize;
-      let mut _9: bool;
-      let _10: ();
-      let mut _11: T;
-      let _12: usize;
-      let mut _13: usize;
-      let mut _14: bool;
+      let mut _8: bool;
+      let _9: ();
+      let mut _10: T;
+      let _11: usize;
+      let mut _12: bool;
       scope 1 {
           debug a => _3;
       }
@@ -32,12 +30,10 @@
           StorageLive(_6);
           StorageLive(_7);
           _7 = const 0_usize;
--         _8 = Len(_3);
--         _9 = Lt(copy _7, copy _8);
--         assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb1, unwind unreachable];
-+         _8 = const N;
-+         _9 = Lt(const 0_usize, const N);
-+         assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind unreachable];
+-         _8 = Lt(copy _7, const N);
+-         assert(move _8, "index out of bounds: the length is {} but the index is {}", const N, copy _7) -> [success: bb1, unwind unreachable];
++         _8 = Lt(const 0_usize, const N);
++         assert(move _8, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind unreachable];
       }
   
       bb1: {
@@ -51,29 +47,27 @@
           StorageDead(_6);
           StorageDead(_7);
           StorageDead(_5);
+          StorageLive(_9);
           StorageLive(_10);
           StorageLive(_11);
-          StorageLive(_12);
-          _12 = copy _2;
--         _13 = Len(_3);
--         _14 = Lt(copy _12, copy _13);
--         assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, copy _12) -> [success: bb3, unwind unreachable];
-+         _13 = const N;
-+         _14 = Lt(copy _2, const N);
-+         assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, copy _2) -> [success: bb3, unwind unreachable];
+          _11 = copy _2;
+-         _12 = Lt(copy _11, const N);
+-         assert(move _12, "index out of bounds: the length is {} but the index is {}", const N, copy _11) -> [success: bb3, unwind unreachable];
++         _12 = Lt(copy _2, const N);
++         assert(move _12, "index out of bounds: the length is {} but the index is {}", const N, copy _2) -> [success: bb3, unwind unreachable];
       }
   
       bb3: {
--         _11 = copy _3[_12];
--         _10 = opaque::<T>(move _11) -> [return: bb4, unwind unreachable];
-+         _11 = copy _1;
-+         _10 = opaque::<T>(copy _1) -> [return: bb4, unwind unreachable];
+-         _10 = copy _3[_11];
+-         _9 = opaque::<T>(move _10) -> [return: bb4, unwind unreachable];
++         _10 = copy _1;
++         _9 = opaque::<T>(copy _1) -> [return: bb4, unwind unreachable];
       }
   
       bb4: {
-          StorageDead(_11);
-          StorageDead(_12);
           StorageDead(_10);
+          StorageDead(_11);
+          StorageDead(_9);
           _0 = const ();
           StorageDead(_3);
           return;
diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff
index 708c0f92e54..d34882d725f 100644
--- a/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff
+++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff
@@ -10,13 +10,11 @@
       let _5: ();
       let mut _6: T;
       let _7: usize;
-      let mut _8: usize;
-      let mut _9: bool;
-      let _10: ();
-      let mut _11: T;
-      let _12: usize;
-      let mut _13: usize;
-      let mut _14: bool;
+      let mut _8: bool;
+      let _9: ();
+      let mut _10: T;
+      let _11: usize;
+      let mut _12: bool;
       scope 1 {
           debug a => _3;
       }
@@ -32,12 +30,10 @@
           StorageLive(_6);
           StorageLive(_7);
           _7 = const 0_usize;
--         _8 = Len(_3);
--         _9 = Lt(copy _7, copy _8);
--         assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb1, unwind continue];
-+         _8 = const N;
-+         _9 = Lt(const 0_usize, const N);
-+         assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind continue];
+-         _8 = Lt(copy _7, const N);
+-         assert(move _8, "index out of bounds: the length is {} but the index is {}", const N, copy _7) -> [success: bb1, unwind continue];
++         _8 = Lt(const 0_usize, const N);
++         assert(move _8, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb1, unwind continue];
       }
   
       bb1: {
@@ -51,29 +47,27 @@
           StorageDead(_6);
           StorageDead(_7);
           StorageDead(_5);
+          StorageLive(_9);
           StorageLive(_10);
           StorageLive(_11);
-          StorageLive(_12);
-          _12 = copy _2;
--         _13 = Len(_3);
--         _14 = Lt(copy _12, copy _13);
--         assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, copy _12) -> [success: bb3, unwind continue];
-+         _13 = const N;
-+         _14 = Lt(copy _2, const N);
-+         assert(move _14, "index out of bounds: the length is {} but the index is {}", const N, copy _2) -> [success: bb3, unwind continue];
+          _11 = copy _2;
+-         _12 = Lt(copy _11, const N);
+-         assert(move _12, "index out of bounds: the length is {} but the index is {}", const N, copy _11) -> [success: bb3, unwind continue];
++         _12 = Lt(copy _2, const N);
++         assert(move _12, "index out of bounds: the length is {} but the index is {}", const N, copy _2) -> [success: bb3, unwind continue];
       }
   
       bb3: {
--         _11 = copy _3[_12];
--         _10 = opaque::<T>(move _11) -> [return: bb4, unwind continue];
-+         _11 = copy _1;
-+         _10 = opaque::<T>(copy _1) -> [return: bb4, unwind continue];
+-         _10 = copy _3[_11];
+-         _9 = opaque::<T>(move _10) -> [return: bb4, unwind continue];
++         _10 = copy _1;
++         _9 = opaque::<T>(copy _1) -> [return: bb4, unwind continue];
       }
   
       bb4: {
-          StorageDead(_11);
-          StorageDead(_12);
           StorageDead(_10);
+          StorageDead(_11);
+          StorageDead(_9);
           _0 = const ();
           StorageDead(_3);
           return;
diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs
index 97513248e23..19b58a917f8 100644
--- a/tests/mir-opt/gvn.rs
+++ b/tests/mir-opt/gvn.rs
@@ -835,6 +835,25 @@ fn array_len(x: &mut [i32; 42]) -> usize {
     std::intrinsics::ptr_metadata(x)
 }
 
+// Check that we only load the length once, rather than all 3 times.
+fn dedup_multiple_bounds_checks_lengths(x: &[i32]) -> [i32; 3] {
+    // CHECK-LABEL: fn dedup_multiple_bounds_checks_lengths
+    // CHECK: [[LEN:_.+]] = PtrMetadata(copy _1);
+    // CHECK: Lt(const 42_usize, copy [[LEN]]);
+    // CHECK: assert{{.+}}copy [[LEN]]
+    // CHECK: [[A:_.+]] = copy (*_1)[42 of 43];
+    // CHECK-NOT: PtrMetadata
+    // CHECK: Lt(const 13_usize, copy [[LEN]]);
+    // CHECK: assert{{.+}}copy [[LEN]]
+    // CHECK: [[B:_.+]] = copy (*_1)[13 of 14];
+    // CHECK-NOT: PtrMetadata
+    // CHECK: Lt(const 7_usize, copy [[LEN]]);
+    // CHECK: assert{{.+}}copy [[LEN]]
+    // CHECK: [[C:_.+]] = copy (*_1)[7 of 8];
+    // CHECK: _0 = [move [[A]], move [[B]], move [[C]]]
+    [x[42], x[13], x[7]]
+}
+
 #[custom_mir(dialect = "runtime")]
 fn generic_cast_metadata<T, A: ?Sized, B: ?Sized>(ps: *const [T], pa: *const A, pb: *const B) {
     // CHECK-LABEL: fn generic_cast_metadata
@@ -1012,6 +1031,7 @@ fn identity<T>(x: T) -> T {
 // EMIT_MIR gvn.casts_before_aggregate_raw_ptr.GVN.diff
 // EMIT_MIR gvn.manual_slice_mut_len.GVN.diff
 // EMIT_MIR gvn.array_len.GVN.diff
+// EMIT_MIR gvn.dedup_multiple_bounds_checks_lengths.GVN.diff
 // EMIT_MIR gvn.generic_cast_metadata.GVN.diff
 // EMIT_MIR gvn.cast_pointer_eq.GVN.diff
 // EMIT_MIR gvn.cast_pointer_then_transmute.GVN.diff
diff --git a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff
index 6b6152c1117..1b305e746f5 100644
--- a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff
+++ b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff
@@ -10,62 +10,60 @@
       let mut _6: &i32;
       let _7: &i32;
       let _8: usize;
-      let mut _9: usize;
-      let mut _10: bool;
-      let mut _12: *const dyn std::marker::Send;
-      let _13: &dyn std::marker::Send;
-      let mut _14: &i32;
-      let _15: &i32;
-      let _16: usize;
-      let mut _17: usize;
+      let mut _9: bool;
+      let mut _11: *const dyn std::marker::Send;
+      let _12: &dyn std::marker::Send;
+      let mut _13: &i32;
+      let _14: &i32;
+      let _15: usize;
+      let mut _16: bool;
+      let _17: ();
       let mut _18: bool;
-      let _19: ();
-      let mut _20: bool;
+      let mut _19: *const dyn std::marker::Send;
+      let mut _20: *const dyn std::marker::Send;
       let mut _21: *const dyn std::marker::Send;
-      let mut _22: *const dyn std::marker::Send;
-      let mut _23: *const dyn std::marker::Send;
-      let _24: ();
-      let mut _25: bool;
+      let _22: ();
+      let mut _23: bool;
+      let mut _24: *const dyn std::marker::Send;
+      let mut _25: *const dyn std::marker::Send;
       let mut _26: *const dyn std::marker::Send;
-      let mut _27: *const dyn std::marker::Send;
-      let mut _28: *const dyn std::marker::Send;
-      let _29: ();
-      let mut _30: bool;
+      let _27: ();
+      let mut _28: bool;
+      let mut _29: *const dyn std::marker::Send;
+      let mut _30: *const dyn std::marker::Send;
       let mut _31: *const dyn std::marker::Send;
-      let mut _32: *const dyn std::marker::Send;
-      let mut _33: *const dyn std::marker::Send;
-      let _34: ();
-      let mut _35: bool;
+      let _32: ();
+      let mut _33: bool;
+      let mut _34: *const dyn std::marker::Send;
+      let mut _35: *const dyn std::marker::Send;
       let mut _36: *const dyn std::marker::Send;
-      let mut _37: *const dyn std::marker::Send;
-      let mut _38: *const dyn std::marker::Send;
-      let _39: ();
-      let mut _40: bool;
+      let _37: ();
+      let mut _38: bool;
+      let mut _39: *const dyn std::marker::Send;
+      let mut _40: *const dyn std::marker::Send;
       let mut _41: *const dyn std::marker::Send;
-      let mut _42: *const dyn std::marker::Send;
-      let mut _43: *const dyn std::marker::Send;
-      let _44: ();
-      let mut _45: bool;
+      let _42: ();
+      let mut _43: bool;
+      let mut _44: *const dyn std::marker::Send;
+      let mut _45: *const dyn std::marker::Send;
       let mut _46: *const dyn std::marker::Send;
-      let mut _47: *const dyn std::marker::Send;
-      let mut _48: *const dyn std::marker::Send;
-      let mut _49: &[i32; 2];
+      let mut _47: &[i32; 2];
       scope 1 {
           debug slice => _1;
           let _3: *const dyn std::marker::Send;
           scope 2 {
               debug a => _3;
-              let _11: *const dyn std::marker::Send;
+              let _10: *const dyn std::marker::Send;
               scope 3 {
-                  debug b => _11;
+                  debug b => _10;
               }
           }
       }
   
       bb0: {
           StorageLive(_1);
-          _49 = const wide_ptr_same_provenance::promoted[0];
-          _1 = &(*_49);
+          _47 = const wide_ptr_same_provenance::promoted[0];
+          _1 = &(*_47);
           StorageLive(_3);
 -         StorageLive(_4);
 +         nop;
@@ -74,11 +72,9 @@
           StorageLive(_7);
           StorageLive(_8);
           _8 = const 0_usize;
--         _9 = Len((*_1));
--         _10 = Lt(copy _8, copy _9);
--         assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb1, unwind unreachable];
-+         _9 = const 2_usize;
-+         _10 = const true;
+-         _9 = Lt(copy _8, const 2_usize);
+-         assert(move _9, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _8) -> [success: bb1, unwind unreachable];
++         _9 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 2_usize, const 0_usize) -> [success: bb1, unwind unreachable];
       }
   
@@ -95,170 +91,168 @@
 +         nop;
           StorageDead(_7);
           StorageDead(_5);
-          StorageLive(_11);
--         StorageLive(_12);
+          StorageLive(_10);
+-         StorageLive(_11);
 +         nop;
+          StorageLive(_12);
           StorageLive(_13);
           StorageLive(_14);
           StorageLive(_15);
-          StorageLive(_16);
-          _16 = const 1_usize;
--         _17 = Len((*_1));
--         _18 = Lt(copy _16, copy _17);
--         assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, copy _16) -> [success: bb2, unwind unreachable];
-+         _17 = const 2_usize;
-+         _18 = const true;
+          _15 = const 1_usize;
+-         _16 = Lt(copy _15, const 2_usize);
+-         assert(move _16, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _15) -> [success: bb2, unwind unreachable];
++         _16 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 2_usize, const 1_usize) -> [success: bb2, unwind unreachable];
       }
   
       bb2: {
--         _15 = &(*_1)[_16];
-+         _15 = &(*_1)[1 of 2];
-          _14 = &(*_15);
-          _13 = move _14 as &dyn std::marker::Send (PointerCoercion(Unsize, AsCast));
-          StorageDead(_14);
-          _12 = &raw const (*_13);
--         _11 = move _12 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
--         StorageDead(_12);
-+         _11 = copy _12;
-+         nop;
-          StorageDead(_15);
+-         _14 = &(*_1)[_15];
++         _14 = &(*_1)[1 of 2];
+          _13 = &(*_14);
+          _12 = move _13 as &dyn std::marker::Send (PointerCoercion(Unsize, AsCast));
           StorageDead(_13);
+          _11 = &raw const (*_12);
+-         _10 = move _11 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
+-         StorageDead(_11);
++         _10 = copy _11;
++         nop;
+          StorageDead(_14);
+          StorageDead(_12);
+          StorageLive(_17);
+          StorageLive(_18);
           StorageLive(_19);
+-         _19 = copy _3;
++         _19 = copy _4;
           StorageLive(_20);
           StorageLive(_21);
--         _21 = copy _3;
-+         _21 = copy _4;
-          StorageLive(_22);
-          StorageLive(_23);
--         _23 = copy _11;
--         _22 = move _23 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
-+         _23 = copy _12;
-+         _22 = copy _12;
-          StorageDead(_23);
--         _20 = Eq(move _21, move _22);
-+         _20 = Eq(copy _4, copy _12);
-          StorageDead(_22);
+-         _21 = copy _10;
+-         _20 = move _21 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
++         _21 = copy _11;
++         _20 = copy _11;
           StorageDead(_21);
-          _19 = opaque::<bool>(move _20) -> [return: bb3, unwind unreachable];
+-         _18 = Eq(move _19, move _20);
++         _18 = Eq(copy _4, copy _11);
+          StorageDead(_20);
+          StorageDead(_19);
+          _17 = opaque::<bool>(move _18) -> [return: bb3, unwind unreachable];
       }
   
       bb3: {
-          StorageDead(_20);
-          StorageDead(_19);
+          StorageDead(_18);
+          StorageDead(_17);
+          StorageLive(_22);
+          StorageLive(_23);
           StorageLive(_24);
+-         _24 = copy _3;
++         _24 = copy _4;
           StorageLive(_25);
           StorageLive(_26);
--         _26 = copy _3;
-+         _26 = copy _4;
-          StorageLive(_27);
-          StorageLive(_28);
--         _28 = copy _11;
--         _27 = move _28 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
-+         _28 = copy _12;
-+         _27 = copy _12;
-          StorageDead(_28);
--         _25 = Ne(move _26, move _27);
-+         _25 = Ne(copy _4, copy _12);
-          StorageDead(_27);
+-         _26 = copy _10;
+-         _25 = move _26 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
++         _26 = copy _11;
++         _25 = copy _11;
           StorageDead(_26);
-          _24 = opaque::<bool>(move _25) -> [return: bb4, unwind unreachable];
+-         _23 = Ne(move _24, move _25);
++         _23 = Ne(copy _4, copy _11);
+          StorageDead(_25);
+          StorageDead(_24);
+          _22 = opaque::<bool>(move _23) -> [return: bb4, unwind unreachable];
       }
   
       bb4: {
-          StorageDead(_25);
-          StorageDead(_24);
+          StorageDead(_23);
+          StorageDead(_22);
+          StorageLive(_27);
+          StorageLive(_28);
           StorageLive(_29);
+-         _29 = copy _3;
++         _29 = copy _4;
           StorageLive(_30);
           StorageLive(_31);
--         _31 = copy _3;
-+         _31 = copy _4;
-          StorageLive(_32);
-          StorageLive(_33);
--         _33 = copy _11;
--         _32 = move _33 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
-+         _33 = copy _12;
-+         _32 = copy _12;
-          StorageDead(_33);
--         _30 = Lt(move _31, move _32);
-+         _30 = Lt(copy _4, copy _12);
-          StorageDead(_32);
+-         _31 = copy _10;
+-         _30 = move _31 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
++         _31 = copy _11;
++         _30 = copy _11;
           StorageDead(_31);
-          _29 = opaque::<bool>(move _30) -> [return: bb5, unwind unreachable];
+-         _28 = Lt(move _29, move _30);
++         _28 = Lt(copy _4, copy _11);
+          StorageDead(_30);
+          StorageDead(_29);
+          _27 = opaque::<bool>(move _28) -> [return: bb5, unwind unreachable];
       }
   
       bb5: {
-          StorageDead(_30);
-          StorageDead(_29);
+          StorageDead(_28);
+          StorageDead(_27);
+          StorageLive(_32);
+          StorageLive(_33);
           StorageLive(_34);
+-         _34 = copy _3;
++         _34 = copy _4;
           StorageLive(_35);
           StorageLive(_36);
--         _36 = copy _3;
-+         _36 = copy _4;
-          StorageLive(_37);
-          StorageLive(_38);
--         _38 = copy _11;
--         _37 = move _38 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
-+         _38 = copy _12;
-+         _37 = copy _12;
-          StorageDead(_38);
--         _35 = Le(move _36, move _37);
-+         _35 = Le(copy _4, copy _12);
-          StorageDead(_37);
+-         _36 = copy _10;
+-         _35 = move _36 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
++         _36 = copy _11;
++         _35 = copy _11;
           StorageDead(_36);
-          _34 = opaque::<bool>(move _35) -> [return: bb6, unwind unreachable];
+-         _33 = Le(move _34, move _35);
++         _33 = Le(copy _4, copy _11);
+          StorageDead(_35);
+          StorageDead(_34);
+          _32 = opaque::<bool>(move _33) -> [return: bb6, unwind unreachable];
       }
   
       bb6: {
-          StorageDead(_35);
-          StorageDead(_34);
+          StorageDead(_33);
+          StorageDead(_32);
+          StorageLive(_37);
+          StorageLive(_38);
           StorageLive(_39);
+-         _39 = copy _3;
++         _39 = copy _4;
           StorageLive(_40);
           StorageLive(_41);
--         _41 = copy _3;
-+         _41 = copy _4;
-          StorageLive(_42);
-          StorageLive(_43);
--         _43 = copy _11;
--         _42 = move _43 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
-+         _43 = copy _12;
-+         _42 = copy _12;
-          StorageDead(_43);
--         _40 = Gt(move _41, move _42);
-+         _40 = Gt(copy _4, copy _12);
-          StorageDead(_42);
+-         _41 = copy _10;
+-         _40 = move _41 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
++         _41 = copy _11;
++         _40 = copy _11;
           StorageDead(_41);
-          _39 = opaque::<bool>(move _40) -> [return: bb7, unwind unreachable];
+-         _38 = Gt(move _39, move _40);
++         _38 = Gt(copy _4, copy _11);
+          StorageDead(_40);
+          StorageDead(_39);
+          _37 = opaque::<bool>(move _38) -> [return: bb7, unwind unreachable];
       }
   
       bb7: {
-          StorageDead(_40);
-          StorageDead(_39);
+          StorageDead(_38);
+          StorageDead(_37);
+          StorageLive(_42);
+          StorageLive(_43);
           StorageLive(_44);
+-         _44 = copy _3;
++         _44 = copy _4;
           StorageLive(_45);
           StorageLive(_46);
--         _46 = copy _3;
-+         _46 = copy _4;
-          StorageLive(_47);
-          StorageLive(_48);
--         _48 = copy _11;
--         _47 = move _48 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
-+         _48 = copy _12;
-+         _47 = copy _12;
-          StorageDead(_48);
--         _45 = Ge(move _46, move _47);
-+         _45 = Ge(copy _4, copy _12);
-          StorageDead(_47);
+-         _46 = copy _10;
+-         _45 = move _46 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
++         _46 = copy _11;
++         _45 = copy _11;
           StorageDead(_46);
-          _44 = opaque::<bool>(move _45) -> [return: bb8, unwind unreachable];
+-         _43 = Ge(move _44, move _45);
++         _43 = Ge(copy _4, copy _11);
+          StorageDead(_45);
+          StorageDead(_44);
+          _42 = opaque::<bool>(move _43) -> [return: bb8, unwind unreachable];
       }
   
       bb8: {
-          StorageDead(_45);
-          StorageDead(_44);
+          StorageDead(_43);
+          StorageDead(_42);
           _0 = const ();
-          StorageDead(_16);
-          StorageDead(_11);
+          StorageDead(_15);
+          StorageDead(_10);
           StorageDead(_8);
           StorageDead(_3);
           StorageDead(_1);
diff --git a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff
index 093c1ec6ce3..e418ecf25bd 100644
--- a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff
+++ b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff
@@ -10,62 +10,60 @@
       let mut _6: &i32;
       let _7: &i32;
       let _8: usize;
-      let mut _9: usize;
-      let mut _10: bool;
-      let mut _12: *const dyn std::marker::Send;
-      let _13: &dyn std::marker::Send;
-      let mut _14: &i32;
-      let _15: &i32;
-      let _16: usize;
-      let mut _17: usize;
+      let mut _9: bool;
+      let mut _11: *const dyn std::marker::Send;
+      let _12: &dyn std::marker::Send;
+      let mut _13: &i32;
+      let _14: &i32;
+      let _15: usize;
+      let mut _16: bool;
+      let _17: ();
       let mut _18: bool;
-      let _19: ();
-      let mut _20: bool;
+      let mut _19: *const dyn std::marker::Send;
+      let mut _20: *const dyn std::marker::Send;
       let mut _21: *const dyn std::marker::Send;
-      let mut _22: *const dyn std::marker::Send;
-      let mut _23: *const dyn std::marker::Send;
-      let _24: ();
-      let mut _25: bool;
+      let _22: ();
+      let mut _23: bool;
+      let mut _24: *const dyn std::marker::Send;
+      let mut _25: *const dyn std::marker::Send;
       let mut _26: *const dyn std::marker::Send;
-      let mut _27: *const dyn std::marker::Send;
-      let mut _28: *const dyn std::marker::Send;
-      let _29: ();
-      let mut _30: bool;
+      let _27: ();
+      let mut _28: bool;
+      let mut _29: *const dyn std::marker::Send;
+      let mut _30: *const dyn std::marker::Send;
       let mut _31: *const dyn std::marker::Send;
-      let mut _32: *const dyn std::marker::Send;
-      let mut _33: *const dyn std::marker::Send;
-      let _34: ();
-      let mut _35: bool;
+      let _32: ();
+      let mut _33: bool;
+      let mut _34: *const dyn std::marker::Send;
+      let mut _35: *const dyn std::marker::Send;
       let mut _36: *const dyn std::marker::Send;
-      let mut _37: *const dyn std::marker::Send;
-      let mut _38: *const dyn std::marker::Send;
-      let _39: ();
-      let mut _40: bool;
+      let _37: ();
+      let mut _38: bool;
+      let mut _39: *const dyn std::marker::Send;
+      let mut _40: *const dyn std::marker::Send;
       let mut _41: *const dyn std::marker::Send;
-      let mut _42: *const dyn std::marker::Send;
-      let mut _43: *const dyn std::marker::Send;
-      let _44: ();
-      let mut _45: bool;
+      let _42: ();
+      let mut _43: bool;
+      let mut _44: *const dyn std::marker::Send;
+      let mut _45: *const dyn std::marker::Send;
       let mut _46: *const dyn std::marker::Send;
-      let mut _47: *const dyn std::marker::Send;
-      let mut _48: *const dyn std::marker::Send;
-      let mut _49: &[i32; 2];
+      let mut _47: &[i32; 2];
       scope 1 {
           debug slice => _1;
           let _3: *const dyn std::marker::Send;
           scope 2 {
               debug a => _3;
-              let _11: *const dyn std::marker::Send;
+              let _10: *const dyn std::marker::Send;
               scope 3 {
-                  debug b => _11;
+                  debug b => _10;
               }
           }
       }
   
       bb0: {
           StorageLive(_1);
-          _49 = const wide_ptr_same_provenance::promoted[0];
-          _1 = &(*_49);
+          _47 = const wide_ptr_same_provenance::promoted[0];
+          _1 = &(*_47);
           StorageLive(_3);
 -         StorageLive(_4);
 +         nop;
@@ -74,11 +72,9 @@
           StorageLive(_7);
           StorageLive(_8);
           _8 = const 0_usize;
--         _9 = Len((*_1));
--         _10 = Lt(copy _8, copy _9);
--         assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb1, unwind continue];
-+         _9 = const 2_usize;
-+         _10 = const true;
+-         _9 = Lt(copy _8, const 2_usize);
+-         assert(move _9, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _8) -> [success: bb1, unwind continue];
++         _9 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 2_usize, const 0_usize) -> [success: bb1, unwind continue];
       }
   
@@ -95,170 +91,168 @@
 +         nop;
           StorageDead(_7);
           StorageDead(_5);
-          StorageLive(_11);
--         StorageLive(_12);
+          StorageLive(_10);
+-         StorageLive(_11);
 +         nop;
+          StorageLive(_12);
           StorageLive(_13);
           StorageLive(_14);
           StorageLive(_15);
-          StorageLive(_16);
-          _16 = const 1_usize;
--         _17 = Len((*_1));
--         _18 = Lt(copy _16, copy _17);
--         assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, copy _16) -> [success: bb2, unwind continue];
-+         _17 = const 2_usize;
-+         _18 = const true;
+          _15 = const 1_usize;
+-         _16 = Lt(copy _15, const 2_usize);
+-         assert(move _16, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _15) -> [success: bb2, unwind continue];
++         _16 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 2_usize, const 1_usize) -> [success: bb2, unwind continue];
       }
   
       bb2: {
--         _15 = &(*_1)[_16];
-+         _15 = &(*_1)[1 of 2];
-          _14 = &(*_15);
-          _13 = move _14 as &dyn std::marker::Send (PointerCoercion(Unsize, AsCast));
-          StorageDead(_14);
-          _12 = &raw const (*_13);
--         _11 = move _12 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
--         StorageDead(_12);
-+         _11 = copy _12;
-+         nop;
-          StorageDead(_15);
+-         _14 = &(*_1)[_15];
++         _14 = &(*_1)[1 of 2];
+          _13 = &(*_14);
+          _12 = move _13 as &dyn std::marker::Send (PointerCoercion(Unsize, AsCast));
           StorageDead(_13);
+          _11 = &raw const (*_12);
+-         _10 = move _11 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
+-         StorageDead(_11);
++         _10 = copy _11;
++         nop;
+          StorageDead(_14);
+          StorageDead(_12);
+          StorageLive(_17);
+          StorageLive(_18);
           StorageLive(_19);
+-         _19 = copy _3;
++         _19 = copy _4;
           StorageLive(_20);
           StorageLive(_21);
--         _21 = copy _3;
-+         _21 = copy _4;
-          StorageLive(_22);
-          StorageLive(_23);
--         _23 = copy _11;
--         _22 = move _23 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
-+         _23 = copy _12;
-+         _22 = copy _12;
-          StorageDead(_23);
--         _20 = Eq(move _21, move _22);
-+         _20 = Eq(copy _4, copy _12);
-          StorageDead(_22);
+-         _21 = copy _10;
+-         _20 = move _21 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
++         _21 = copy _11;
++         _20 = copy _11;
           StorageDead(_21);
-          _19 = opaque::<bool>(move _20) -> [return: bb3, unwind continue];
+-         _18 = Eq(move _19, move _20);
++         _18 = Eq(copy _4, copy _11);
+          StorageDead(_20);
+          StorageDead(_19);
+          _17 = opaque::<bool>(move _18) -> [return: bb3, unwind continue];
       }
   
       bb3: {
-          StorageDead(_20);
-          StorageDead(_19);
+          StorageDead(_18);
+          StorageDead(_17);
+          StorageLive(_22);
+          StorageLive(_23);
           StorageLive(_24);
+-         _24 = copy _3;
++         _24 = copy _4;
           StorageLive(_25);
           StorageLive(_26);
--         _26 = copy _3;
-+         _26 = copy _4;
-          StorageLive(_27);
-          StorageLive(_28);
--         _28 = copy _11;
--         _27 = move _28 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
-+         _28 = copy _12;
-+         _27 = copy _12;
-          StorageDead(_28);
--         _25 = Ne(move _26, move _27);
-+         _25 = Ne(copy _4, copy _12);
-          StorageDead(_27);
+-         _26 = copy _10;
+-         _25 = move _26 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
++         _26 = copy _11;
++         _25 = copy _11;
           StorageDead(_26);
-          _24 = opaque::<bool>(move _25) -> [return: bb4, unwind continue];
+-         _23 = Ne(move _24, move _25);
++         _23 = Ne(copy _4, copy _11);
+          StorageDead(_25);
+          StorageDead(_24);
+          _22 = opaque::<bool>(move _23) -> [return: bb4, unwind continue];
       }
   
       bb4: {
-          StorageDead(_25);
-          StorageDead(_24);
+          StorageDead(_23);
+          StorageDead(_22);
+          StorageLive(_27);
+          StorageLive(_28);
           StorageLive(_29);
+-         _29 = copy _3;
++         _29 = copy _4;
           StorageLive(_30);
           StorageLive(_31);
--         _31 = copy _3;
-+         _31 = copy _4;
-          StorageLive(_32);
-          StorageLive(_33);
--         _33 = copy _11;
--         _32 = move _33 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
-+         _33 = copy _12;
-+         _32 = copy _12;
-          StorageDead(_33);
--         _30 = Lt(move _31, move _32);
-+         _30 = Lt(copy _4, copy _12);
-          StorageDead(_32);
+-         _31 = copy _10;
+-         _30 = move _31 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
++         _31 = copy _11;
++         _30 = copy _11;
           StorageDead(_31);
-          _29 = opaque::<bool>(move _30) -> [return: bb5, unwind continue];
+-         _28 = Lt(move _29, move _30);
++         _28 = Lt(copy _4, copy _11);
+          StorageDead(_30);
+          StorageDead(_29);
+          _27 = opaque::<bool>(move _28) -> [return: bb5, unwind continue];
       }
   
       bb5: {
-          StorageDead(_30);
-          StorageDead(_29);
+          StorageDead(_28);
+          StorageDead(_27);
+          StorageLive(_32);
+          StorageLive(_33);
           StorageLive(_34);
+-         _34 = copy _3;
++         _34 = copy _4;
           StorageLive(_35);
           StorageLive(_36);
--         _36 = copy _3;
-+         _36 = copy _4;
-          StorageLive(_37);
-          StorageLive(_38);
--         _38 = copy _11;
--         _37 = move _38 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
-+         _38 = copy _12;
-+         _37 = copy _12;
-          StorageDead(_38);
--         _35 = Le(move _36, move _37);
-+         _35 = Le(copy _4, copy _12);
-          StorageDead(_37);
+-         _36 = copy _10;
+-         _35 = move _36 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
++         _36 = copy _11;
++         _35 = copy _11;
           StorageDead(_36);
-          _34 = opaque::<bool>(move _35) -> [return: bb6, unwind continue];
+-         _33 = Le(move _34, move _35);
++         _33 = Le(copy _4, copy _11);
+          StorageDead(_35);
+          StorageDead(_34);
+          _32 = opaque::<bool>(move _33) -> [return: bb6, unwind continue];
       }
   
       bb6: {
-          StorageDead(_35);
-          StorageDead(_34);
+          StorageDead(_33);
+          StorageDead(_32);
+          StorageLive(_37);
+          StorageLive(_38);
           StorageLive(_39);
+-         _39 = copy _3;
++         _39 = copy _4;
           StorageLive(_40);
           StorageLive(_41);
--         _41 = copy _3;
-+         _41 = copy _4;
-          StorageLive(_42);
-          StorageLive(_43);
--         _43 = copy _11;
--         _42 = move _43 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
-+         _43 = copy _12;
-+         _42 = copy _12;
-          StorageDead(_43);
--         _40 = Gt(move _41, move _42);
-+         _40 = Gt(copy _4, copy _12);
-          StorageDead(_42);
+-         _41 = copy _10;
+-         _40 = move _41 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
++         _41 = copy _11;
++         _40 = copy _11;
           StorageDead(_41);
-          _39 = opaque::<bool>(move _40) -> [return: bb7, unwind continue];
+-         _38 = Gt(move _39, move _40);
++         _38 = Gt(copy _4, copy _11);
+          StorageDead(_40);
+          StorageDead(_39);
+          _37 = opaque::<bool>(move _38) -> [return: bb7, unwind continue];
       }
   
       bb7: {
-          StorageDead(_40);
-          StorageDead(_39);
+          StorageDead(_38);
+          StorageDead(_37);
+          StorageLive(_42);
+          StorageLive(_43);
           StorageLive(_44);
+-         _44 = copy _3;
++         _44 = copy _4;
           StorageLive(_45);
           StorageLive(_46);
--         _46 = copy _3;
-+         _46 = copy _4;
-          StorageLive(_47);
-          StorageLive(_48);
--         _48 = copy _11;
--         _47 = move _48 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
-+         _48 = copy _12;
-+         _47 = copy _12;
-          StorageDead(_48);
--         _45 = Ge(move _46, move _47);
-+         _45 = Ge(copy _4, copy _12);
-          StorageDead(_47);
+-         _46 = copy _10;
+-         _45 = move _46 as *const dyn std::marker::Send (PointerCoercion(Unsize, Implicit));
++         _46 = copy _11;
++         _45 = copy _11;
           StorageDead(_46);
-          _44 = opaque::<bool>(move _45) -> [return: bb8, unwind continue];
+-         _43 = Ge(move _44, move _45);
++         _43 = Ge(copy _4, copy _11);
+          StorageDead(_45);
+          StorageDead(_44);
+          _42 = opaque::<bool>(move _43) -> [return: bb8, unwind continue];
       }
   
       bb8: {
-          StorageDead(_45);
-          StorageDead(_44);
+          StorageDead(_43);
+          StorageDead(_42);
           _0 = const ();
-          StorageDead(_16);
-          StorageDead(_11);
+          StorageDead(_15);
+          StorageDead(_10);
           StorageDead(_8);
           StorageDead(_3);
           StorageDead(_1);
diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
index 94017f028cc..56d4d50e967 100644
--- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
@@ -16,7 +16,6 @@
 +     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) {
 +         debug pointer => _3;
 +         scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) {
-+             debug pointer => _3;
 +         }
 +     }
 +     scope 5 (inlined g::{closure#0}) {
diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
index 858f9ace9b4..751916a00f1 100644
--- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
@@ -16,7 +16,6 @@
 +     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) {
 +         debug pointer => _3;
 +         scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) {
-+             debug pointer => _3;
 +         }
 +     }
 +     scope 5 (inlined g::{closure#0}) {
diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff
deleted file mode 100644
index f39df7ffca0..00000000000
--- a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff
+++ /dev/null
@@ -1,77 +0,0 @@
-- // MIR for `norm2` before InstSimplify-after-simplifycfg
-+ // MIR for `norm2` after InstSimplify-after-simplifycfg
-  
-  fn norm2(_1: [f32; 2]) -> f32 {
-      debug x => _1;
-      let mut _0: f32;
-      let _2: f32;
-      let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
-      let _7: usize;
-      let mut _8: usize;
-      let mut _9: bool;
-      let mut _10: f32;
-      let mut _11: f32;
-      let mut _12: f32;
-      let mut _13: f32;
-      let mut _14: f32;
-      let mut _15: f32;
-      scope 1 {
-          debug a => _2;
-          let _6: f32;
-          scope 2 {
-              debug b => _6;
-          }
-      }
-  
-      bb0: {
-          StorageLive(_2);
-          StorageLive(_3);
-          _3 = const 0_usize;
--         _4 = Len(_1);
-+         _4 = const 2_usize;
-          _5 = Lt(copy _3, copy _4);
-          assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind unreachable];
-      }
-  
-      bb1: {
-          _2 = copy _1[_3];
-          StorageDead(_3);
-          StorageLive(_6);
-          StorageLive(_7);
-          _7 = const 1_usize;
--         _8 = Len(_1);
-+         _8 = const 2_usize;
-          _9 = Lt(copy _7, copy _8);
-          assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind unreachable];
-      }
-  
-      bb2: {
-          _6 = copy _1[_7];
-          StorageDead(_7);
-          StorageLive(_10);
-          StorageLive(_11);
-          _11 = copy _2;
-          StorageLive(_12);
-          _12 = copy _2;
-          _10 = Mul(move _11, move _12);
-          StorageDead(_12);
-          StorageDead(_11);
-          StorageLive(_13);
-          StorageLive(_14);
-          _14 = copy _6;
-          StorageLive(_15);
-          _15 = copy _6;
-          _13 = Mul(move _14, move _15);
-          StorageDead(_15);
-          StorageDead(_14);
-          _0 = Add(move _10, move _13);
-          StorageDead(_13);
-          StorageDead(_10);
-          StorageDead(_6);
-          StorageDead(_2);
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff
deleted file mode 100644
index 0e7d5653c68..00000000000
--- a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff
+++ /dev/null
@@ -1,77 +0,0 @@
-- // MIR for `norm2` before InstSimplify-after-simplifycfg
-+ // MIR for `norm2` after InstSimplify-after-simplifycfg
-  
-  fn norm2(_1: [f32; 2]) -> f32 {
-      debug x => _1;
-      let mut _0: f32;
-      let _2: f32;
-      let _3: usize;
-      let mut _4: usize;
-      let mut _5: bool;
-      let _7: usize;
-      let mut _8: usize;
-      let mut _9: bool;
-      let mut _10: f32;
-      let mut _11: f32;
-      let mut _12: f32;
-      let mut _13: f32;
-      let mut _14: f32;
-      let mut _15: f32;
-      scope 1 {
-          debug a => _2;
-          let _6: f32;
-          scope 2 {
-              debug b => _6;
-          }
-      }
-  
-      bb0: {
-          StorageLive(_2);
-          StorageLive(_3);
-          _3 = const 0_usize;
--         _4 = Len(_1);
-+         _4 = const 2_usize;
-          _5 = Lt(copy _3, copy _4);
-          assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind continue];
-      }
-  
-      bb1: {
-          _2 = copy _1[_3];
-          StorageDead(_3);
-          StorageLive(_6);
-          StorageLive(_7);
-          _7 = const 1_usize;
--         _8 = Len(_1);
-+         _8 = const 2_usize;
-          _9 = Lt(copy _7, copy _8);
-          assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb2, unwind continue];
-      }
-  
-      bb2: {
-          _6 = copy _1[_7];
-          StorageDead(_7);
-          StorageLive(_10);
-          StorageLive(_11);
-          _11 = copy _2;
-          StorageLive(_12);
-          _12 = copy _2;
-          _10 = Mul(move _11, move _12);
-          StorageDead(_12);
-          StorageDead(_11);
-          StorageLive(_13);
-          StorageLive(_14);
-          _14 = copy _6;
-          StorageLive(_15);
-          _15 = copy _6;
-          _13 = Mul(move _14, move _15);
-          StorageDead(_15);
-          StorageDead(_14);
-          _0 = Add(move _10, move _13);
-          StorageDead(_13);
-          StorageDead(_10);
-          StorageDead(_6);
-          StorageDead(_2);
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/instsimplify/combine_array_len.rs b/tests/mir-opt/instsimplify/combine_array_len.rs
deleted file mode 100644
index 91f43f75689..00000000000
--- a/tests/mir-opt/instsimplify/combine_array_len.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
-//@ test-mir-pass: InstSimplify-after-simplifycfg
-
-// EMIT_MIR combine_array_len.norm2.InstSimplify-after-simplifycfg.diff
-fn norm2(x: [f32; 2]) -> f32 {
-    // CHECK-LABEL: fn norm2(
-    // CHECK-NOT: Len(
-    let a = x[0];
-    let b = x[1];
-    a * a + b * b
-}
-
-fn main() {
-    assert_eq!(norm2([3.0, 4.0]), 5.0 * 5.0);
-}
diff --git a/tests/mir-opt/issue_72181.foo.built.after.mir b/tests/mir-opt/issue_72181.foo.built.after.mir
index 314cf8b367f..7593b795432 100644
--- a/tests/mir-opt/issue_72181.foo.built.after.mir
+++ b/tests/mir-opt/issue_72181.foo.built.after.mir
@@ -4,15 +4,14 @@ fn foo(_1: [(Never, u32); 1]) -> u32 {
     debug xs => _1;
     let mut _0: u32;
     let _2: usize;
-    let mut _3: usize;
-    let mut _4: bool;
+    let mut _3: bool;
 
     bb0: {
         StorageLive(_2);
         _2 = const 0_usize;
-        _3 = Len(_1);
-        _4 = Lt(copy _2, copy _3);
-        assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, copy _2) -> [success: bb1, unwind: bb2];
+        FakeRead(ForIndex, _1);
+        _3 = Lt(copy _2, const 1_usize);
+        assert(move _3, "index out of bounds: the length is {} but the index is {}", const 1_usize, copy _2) -> [success: bb1, unwind: bb2];
     }
 
     bb1: {
diff --git a/tests/mir-opt/issue_72181.main.built.after.mir b/tests/mir-opt/issue_72181.main.built.after.mir
index aade84a6dd2..9f3803f5407 100644
--- a/tests/mir-opt/issue_72181.main.built.after.mir
+++ b/tests/mir-opt/issue_72181.main.built.after.mir
@@ -7,8 +7,7 @@ fn main() -> () {
     let mut _4: Foo;
     let mut _5: u64;
     let _6: usize;
-    let mut _7: usize;
-    let mut _8: bool;
+    let mut _7: bool;
     scope 1 {
         let _2: [Foo; 2];
         scope 2 {
@@ -38,9 +37,9 @@ fn main() -> () {
         StorageLive(_5);
         StorageLive(_6);
         _6 = const 0_usize;
-        _7 = Len(_2);
-        _8 = Lt(copy _6, copy _7);
-        assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb3, unwind: bb5];
+        FakeRead(ForIndex, _2);
+        _7 = Lt(copy _6, const 2_usize);
+        assert(move _7, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _6) -> [success: bb3, unwind: bb5];
     }
 
     bb2: {
diff --git a/tests/mir-opt/issue_91633.foo.built.after.mir b/tests/mir-opt/issue_91633.foo.built.after.mir
index 50fdf08375a..bf65b5b4a8c 100644
--- a/tests/mir-opt/issue_91633.foo.built.after.mir
+++ b/tests/mir-opt/issue_91633.foo.built.after.mir
@@ -6,8 +6,9 @@ fn foo(_1: Box<[T]>) -> T {
     let _2: T;
     let mut _3: &T;
     let _4: usize;
-    let mut _5: usize;
-    let mut _6: bool;
+    let mut _5: *const [T];
+    let mut _6: usize;
+    let mut _7: bool;
     scope 1 {
         debug f => _2;
     }
@@ -17,9 +18,10 @@ fn foo(_1: Box<[T]>) -> T {
         StorageLive(_3);
         StorageLive(_4);
         _4 = const 0_usize;
-        _5 = Len((*_1));
-        _6 = Lt(copy _4, copy _5);
-        assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, copy _4) -> [success: bb1, unwind: bb5];
+        _5 = &raw const (*_1);
+        _6 = PtrMetadata(move _5);
+        _7 = Lt(copy _4, copy _6);
+        assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _4) -> [success: bb1, unwind: bb5];
     }
 
     bb1: {
diff --git a/tests/mir-opt/issue_91633.fun.built.after.mir b/tests/mir-opt/issue_91633.fun.built.after.mir
index 5b41b376719..d2fc438d3e8 100644
--- a/tests/mir-opt/issue_91633.fun.built.after.mir
+++ b/tests/mir-opt/issue_91633.fun.built.after.mir
@@ -15,7 +15,7 @@ fn fun(_1: &[T]) -> &T {
         StorageLive(_2);
         StorageLive(_3);
         _3 = const 0_usize;
-        _4 = Len((*_1));
+        _4 = PtrMetadata(copy _1);
         _5 = Lt(copy _3, copy _4);
         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind: bb2];
     }
diff --git a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff
index f052c8f63dc..98c5e868046 100644
--- a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff
+++ b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff
@@ -11,16 +11,14 @@
       let mut _6: &[u8];
       let mut _7: &[u8; N];
       let _8: usize;
-      let mut _9: usize;
-      let mut _10: bool;
+      let mut _9: bool;
   
       bb0: {
 -         StorageLive(_3);
 +         nop;
           StorageLive(_4);
           _4 = copy _1;
--         StorageLive(_5);
-+         nop;
+          StorageLive(_5);
           StorageLive(_6);
           StorageLive(_7);
           _7 = &(*_2);
@@ -40,16 +38,13 @@
       }
   
       bb2: {
--         StorageDead(_5);
-+         nop;
+          StorageDead(_5);
           StorageDead(_4);
           StorageLive(_8);
           _8 = copy _1;
--         _9 = Len((*_2));
--         _10 = Lt(copy _8, copy _9);
--         assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind unreachable];
-+         _9 = const N;
-+         _10 = copy _3;
+-         _9 = Lt(copy _8, const N);
+-         assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb3, unwind unreachable];
++         _9 = copy _3;
 +         assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind unreachable];
       }
   
@@ -61,8 +56,7 @@
       }
   
       bb4: {
--         StorageDead(_5);
-+         nop;
+          StorageDead(_5);
           StorageDead(_4);
           _0 = const 42_u8;
           goto -> bb5;
diff --git a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff
index 3299e300431..72c73137869 100644
--- a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff
+++ b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff
@@ -11,16 +11,14 @@
       let mut _6: &[u8];
       let mut _7: &[u8; N];
       let _8: usize;
-      let mut _9: usize;
-      let mut _10: bool;
+      let mut _9: bool;
   
       bb0: {
 -         StorageLive(_3);
 +         nop;
           StorageLive(_4);
           _4 = copy _1;
--         StorageLive(_5);
-+         nop;
+          StorageLive(_5);
           StorageLive(_6);
           StorageLive(_7);
           _7 = &(*_2);
@@ -40,16 +38,13 @@
       }
   
       bb2: {
--         StorageDead(_5);
-+         nop;
+          StorageDead(_5);
           StorageDead(_4);
           StorageLive(_8);
           _8 = copy _1;
--         _9 = Len((*_2));
--         _10 = Lt(copy _8, copy _9);
--         assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind continue];
-+         _9 = const N;
-+         _10 = copy _3;
+-         _9 = Lt(copy _8, const N);
+-         assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb3, unwind continue];
++         _9 = copy _3;
 +         assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind continue];
       }
   
@@ -61,8 +56,7 @@
       }
   
       bb4: {
--         StorageDead(_5);
-+         nop;
+          StorageDead(_5);
           StorageDead(_4);
           _0 = const 42_u8;
           goto -> bb5;
diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff
index 329eb80b3c4..9ffaf44c02b 100644
--- a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff
+++ b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff
@@ -11,19 +11,16 @@
       let mut _6: &[u8];
       let mut _7: &[u8; N];
       let _8: usize;
-      let mut _9: usize;
-      let mut _10: bool;
-      let _11: usize;
-      let mut _12: usize;
-      let mut _13: bool;
+      let mut _9: bool;
+      let _10: usize;
+      let mut _11: bool;
   
       bb0: {
 -         StorageLive(_3);
 +         nop;
           StorageLive(_4);
           _4 = copy _1;
--         StorageLive(_5);
-+         nop;
+          StorageLive(_5);
           StorageLive(_6);
           StorageLive(_7);
           _7 = &(*_2);
@@ -43,16 +40,13 @@
       }
   
       bb2: {
--         StorageDead(_5);
-+         nop;
+          StorageDead(_5);
           StorageDead(_4);
           StorageLive(_8);
           _8 = copy _1;
--         _9 = Len((*_2));
--         _10 = Lt(copy _8, copy _9);
--         assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind unreachable];
-+         _9 = const N;
-+         _10 = copy _3;
+-         _9 = Lt(copy _8, const N);
+-         assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb3, unwind unreachable];
++         _9 = copy _3;
 +         assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind unreachable];
       }
   
@@ -64,23 +58,20 @@
       }
   
       bb4: {
--         StorageDead(_5);
-+         nop;
+          StorageDead(_5);
           StorageDead(_4);
-          StorageLive(_11);
-          _11 = const 0_usize;
--         _12 = Len((*_2));
--         _13 = Lt(copy _11, copy _12);
--         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb5, unwind unreachable];
-+         _12 = const N;
-+         _13 = Lt(const 0_usize, const N);
-+         assert(move _13, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb5, unwind unreachable];
+          StorageLive(_10);
+          _10 = const 0_usize;
+-         _11 = Lt(copy _10, const N);
+-         assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, copy _10) -> [success: bb5, unwind unreachable];
++         _11 = Lt(const 0_usize, const N);
++         assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb5, unwind unreachable];
       }
   
       bb5: {
--         (*_2)[_11] = const 42_u8;
+-         (*_2)[_10] = const 42_u8;
 +         (*_2)[0 of 1] = const 42_u8;
-          StorageDead(_11);
+          StorageDead(_10);
           _0 = const 42_u8;
           goto -> bb6;
       }
diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff
index ab007e133ec..08008e46335 100644
--- a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff
+++ b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff
@@ -11,19 +11,16 @@
       let mut _6: &[u8];
       let mut _7: &[u8; N];
       let _8: usize;
-      let mut _9: usize;
-      let mut _10: bool;
-      let _11: usize;
-      let mut _12: usize;
-      let mut _13: bool;
+      let mut _9: bool;
+      let _10: usize;
+      let mut _11: bool;
   
       bb0: {
 -         StorageLive(_3);
 +         nop;
           StorageLive(_4);
           _4 = copy _1;
--         StorageLive(_5);
-+         nop;
+          StorageLive(_5);
           StorageLive(_6);
           StorageLive(_7);
           _7 = &(*_2);
@@ -43,16 +40,13 @@
       }
   
       bb2: {
--         StorageDead(_5);
-+         nop;
+          StorageDead(_5);
           StorageDead(_4);
           StorageLive(_8);
           _8 = copy _1;
--         _9 = Len((*_2));
--         _10 = Lt(copy _8, copy _9);
--         assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, copy _8) -> [success: bb3, unwind continue];
-+         _9 = const N;
-+         _10 = copy _3;
+-         _9 = Lt(copy _8, const N);
+-         assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb3, unwind continue];
++         _9 = copy _3;
 +         assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind continue];
       }
   
@@ -64,23 +58,20 @@
       }
   
       bb4: {
--         StorageDead(_5);
-+         nop;
+          StorageDead(_5);
           StorageDead(_4);
-          StorageLive(_11);
-          _11 = const 0_usize;
--         _12 = Len((*_2));
--         _13 = Lt(copy _11, copy _12);
--         assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb5, unwind continue];
-+         _12 = const N;
-+         _13 = Lt(const 0_usize, const N);
-+         assert(move _13, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb5, unwind continue];
+          StorageLive(_10);
+          _10 = const 0_usize;
+-         _11 = Lt(copy _10, const N);
+-         assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, copy _10) -> [success: bb5, unwind continue];
++         _11 = Lt(const 0_usize, const N);
++         assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb5, unwind continue];
       }
   
       bb5: {
--         (*_2)[_11] = const 42_u8;
+-         (*_2)[_10] = const 42_u8;
 +         (*_2)[0 of 1] = const 42_u8;
-          StorageDead(_11);
+          StorageDead(_10);
           _0 = const 42_u8;
           goto -> bb6;
       }
diff --git a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-abort.diff b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-abort.diff
index 20001f1248e..4b39e18d16c 100644
--- a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-abort.diff
+++ b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-abort.diff
@@ -36,7 +36,7 @@
           StorageDead(_4);
           StorageLive(_7);
           _7 = copy _1;
-          _8 = Len((*_2));
+          _8 = PtrMetadata(copy _2);
           _9 = Lt(copy _7, copy _8);
           assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb3, unwind unreachable];
       }
diff --git a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff
index ca8f92df5de..f0d4afa21ae 100644
--- a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff
+++ b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.panic-unwind.diff
@@ -36,7 +36,7 @@
           StorageDead(_4);
           StorageLive(_7);
           _7 = copy _1;
-          _8 = Len((*_2));
+          _8 = PtrMetadata(copy _2);
           _9 = Lt(copy _7, copy _8);
           assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, copy _7) -> [success: bb3, unwind continue];
       }
diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
index 7294302609a..35e44b2314a 100644
--- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
+++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
@@ -27,20 +27,19 @@ fn main() -> () {
     let mut _0: ();
     let mut _1: [usize; ValTree(Leaf(0x00000003): usize)];
     let _3: usize;
-    let mut _4: usize;
-    let mut _5: bool;
-    let mut _7: bool;
-    let _8: bool;
-    let mut _9: usize;
-    let _10: bool;
+    let mut _4: bool;
+    let mut _6: bool;
+    let _7: bool;
+    let mut _8: usize;
+    let _9: bool;
     scope 1 {
         debug v => _1;
         let _2: &'?3 usize;
         scope 2 {
             debug p => _2;
-            let _6: &'?4 usize;
+            let _5: &'?4 usize;
             scope 3 {
-                debug q => _6;
+                debug q => _5;
             }
         }
     }
@@ -52,50 +51,50 @@ fn main() -> () {
         StorageLive(_2);
         StorageLive(_3);
         _3 = const ConstValue(Scalar(0x00000000): usize);
-        _4 = Len(_1);
-        _5 = Lt(copy _3, copy _4);
-        assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind: bb7];
+        FakeRead(ForIndex, _1);
+        _4 = Lt(copy _3, const ConstValue(Scalar(0x00000003): usize));
+        assert(move _4, "index out of bounds: the length is {} but the index is {}", const ConstValue(Scalar(0x00000003): usize), copy _3) -> [success: bb1, unwind: bb7];
     }
 
     bb1: {
         _2 = &'?2 _1[_3];
         FakeRead(ForLet(None), _2);
+        StorageLive(_5);
+        _5 = copy _2;
+        FakeRead(ForLet(None), _5);
         StorageLive(_6);
-        _6 = copy _2;
-        FakeRead(ForLet(None), _6);
-        StorageLive(_7);
-        _7 = const ConstValue(Scalar(0x01): bool);
-        switchInt(move _7) -> [0: bb4, otherwise: bb2];
+        _6 = const ConstValue(Scalar(0x01): bool);
+        switchInt(move _6) -> [0: bb4, otherwise: bb2];
     }
 
     bb2: {
+        StorageLive(_7);
         StorageLive(_8);
-        StorageLive(_9);
-        _9 = copy (*_6);
-        _8 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7];
+        _8 = copy (*_5);
+        _7 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _8) -> [return: bb3, unwind: bb7];
     }
 
     bb3: {
-        StorageDead(_9);
         StorageDead(_8);
+        StorageDead(_7);
         _0 = const ConstValue(ZeroSized: ());
         goto -> bb6;
     }
 
     bb4: {
-        StorageLive(_10);
-        _10 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x00000016): usize)) -> [return: bb5, unwind: bb7];
+        StorageLive(_9);
+        _9 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x00000016): usize)) -> [return: bb5, unwind: bb7];
     }
 
     bb5: {
-        StorageDead(_10);
+        StorageDead(_9);
         _0 = const ConstValue(ZeroSized: ());
         goto -> bb6;
     }
 
     bb6: {
-        StorageDead(_7);
         StorageDead(_6);
+        StorageDead(_5);
         StorageDead(_3);
         StorageDead(_2);
         StorageDead(_1);
diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
index 85b89a013c4..6d415f42d06 100644
--- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
+++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
@@ -27,20 +27,19 @@ fn main() -> () {
     let mut _0: ();
     let mut _1: [usize; ValTree(Leaf(0x0000000000000003): usize)];
     let _3: usize;
-    let mut _4: usize;
-    let mut _5: bool;
-    let mut _7: bool;
-    let _8: bool;
-    let mut _9: usize;
-    let _10: bool;
+    let mut _4: bool;
+    let mut _6: bool;
+    let _7: bool;
+    let mut _8: usize;
+    let _9: bool;
     scope 1 {
         debug v => _1;
         let _2: &'?3 usize;
         scope 2 {
             debug p => _2;
-            let _6: &'?4 usize;
+            let _5: &'?4 usize;
             scope 3 {
-                debug q => _6;
+                debug q => _5;
             }
         }
     }
@@ -52,50 +51,50 @@ fn main() -> () {
         StorageLive(_2);
         StorageLive(_3);
         _3 = const ConstValue(Scalar(0x0000000000000000): usize);
-        _4 = Len(_1);
-        _5 = Lt(copy _3, copy _4);
-        assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, copy _3) -> [success: bb1, unwind: bb7];
+        FakeRead(ForIndex, _1);
+        _4 = Lt(copy _3, const ConstValue(Scalar(0x0000000000000003): usize));
+        assert(move _4, "index out of bounds: the length is {} but the index is {}", const ConstValue(Scalar(0x0000000000000003): usize), copy _3) -> [success: bb1, unwind: bb7];
     }
 
     bb1: {
         _2 = &'?2 _1[_3];
         FakeRead(ForLet(None), _2);
+        StorageLive(_5);
+        _5 = copy _2;
+        FakeRead(ForLet(None), _5);
         StorageLive(_6);
-        _6 = copy _2;
-        FakeRead(ForLet(None), _6);
-        StorageLive(_7);
-        _7 = const ConstValue(Scalar(0x01): bool);
-        switchInt(move _7) -> [0: bb4, otherwise: bb2];
+        _6 = const ConstValue(Scalar(0x01): bool);
+        switchInt(move _6) -> [0: bb4, otherwise: bb2];
     }
 
     bb2: {
+        StorageLive(_7);
         StorageLive(_8);
-        StorageLive(_9);
-        _9 = copy (*_6);
-        _8 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7];
+        _8 = copy (*_5);
+        _7 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(move _8) -> [return: bb3, unwind: bb7];
     }
 
     bb3: {
-        StorageDead(_9);
         StorageDead(_8);
+        StorageDead(_7);
         _0 = const ConstValue(ZeroSized: ());
         goto -> bb6;
     }
 
     bb4: {
-        StorageLive(_10);
-        _10 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x0000000000000016): usize)) -> [return: bb5, unwind: bb7];
+        StorageLive(_9);
+        _9 = ConstValue(ZeroSized: fn(usize) -> bool {use_x})(const ConstValue(Scalar(0x0000000000000016): usize)) -> [return: bb5, unwind: bb7];
     }
 
     bb5: {
-        StorageDead(_10);
+        StorageDead(_9);
         _0 = const ConstValue(ZeroSized: ());
         goto -> bb6;
     }
 
     bb6: {
-        StorageDead(_7);
         StorageDead(_6);
+        StorageDead(_5);
         StorageDead(_3);
         StorageDead(_2);
         StorageDead(_1);
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff
index 6575610727b..5b39e45806e 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-abort.diff
@@ -7,17 +7,16 @@
       let mut _2: (i32, bool);
       let mut _4: [i32; 6];
       let _5: usize;
-      let mut _6: usize;
-      let mut _7: bool;
-      let mut _9: u32;
+      let mut _6: bool;
+      let mut _8: u32;
       scope 1 {
           debug x => _1;
           let _3: i32;
           scope 2 {
               debug y => _3;
-              let _8: u32;
+              let _7: u32;
               scope 3 {
-                  debug z => _8;
+                  debug z => _7;
               }
           }
       }
@@ -38,10 +37,9 @@
           _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
           StorageLive(_5);
           _5 = const 3_usize;
-          _6 = const 6_usize;
--         _7 = Lt(copy _5, copy _6);
--         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind unreachable];
-+         _7 = const true;
+-         _6 = Lt(copy _5, const 6_usize);
+-         assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind unreachable];
++         _6 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind unreachable];
       }
   
@@ -50,13 +48,13 @@
 +         _3 = const 3_i32;
           StorageDead(_5);
           StorageDead(_4);
+          StorageLive(_7);
           StorageLive(_8);
-          StorageLive(_9);
-          _9 = const 42_u32;
--         _8 = copy _9;
-+         _8 = const 42_u32;
-          StorageDead(_9);
+          _8 = const 42_u32;
+-         _7 = copy _8;
++         _7 = const 42_u32;
           StorageDead(_8);
+          StorageDead(_7);
           StorageDead(_3);
           StorageDead(_1);
           return;
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff
index 1a4ed5767fe..ea2742a6471 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.32bit.panic-unwind.diff
@@ -7,17 +7,16 @@
       let mut _2: (i32, bool);
       let mut _4: [i32; 6];
       let _5: usize;
-      let mut _6: usize;
-      let mut _7: bool;
-      let mut _9: u32;
+      let mut _6: bool;
+      let mut _8: u32;
       scope 1 {
           debug x => _1;
           let _3: i32;
           scope 2 {
               debug y => _3;
-              let _8: u32;
+              let _7: u32;
               scope 3 {
-                  debug z => _8;
+                  debug z => _7;
               }
           }
       }
@@ -38,10 +37,9 @@
           _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
           StorageLive(_5);
           _5 = const 3_usize;
-          _6 = const 6_usize;
--         _7 = Lt(copy _5, copy _6);
--         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind continue];
-+         _7 = const true;
+-         _6 = Lt(copy _5, const 6_usize);
+-         assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind continue];
++         _6 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind continue];
       }
   
@@ -50,13 +48,13 @@
 +         _3 = const 3_i32;
           StorageDead(_5);
           StorageDead(_4);
+          StorageLive(_7);
           StorageLive(_8);
-          StorageLive(_9);
-          _9 = const 42_u32;
--         _8 = copy _9;
-+         _8 = const 42_u32;
-          StorageDead(_9);
+          _8 = const 42_u32;
+-         _7 = copy _8;
++         _7 = const 42_u32;
           StorageDead(_8);
+          StorageDead(_7);
           StorageDead(_3);
           StorageDead(_1);
           return;
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff
index 6575610727b..5b39e45806e 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-abort.diff
@@ -7,17 +7,16 @@
       let mut _2: (i32, bool);
       let mut _4: [i32; 6];
       let _5: usize;
-      let mut _6: usize;
-      let mut _7: bool;
-      let mut _9: u32;
+      let mut _6: bool;
+      let mut _8: u32;
       scope 1 {
           debug x => _1;
           let _3: i32;
           scope 2 {
               debug y => _3;
-              let _8: u32;
+              let _7: u32;
               scope 3 {
-                  debug z => _8;
+                  debug z => _7;
               }
           }
       }
@@ -38,10 +37,9 @@
           _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
           StorageLive(_5);
           _5 = const 3_usize;
-          _6 = const 6_usize;
--         _7 = Lt(copy _5, copy _6);
--         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind unreachable];
-+         _7 = const true;
+-         _6 = Lt(copy _5, const 6_usize);
+-         assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind unreachable];
++         _6 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind unreachable];
       }
   
@@ -50,13 +48,13 @@
 +         _3 = const 3_i32;
           StorageDead(_5);
           StorageDead(_4);
+          StorageLive(_7);
           StorageLive(_8);
-          StorageLive(_9);
-          _9 = const 42_u32;
--         _8 = copy _9;
-+         _8 = const 42_u32;
-          StorageDead(_9);
+          _8 = const 42_u32;
+-         _7 = copy _8;
++         _7 = const 42_u32;
           StorageDead(_8);
+          StorageDead(_7);
           StorageDead(_3);
           StorageDead(_1);
           return;
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff
index 1a4ed5767fe..ea2742a6471 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.GVN.64bit.panic-unwind.diff
@@ -7,17 +7,16 @@
       let mut _2: (i32, bool);
       let mut _4: [i32; 6];
       let _5: usize;
-      let mut _6: usize;
-      let mut _7: bool;
-      let mut _9: u32;
+      let mut _6: bool;
+      let mut _8: u32;
       scope 1 {
           debug x => _1;
           let _3: i32;
           scope 2 {
               debug y => _3;
-              let _8: u32;
+              let _7: u32;
               scope 3 {
-                  debug z => _8;
+                  debug z => _7;
               }
           }
       }
@@ -38,10 +37,9 @@
           _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
           StorageLive(_5);
           _5 = const 3_usize;
-          _6 = const 6_usize;
--         _7 = Lt(copy _5, copy _6);
--         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind continue];
-+         _7 = const true;
+-         _6 = Lt(copy _5, const 6_usize);
+-         assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind continue];
++         _6 = const true;
 +         assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> [success: bb2, unwind continue];
       }
   
@@ -50,13 +48,13 @@
 +         _3 = const 3_i32;
           StorageDead(_5);
           StorageDead(_4);
+          StorageLive(_7);
           StorageLive(_8);
-          StorageLive(_9);
-          _9 = const 42_u32;
--         _8 = copy _9;
-+         _8 = const 42_u32;
-          StorageDead(_9);
+          _8 = const 42_u32;
+-         _7 = copy _8;
++         _7 = const 42_u32;
           StorageDead(_8);
+          StorageDead(_7);
           StorageDead(_3);
           StorageDead(_1);
           return;
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff
index e2420a341e0..f7fe08831b9 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff
@@ -7,19 +7,18 @@
       let mut _2: (i32, bool);
       let mut _4: [i32; 6];
       let _5: usize;
-      let mut _6: usize;
-      let mut _7: bool;
-      let mut _9: Point;
+      let mut _6: bool;
+      let mut _8: Point;
++     let mut _9: u32;
 +     let mut _10: u32;
-+     let mut _11: u32;
       scope 1 {
           debug x => _1;
           let _3: i32;
           scope 2 {
               debug y => _3;
-              let _8: u32;
+              let _7: u32;
               scope 3 {
-                  debug z => _8;
+                  debug z => _7;
               }
           }
       }
@@ -37,31 +36,30 @@
           _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
           StorageLive(_5);
           _5 = const 3_usize;
-          _6 = const 6_usize;
-          _7 = Lt(copy _5, copy _6);
-          assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind unreachable];
+          _6 = Lt(copy _5, const 6_usize);
+          assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind unreachable];
       }
   
       bb2: {
           _3 = copy _4[_5];
           StorageDead(_5);
           StorageDead(_4);
-          StorageLive(_8);
--         StorageLive(_9);
--         _9 = Point { x: const 12_u32, y: const 42_u32 };
--         _8 = copy (_9.1: u32);
--         StorageDead(_9);
+          StorageLive(_7);
+-         StorageLive(_8);
+-         _8 = Point { x: const 12_u32, y: const 42_u32 };
+-         _7 = copy (_8.1: u32);
+-         StorageDead(_8);
++         StorageLive(_9);
 +         StorageLive(_10);
-+         StorageLive(_11);
 +         nop;
-+         _10 = const 12_u32;
-+         _11 = const 42_u32;
++         _9 = const 12_u32;
++         _10 = const 42_u32;
 +         nop;
-+         _8 = copy _11;
++         _7 = copy _10;
++         StorageDead(_9);
 +         StorageDead(_10);
-+         StorageDead(_11);
 +         nop;
-          StorageDead(_8);
+          StorageDead(_7);
           StorageDead(_3);
           StorageDead(_1);
           return;
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff
index a2fb3b979e6..6e36386bea6 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff
@@ -7,19 +7,18 @@
       let mut _2: (i32, bool);
       let mut _4: [i32; 6];
       let _5: usize;
-      let mut _6: usize;
-      let mut _7: bool;
-      let mut _9: Point;
+      let mut _6: bool;
+      let mut _8: Point;
++     let mut _9: u32;
 +     let mut _10: u32;
-+     let mut _11: u32;
       scope 1 {
           debug x => _1;
           let _3: i32;
           scope 2 {
               debug y => _3;
-              let _8: u32;
+              let _7: u32;
               scope 3 {
-                  debug z => _8;
+                  debug z => _7;
               }
           }
       }
@@ -37,31 +36,30 @@
           _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
           StorageLive(_5);
           _5 = const 3_usize;
-          _6 = const 6_usize;
-          _7 = Lt(copy _5, copy _6);
-          assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind continue];
+          _6 = Lt(copy _5, const 6_usize);
+          assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind continue];
       }
   
       bb2: {
           _3 = copy _4[_5];
           StorageDead(_5);
           StorageDead(_4);
-          StorageLive(_8);
--         StorageLive(_9);
--         _9 = Point { x: const 12_u32, y: const 42_u32 };
--         _8 = copy (_9.1: u32);
--         StorageDead(_9);
+          StorageLive(_7);
+-         StorageLive(_8);
+-         _8 = Point { x: const 12_u32, y: const 42_u32 };
+-         _7 = copy (_8.1: u32);
+-         StorageDead(_8);
++         StorageLive(_9);
 +         StorageLive(_10);
-+         StorageLive(_11);
 +         nop;
-+         _10 = const 12_u32;
-+         _11 = const 42_u32;
++         _9 = const 12_u32;
++         _10 = const 42_u32;
 +         nop;
-+         _8 = copy _11;
++         _7 = copy _10;
++         StorageDead(_9);
 +         StorageDead(_10);
-+         StorageDead(_11);
 +         nop;
-          StorageDead(_8);
+          StorageDead(_7);
           StorageDead(_3);
           StorageDead(_1);
           return;
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff
index e2420a341e0..f7fe08831b9 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff
@@ -7,19 +7,18 @@
       let mut _2: (i32, bool);
       let mut _4: [i32; 6];
       let _5: usize;
-      let mut _6: usize;
-      let mut _7: bool;
-      let mut _9: Point;
+      let mut _6: bool;
+      let mut _8: Point;
++     let mut _9: u32;
 +     let mut _10: u32;
-+     let mut _11: u32;
       scope 1 {
           debug x => _1;
           let _3: i32;
           scope 2 {
               debug y => _3;
-              let _8: u32;
+              let _7: u32;
               scope 3 {
-                  debug z => _8;
+                  debug z => _7;
               }
           }
       }
@@ -37,31 +36,30 @@
           _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
           StorageLive(_5);
           _5 = const 3_usize;
-          _6 = const 6_usize;
-          _7 = Lt(copy _5, copy _6);
-          assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind unreachable];
+          _6 = Lt(copy _5, const 6_usize);
+          assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind unreachable];
       }
   
       bb2: {
           _3 = copy _4[_5];
           StorageDead(_5);
           StorageDead(_4);
-          StorageLive(_8);
--         StorageLive(_9);
--         _9 = Point { x: const 12_u32, y: const 42_u32 };
--         _8 = copy (_9.1: u32);
--         StorageDead(_9);
+          StorageLive(_7);
+-         StorageLive(_8);
+-         _8 = Point { x: const 12_u32, y: const 42_u32 };
+-         _7 = copy (_8.1: u32);
+-         StorageDead(_8);
++         StorageLive(_9);
 +         StorageLive(_10);
-+         StorageLive(_11);
 +         nop;
-+         _10 = const 12_u32;
-+         _11 = const 42_u32;
++         _9 = const 12_u32;
++         _10 = const 42_u32;
 +         nop;
-+         _8 = copy _11;
++         _7 = copy _10;
++         StorageDead(_9);
 +         StorageDead(_10);
-+         StorageDead(_11);
 +         nop;
-          StorageDead(_8);
+          StorageDead(_7);
           StorageDead(_3);
           StorageDead(_1);
           return;
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff
index a2fb3b979e6..6e36386bea6 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff
@@ -7,19 +7,18 @@
       let mut _2: (i32, bool);
       let mut _4: [i32; 6];
       let _5: usize;
-      let mut _6: usize;
-      let mut _7: bool;
-      let mut _9: Point;
+      let mut _6: bool;
+      let mut _8: Point;
++     let mut _9: u32;
 +     let mut _10: u32;
-+     let mut _11: u32;
       scope 1 {
           debug x => _1;
           let _3: i32;
           scope 2 {
               debug y => _3;
-              let _8: u32;
+              let _7: u32;
               scope 3 {
-                  debug z => _8;
+                  debug z => _7;
               }
           }
       }
@@ -37,31 +36,30 @@
           _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
           StorageLive(_5);
           _5 = const 3_usize;
-          _6 = const 6_usize;
-          _7 = Lt(copy _5, copy _6);
-          assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _5) -> [success: bb2, unwind continue];
+          _6 = Lt(copy _5, const 6_usize);
+          assert(move _6, "index out of bounds: the length is {} but the index is {}", const 6_usize, copy _5) -> [success: bb2, unwind continue];
       }
   
       bb2: {
           _3 = copy _4[_5];
           StorageDead(_5);
           StorageDead(_4);
-          StorageLive(_8);
--         StorageLive(_9);
--         _9 = Point { x: const 12_u32, y: const 42_u32 };
--         _8 = copy (_9.1: u32);
--         StorageDead(_9);
+          StorageLive(_7);
+-         StorageLive(_8);
+-         _8 = Point { x: const 12_u32, y: const 42_u32 };
+-         _7 = copy (_8.1: u32);
+-         StorageDead(_8);
++         StorageLive(_9);
 +         StorageLive(_10);
-+         StorageLive(_11);
 +         nop;
-+         _10 = const 12_u32;
-+         _11 = const 42_u32;
++         _9 = const 12_u32;
++         _10 = const 42_u32;
 +         nop;
-+         _8 = copy _11;
++         _7 = copy _10;
++         StorageDead(_9);
 +         StorageDead(_10);
-+         StorageDead(_11);
 +         nop;
-          StorageDead(_8);
+          StorageDead(_7);
           StorageDead(_3);
           StorageDead(_1);
           return;
diff --git a/tests/mir-opt/pre-codegen/slice_index.rs b/tests/mir-opt/pre-codegen/slice_index.rs
index 574062d6c35..5dac535d195 100644
--- a/tests/mir-opt/pre-codegen/slice_index.rs
+++ b/tests/mir-opt/pre-codegen/slice_index.rs
@@ -9,7 +9,7 @@ use std::ops::Range;
 // EMIT_MIR slice_index.slice_index_usize.PreCodegen.after.mir
 pub fn slice_index_usize(slice: &[u32], index: usize) -> u32 {
     // CHECK-LABEL: slice_index_usize
-    // CHECK: [[LEN:_[0-9]+]] = Len((*_1))
+    // CHECK: [[LEN:_[0-9]+]] = PtrMetadata(copy _1)
     // CHECK: Lt(copy _2, copy [[LEN]])
     // CHECK-NOT: precondition_check
     // CHECK: _0 = copy (*_1)[_2];
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-abort.mir
index cc1034229fc..81e60b8ec2c 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-abort.mir
@@ -8,7 +8,7 @@ fn slice_index_usize(_1: &[u32], _2: usize) -> u32 {
     let mut _4: bool;
 
     bb0: {
-        _3 = Len((*_1));
+        _3 = PtrMetadata(copy _1);
         _4 = Lt(copy _2, copy _3);
         assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, copy _2) -> [success: bb1, unwind unreachable];
     }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir
index 358226fb529..c0fdc839608 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_usize.PreCodegen.after.panic-unwind.mir
@@ -8,7 +8,7 @@ fn slice_index_usize(_1: &[u32], _2: usize) -> u32 {
     let mut _4: bool;
 
     bb0: {
-        _3 = Len((*_1));
+        _3 = PtrMetadata(copy _1);
         _4 = Lt(copy _2, copy _3);
         assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, copy _2) -> [success: bb1, unwind continue];
     }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
index ecac03ad0f9..151783969dd 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
@@ -7,20 +7,19 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     let mut _3: usize;
     let mut _4: usize;
     let mut _9: std::option::Option<usize>;
-    let mut _11: usize;
-    let mut _12: bool;
-    let mut _14: &impl Fn(usize, &T);
-    let mut _15: (usize, &T);
-    let _16: ();
+    let mut _11: bool;
+    let mut _13: &impl Fn(usize, &T);
+    let mut _14: (usize, &T);
+    let _15: ();
     scope 1 {
         debug ((iter: std::ops::Range<usize>).0: usize) => _4;
         debug ((iter: std::ops::Range<usize>).1: usize) => _3;
         let _10: usize;
         scope 2 {
             debug i => _10;
-            let _13: &T;
+            let _12: &T;
             scope 3 {
-                debug x => _13;
+                debug x => _12;
             }
         }
         scope 5 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) {
@@ -82,23 +81,22 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
         StorageDead(_6);
         StorageDead(_7);
         _10 = copy ((_9 as Some).0: usize);
-        _11 = Len((*_1));
-        _12 = Lt(copy _10, copy _11);
-        assert(move _12, "index out of bounds: the length is {} but the index is {}", move _11, copy _10) -> [success: bb6, unwind unreachable];
+        _11 = Lt(copy _10, copy _3);
+        assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb6, unwind unreachable];
     }
 
     bb6: {
-        _13 = &(*_1)[_10];
+        _12 = &(*_1)[_10];
+        StorageLive(_13);
+        _13 = &_2;
         StorageLive(_14);
-        _14 = &_2;
-        StorageLive(_15);
-        _15 = (copy _10, copy _13);
-        _16 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _14, move _15) -> [return: bb7, unwind unreachable];
+        _14 = (copy _10, copy _12);
+        _15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb7, unwind unreachable];
     }
 
     bb7: {
-        StorageDead(_15);
         StorageDead(_14);
+        StorageDead(_13);
         StorageDead(_9);
         goto -> bb1;
     }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
index 1032473b9b2..006329dc20d 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
@@ -7,20 +7,19 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     let mut _3: usize;
     let mut _4: usize;
     let mut _9: std::option::Option<usize>;
-    let mut _11: usize;
-    let mut _12: bool;
-    let mut _14: &impl Fn(usize, &T);
-    let mut _15: (usize, &T);
-    let _16: ();
+    let mut _11: bool;
+    let mut _13: &impl Fn(usize, &T);
+    let mut _14: (usize, &T);
+    let _15: ();
     scope 1 {
         debug ((iter: std::ops::Range<usize>).0: usize) => _4;
         debug ((iter: std::ops::Range<usize>).1: usize) => _3;
         let _10: usize;
         scope 2 {
             debug i => _10;
-            let _13: &T;
+            let _12: &T;
             scope 3 {
-                debug x => _13;
+                debug x => _12;
             }
         }
         scope 5 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) {
@@ -82,23 +81,22 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
         StorageDead(_6);
         StorageDead(_7);
         _10 = copy ((_9 as Some).0: usize);
-        _11 = Len((*_1));
-        _12 = Lt(copy _10, copy _11);
-        assert(move _12, "index out of bounds: the length is {} but the index is {}", move _11, copy _10) -> [success: bb6, unwind: bb8];
+        _11 = Lt(copy _10, copy _3);
+        assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb6, unwind: bb8];
     }
 
     bb6: {
-        _13 = &(*_1)[_10];
+        _12 = &(*_1)[_10];
+        StorageLive(_13);
+        _13 = &_2;
         StorageLive(_14);
-        _14 = &_2;
-        StorageLive(_15);
-        _15 = (copy _10, copy _13);
-        _16 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _14, move _15) -> [return: bb7, unwind: bb8];
+        _14 = (copy _10, copy _12);
+        _15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb7, unwind: bb8];
     }
 
     bb7: {
-        StorageDead(_15);
         StorageDead(_14);
+        StorageDead(_13);
         StorageDead(_9);
         goto -> bb1;
     }
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
index 2efbb6d9904..3f0d60b46f4 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
@@ -7,48 +7,36 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         debug self => _1;
         scope 2 (inlined Vec::<u8>::as_slice) {
             debug self => _1;
-            let mut _9: *const u8;
-            let mut _10: usize;
+            let mut _7: *const u8;
+            let mut _8: usize;
             scope 3 (inlined Vec::<u8>::as_ptr) {
                 debug self => _1;
-                let mut _2: &alloc::raw_vec::RawVec<u8>;
-                let mut _8: *mut u8;
+                let mut _6: *mut u8;
                 scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
-                    debug self => _2;
-                    let mut _3: &alloc::raw_vec::RawVecInner;
                     scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
-                        debug self => _3;
-                        let mut _7: std::ptr::NonNull<u8>;
+                        let mut _5: std::ptr::NonNull<u8>;
                         scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
-                            debug self => _3;
-                            let mut _4: std::ptr::NonNull<u8>;
+                            let mut _2: std::ptr::NonNull<u8>;
                             scope 7 (inlined Unique::<u8>::cast::<u8>) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
-                                debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                                 scope 8 (inlined NonNull::<u8>::cast::<u8>) {
-                                    debug self => _4;
-                                    let mut _5: *mut u8;
-                                    let mut _6: *const u8;
+                                    let mut _3: *mut u8;
+                                    let mut _4: *const u8;
                                     scope 9 (inlined NonNull::<u8>::as_ptr) {
-                                        debug self => _4;
                                     }
                                 }
                             }
                             scope 10 (inlined Unique::<u8>::as_non_null_ptr) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _7;
-                                debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                             }
                         }
                         scope 11 (inlined NonNull::<u8>::as_ptr) {
-                            debug self => _7;
                         }
                     }
                 }
             }
             scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
-                debug data => _9;
-                debug len => _10;
-                let _11: *const [u8];
+                debug data => _7;
+                debug len => _8;
+                let _9: *const [u8];
                 scope 13 (inlined core::ub_checks::check_language_ub) {
                     scope 14 (inlined core::ub_checks::check_language_ub::runtime) {
                     }
@@ -58,11 +46,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                 scope 16 (inlined align_of::<u8>) {
                 }
                 scope 17 (inlined slice_from_raw_parts::<u8>) {
-                    debug data => _9;
-                    debug len => _10;
+                    debug data => _7;
+                    debug len => _8;
                     scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
-                        debug data_pointer => _9;
-                        debug metadata => _10;
+                        debug data_pointer => _7;
                     }
                 }
             }
@@ -70,37 +57,31 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
     }
 
     bb0: {
-        StorageLive(_8);
-        StorageLive(_9);
+        StorageLive(_6);
+        StorageLive(_7);
+        StorageLive(_5);
         StorageLive(_2);
-        _2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
+        _2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
         StorageLive(_3);
-        _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
-        StorageLive(_7);
         StorageLive(_4);
-        _4 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
-        StorageLive(_5);
-        StorageLive(_6);
-        _5 = copy _4 as *mut u8 (Transmute);
-        _6 = copy _5 as *const u8 (PtrToPtr);
-        _7 = NonNull::<u8> { pointer: move _6 };
-        StorageDead(_6);
-        StorageDead(_5);
+        _3 = copy _2 as *mut u8 (Transmute);
+        _4 = copy _3 as *const u8 (PtrToPtr);
+        _5 = NonNull::<u8> { pointer: move _4 };
         StorageDead(_4);
-        _8 = copy _7 as *mut u8 (Transmute);
-        StorageDead(_7);
         StorageDead(_3);
-        _9 = copy _8 as *const u8 (PtrToPtr);
         StorageDead(_2);
-        StorageLive(_10);
-        _10 = copy ((*_1).1: usize);
-        StorageLive(_11);
-        _11 = *const [u8] from (copy _9, copy _10);
-        _0 = &(*_11);
-        StorageDead(_11);
-        StorageDead(_10);
+        _6 = copy _5 as *mut u8 (Transmute);
+        StorageDead(_5);
+        _7 = copy _6 as *const u8 (PtrToPtr);
+        StorageLive(_8);
+        _8 = copy ((*_1).1: usize);
+        StorageLive(_9);
+        _9 = *const [u8] from (copy _7, copy _8);
+        _0 = &(*_9);
         StorageDead(_9);
         StorageDead(_8);
+        StorageDead(_7);
+        StorageDead(_6);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
index 2efbb6d9904..3f0d60b46f4 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
@@ -7,48 +7,36 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         debug self => _1;
         scope 2 (inlined Vec::<u8>::as_slice) {
             debug self => _1;
-            let mut _9: *const u8;
-            let mut _10: usize;
+            let mut _7: *const u8;
+            let mut _8: usize;
             scope 3 (inlined Vec::<u8>::as_ptr) {
                 debug self => _1;
-                let mut _2: &alloc::raw_vec::RawVec<u8>;
-                let mut _8: *mut u8;
+                let mut _6: *mut u8;
                 scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
-                    debug self => _2;
-                    let mut _3: &alloc::raw_vec::RawVecInner;
                     scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
-                        debug self => _3;
-                        let mut _7: std::ptr::NonNull<u8>;
+                        let mut _5: std::ptr::NonNull<u8>;
                         scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
-                            debug self => _3;
-                            let mut _4: std::ptr::NonNull<u8>;
+                            let mut _2: std::ptr::NonNull<u8>;
                             scope 7 (inlined Unique::<u8>::cast::<u8>) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
-                                debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                                 scope 8 (inlined NonNull::<u8>::cast::<u8>) {
-                                    debug self => _4;
-                                    let mut _5: *mut u8;
-                                    let mut _6: *const u8;
+                                    let mut _3: *mut u8;
+                                    let mut _4: *const u8;
                                     scope 9 (inlined NonNull::<u8>::as_ptr) {
-                                        debug self => _4;
                                     }
                                 }
                             }
                             scope 10 (inlined Unique::<u8>::as_non_null_ptr) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _7;
-                                debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                             }
                         }
                         scope 11 (inlined NonNull::<u8>::as_ptr) {
-                            debug self => _7;
                         }
                     }
                 }
             }
             scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
-                debug data => _9;
-                debug len => _10;
-                let _11: *const [u8];
+                debug data => _7;
+                debug len => _8;
+                let _9: *const [u8];
                 scope 13 (inlined core::ub_checks::check_language_ub) {
                     scope 14 (inlined core::ub_checks::check_language_ub::runtime) {
                     }
@@ -58,11 +46,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                 scope 16 (inlined align_of::<u8>) {
                 }
                 scope 17 (inlined slice_from_raw_parts::<u8>) {
-                    debug data => _9;
-                    debug len => _10;
+                    debug data => _7;
+                    debug len => _8;
                     scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
-                        debug data_pointer => _9;
-                        debug metadata => _10;
+                        debug data_pointer => _7;
                     }
                 }
             }
@@ -70,37 +57,31 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
     }
 
     bb0: {
-        StorageLive(_8);
-        StorageLive(_9);
+        StorageLive(_6);
+        StorageLive(_7);
+        StorageLive(_5);
         StorageLive(_2);
-        _2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
+        _2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
         StorageLive(_3);
-        _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
-        StorageLive(_7);
         StorageLive(_4);
-        _4 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
-        StorageLive(_5);
-        StorageLive(_6);
-        _5 = copy _4 as *mut u8 (Transmute);
-        _6 = copy _5 as *const u8 (PtrToPtr);
-        _7 = NonNull::<u8> { pointer: move _6 };
-        StorageDead(_6);
-        StorageDead(_5);
+        _3 = copy _2 as *mut u8 (Transmute);
+        _4 = copy _3 as *const u8 (PtrToPtr);
+        _5 = NonNull::<u8> { pointer: move _4 };
         StorageDead(_4);
-        _8 = copy _7 as *mut u8 (Transmute);
-        StorageDead(_7);
         StorageDead(_3);
-        _9 = copy _8 as *const u8 (PtrToPtr);
         StorageDead(_2);
-        StorageLive(_10);
-        _10 = copy ((*_1).1: usize);
-        StorageLive(_11);
-        _11 = *const [u8] from (copy _9, copy _10);
-        _0 = &(*_11);
-        StorageDead(_11);
-        StorageDead(_10);
+        _6 = copy _5 as *mut u8 (Transmute);
+        StorageDead(_5);
+        _7 = copy _6 as *const u8 (PtrToPtr);
+        StorageLive(_8);
+        _8 = copy ((*_1).1: usize);
+        StorageLive(_9);
+        _9 = *const [u8] from (copy _7, copy _8);
+        _0 = &(*_9);
         StorageDead(_9);
         StorageDead(_8);
+        StorageDead(_7);
+        StorageDead(_6);
         return;
     }
 }
diff --git a/tests/mir-opt/strip_debuginfo.rs b/tests/mir-opt/strip_debuginfo.rs
new file mode 100644
index 00000000000..310609e1e9d
--- /dev/null
+++ b/tests/mir-opt/strip_debuginfo.rs
@@ -0,0 +1,39 @@
+//@ revisions: NONE TINY ALL
+//@[NONE] compile-flags: -Zmir_strip_debuginfo=none
+//@[TINY] compile-flags: -Zmir_strip_debuginfo=locals-in-tiny-functions
+//@[ALL] compile-flags: -Zmir_strip_debuginfo=all-locals
+
+// CHECK: fn tiny_function
+fn tiny_function(end: u32) -> u32 {
+    // CHECK: debug end => _1;
+    // NONE: debug a =>
+    // NONE: debug b =>
+    // TINY-NOT: debug a =>
+    // TINY-NOT: debug b =>
+    // ALL-NOT: debug a =>
+    // ALL-NOT: debug b =>
+    let a = !end;
+    let b = a ^ 1;
+    b
+}
+
+#[inline(never)]
+fn opaque(_: u32) {}
+
+// CHECK: fn looping_function
+fn looping_function(end: u32) {
+    // CHECK: debug end => _1;
+    // NONE: debug i =>
+    // NONE: debug x =>
+    // TINY: debug i =>
+    // TINY: debug x =>
+    // ALL-NOT: debug i =>
+    // ALL-NOT: debug x =>
+    let mut i = 0;
+    while i < end {
+        let x = i ^ 1;
+        opaque(x);
+    }
+}
+
+fn main() {}
diff --git a/tests/run-make/musl-default-linking/rmake.rs b/tests/run-make/musl-default-linking/rmake.rs
new file mode 100644
index 00000000000..b6d428d3f27
--- /dev/null
+++ b/tests/run-make/musl-default-linking/rmake.rs
@@ -0,0 +1,62 @@
+use run_make_support::{rustc, serde_json};
+
+// Please do NOT add more targets to this list!
+// Per https://github.com/rust-lang/compiler-team/issues/422,
+// we should be trying to move these targets to dynamically link
+// musl libc by default.
+static LEGACY_STATIC_LINKING_TARGETS: &[&'static str] = &[
+    "aarch64-unknown-linux-musl",
+    "arm-unknown-linux-musleabi",
+    "arm-unknown-linux-musleabihf",
+    "armv5te-unknown-linux-musleabi",
+    "armv7-unknown-linux-musleabi",
+    "armv7-unknown-linux-musleabihf",
+    "i586-unknown-linux-musl",
+    "i686-unknown-linux-musl",
+    "mips64-unknown-linux-musl",
+    "mips64-unknown-linux-muslabi64",
+    "mips64el-unknown-linux-muslabi64",
+    "powerpc-unknown-linux-musl",
+    "powerpc-unknown-linux-muslspe",
+    "powerpc64-unknown-linux-musl",
+    "powerpc64le-unknown-linux-musl",
+    "riscv32gc-unknown-linux-musl",
+    "s390x-unknown-linux-musl",
+    "thumbv7neon-unknown-linux-musleabihf",
+    "x86_64-unknown-linux-musl",
+];
+
+fn main() {
+    let targets = rustc().print("target-list").run().stdout_utf8();
+
+    for target in targets.lines() {
+        let abi = target.split('-').last().unwrap();
+
+        if !abi.starts_with("musl") {
+            continue;
+        }
+
+        let target_spec_json = rustc()
+            .print("target-spec-json")
+            .target(target)
+            .arg("-Zunstable-options")
+            .run()
+            .stdout_utf8();
+
+        let target_spec: serde_json::Value =
+            serde_json::from_str(&target_spec_json).expect("failed to parse target-spec-json");
+        let default = &target_spec["crt-static-default"];
+
+        // If the value is `null`, then the default to dynamically link from
+        // musl_base was not overriden.
+        if default.is_null() {
+            continue;
+        }
+
+        if default.as_bool().expect("wasn't a boolean")
+            && !LEGACY_STATIC_LINKING_TARGETS.contains(&target)
+        {
+            panic!("{target} statically links musl libc when it should dynamically link it");
+        }
+    }
+}
diff --git a/tests/rustdoc-js-std/osstring-to-string.js b/tests/rustdoc-js-std/osstring-to-string.js
index 3fdc0b9f24a..17bb602a502 100644
--- a/tests/rustdoc-js-std/osstring-to-string.js
+++ b/tests/rustdoc-js-std/osstring-to-string.js
@@ -4,6 +4,6 @@
 const EXPECTED = {
     'query': 'OsString -> String',
     'others': [
-        { 'path': 'std::ffi::os_str::OsString', 'name': 'into_string' },
+        { 'path': 'std::ffi::OsString', 'name': 'into_string' },
     ]
 };
diff --git a/tests/rustdoc-js/reexport.js b/tests/rustdoc-js/reexport.js
index 9021cc2e90f..0b9415dd3e4 100644
--- a/tests/rustdoc-js/reexport.js
+++ b/tests/rustdoc-js/reexport.js
@@ -14,4 +14,13 @@ const EXPECTED = [
             { 'path': 'reexport', 'name': 'AnotherOne' },
         ],
     },
+    {
+        'query': 'fn:Equivalent::equivalent',
+        'others': [
+            // These results must never contain `reexport::equivalent::NotEquivalent`,
+            // since that path does not exist.
+            { 'path': 'equivalent::Equivalent', 'name': 'equivalent' },
+            { 'path': 'reexport::NotEquivalent', 'name': 'equivalent' },
+        ],
+    },
 ];
diff --git a/tests/rustdoc-js/reexport.rs b/tests/rustdoc-js/reexport.rs
index 0b3718cd9a3..ecbbeca5ea8 100644
--- a/tests/rustdoc-js/reexport.rs
+++ b/tests/rustdoc-js/reexport.rs
@@ -2,6 +2,15 @@
 // This is a DWIM case, since renaming the export probably means the intent is also different.
 // For the de-duplication case of exactly the same name, see reexport-dedup
 
+//@ aux-crate:equivalent=equivalent.rs
+//@ compile-flags: --extern equivalent
+//@ aux-build:equivalent.rs
+//@ build-aux-docs
+#[doc(inline)]
+pub extern crate equivalent;
+#[doc(inline)]
+pub use equivalent::Equivalent as NotEquivalent;
+
 pub mod fmt {
     pub struct Subscriber;
 }
diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr
index fc47404734e..385b2ccacc1 100644
--- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr
+++ b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr
@@ -4,7 +4,6 @@ error: unclosed quote string `"`
 LL | / /// ```{class="}
 LL | | /// main;
 LL | | /// ```
-LL | |
 ...  |
 LL | | /// main;
 LL | | /// ```
@@ -23,7 +22,6 @@ error: unclosed quote string `"`
 LL | / /// ```{class="}
 LL | | /// main;
 LL | | /// ```
-LL | |
 ...  |
 LL | | /// main;
 LL | | /// ```
diff --git a/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr b/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr
index 06a1cf6b118..f9080bf0785 100644
--- a/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr
+++ b/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr
@@ -308,19 +308,12 @@ LL |    pub trait SVec: Index<
    | |            |
    | |            this trait cannot be made into an object...
 LL | |      <Self as SVec>::Item,
-LL | |
-LL | |
 ...  |
 LL | |/     Output = <Index<<Self as SVec>::Item,
-LL | ||
-LL | ||
-LL | ||
 ...  ||
-LL | ||
 LL | ||     Output = <Self as SVec>::Item> as SVec>::Item,
    | ||_________________________________________________^ ...because it uses `Self` as a type parameter
 ...  |
-LL | |
 LL | |  > {
    | |__^ ...because it uses `Self` as a type parameter
 help: consider using an opaque type instead
diff --git a/tests/rustdoc-ui/lints/check-attr.stderr b/tests/rustdoc-ui/lints/check-attr.stderr
index e23806e0bab..3366c021727 100644
--- a/tests/rustdoc-ui/lints/check-attr.stderr
+++ b/tests/rustdoc-ui/lints/check-attr.stderr
@@ -2,9 +2,6 @@ error: unknown attribute `compile-fail`
   --> $DIR/check-attr.rs:3:1
    |
 LL | / /// foo
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | /// boo
 LL | | /// ```
@@ -22,9 +19,6 @@ error: unknown attribute `compilefail`
   --> $DIR/check-attr.rs:3:1
    |
 LL | / /// foo
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | /// boo
 LL | | /// ```
@@ -37,9 +31,6 @@ error: unknown attribute `comPile_fail`
   --> $DIR/check-attr.rs:3:1
    |
 LL | / /// foo
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | /// boo
 LL | | /// ```
@@ -52,9 +43,6 @@ error: unknown attribute `should-panic`
   --> $DIR/check-attr.rs:13:1
    |
 LL | / /// bar
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | /// boo
 LL | | /// ```
@@ -67,9 +55,6 @@ error: unknown attribute `shouldpanic`
   --> $DIR/check-attr.rs:13:1
    |
 LL | / /// bar
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | /// boo
 LL | | /// ```
@@ -82,9 +67,6 @@ error: unknown attribute `sHould_panic`
   --> $DIR/check-attr.rs:13:1
    |
 LL | / /// bar
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | /// boo
 LL | | /// ```
@@ -97,9 +79,6 @@ error: unknown attribute `no-run`
   --> $DIR/check-attr.rs:23:1
    |
 LL | / /// foobar
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | /// boo
 LL | | /// ```
@@ -112,9 +91,6 @@ error: unknown attribute `norun`
   --> $DIR/check-attr.rs:23:1
    |
 LL | / /// foobar
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | /// boo
 LL | | /// ```
@@ -127,9 +103,6 @@ error: unknown attribute `no_Run`
   --> $DIR/check-attr.rs:23:1
    |
 LL | / /// foobar
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | /// boo
 LL | | /// ```
@@ -142,9 +115,6 @@ error: unknown attribute `test-harness`
   --> $DIR/check-attr.rs:33:1
    |
 LL | / /// b
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | /// boo
 LL | | /// ```
@@ -157,9 +127,6 @@ error: unknown attribute `testharness`
   --> $DIR/check-attr.rs:33:1
    |
 LL | / /// b
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | /// boo
 LL | | /// ```
@@ -172,9 +139,6 @@ error: unknown attribute `teSt_harness`
   --> $DIR/check-attr.rs:33:1
    |
 LL | / /// b
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | /// boo
 LL | | /// ```
diff --git a/tests/rustdoc-ui/lints/check.stderr b/tests/rustdoc-ui/lints/check.stderr
index f1f36e8830d..dcdf25dda64 100644
--- a/tests/rustdoc-ui/lints/check.stderr
+++ b/tests/rustdoc-ui/lints/check.stderr
@@ -6,7 +6,6 @@ LL | |
 LL | |
 LL | | #![warn(missing_docs)]
 ...  |
-LL | |
 LL | | pub fn foo() {}
    | |_______________^
    |
diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr
index 1e2b3528d4a..d93aaf5f3ca 100644
--- a/tests/rustdoc-ui/unescaped_backticks.stderr
+++ b/tests/rustdoc-ui/unescaped_backticks.stderr
@@ -271,9 +271,6 @@ error: unescaped backtick
   --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
-LL | |
-LL | |
-LL | |
 ...  |
 LL | |     /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
 LL | |     /// level changes.
@@ -290,9 +287,6 @@ error: unescaped backtick
   --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
-LL | |
-LL | |
-LL | |
 ...  |
 LL | |     /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
 LL | |     /// level changes.
@@ -307,9 +301,6 @@ error: unescaped backtick
   --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
-LL | |
-LL | |
-LL | |
 ...  |
 LL | |     /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
 LL | |     /// level changes.
@@ -326,9 +317,6 @@ error: unescaped backtick
   --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
-LL | |
-LL | |
-LL | |
 ...  |
 LL | |     /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
 LL | |     /// level changes.
diff --git a/tests/ui/alias-uninit-value.rs b/tests/ui/alias-uninit-value.rs
deleted file mode 100644
index 0084a98e627..00000000000
--- a/tests/ui/alias-uninit-value.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-//@ run-pass
-
-#![allow(non_camel_case_types)]
-#![allow(dead_code)]
-
-
-
-// Regression test for issue #374
-
-
-enum sty { ty_nil, }
-
-struct RawT {struct_: sty, cname: Option<String>, hash: usize}
-
-fn mk_raw_ty(st: sty, cname: Option<String>) -> RawT {
-    return RawT {struct_: st, cname: cname, hash: 0};
-}
-
-pub fn main() { mk_raw_ty(sty::ty_nil, None::<String>); }
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
index de92841d7f1..80ff10e13d8 100644
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
+++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
@@ -7,8 +7,7 @@ LL | // fn oom(
 LL | ||     info: &Layout,
 LL | || ) -> ()
    | ||_______- arguments to this function are incorrect
-LL | |  {
-LL | |      loop {}
+...  |
 LL | |  }
    | |__^ expected `&Layout`, found `Layout`
    |
@@ -30,8 +29,7 @@ LL | // fn oom(
 LL | ||     info: &Layout,
 LL | || ) -> ()
    | ||_______^ expected `!`, found `()`
-LL | |  {
-LL | |      loop {}
+...  |
 LL | |  }
    | |__- expected `!` because of return type
    |
diff --git a/tests/ui/allow-non-lint-warnings.rs b/tests/ui/allow-non-lint-warnings.rs
deleted file mode 100644
index f8f5a78ebff..00000000000
--- a/tests/ui/allow-non-lint-warnings.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ compile-flags: -Awarnings
-//@ check-pass
-
-#[derive()]
-#[derive(Copy, Clone)]
-pub struct Foo;
-
-pub fn main() {}
diff --git a/tests/ui/artificial-block.rs b/tests/ui/artificial-block.rs
deleted file mode 100644
index 037163b4174..00000000000
--- a/tests/ui/artificial-block.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-//@ run-pass
-
-fn f() -> isize { { return 3; } }
-
-pub fn main() { assert_eq!(f(), 3); }
diff --git a/tests/ui/as-precedence.rs b/tests/ui/as-precedence.rs
deleted file mode 100644
index 5021a3b677f..00000000000
--- a/tests/ui/as-precedence.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ run-pass
-
-#[allow(unused_parens)]
-fn main() {
-    assert_eq!(3 as usize * 3, 9);
-    assert_eq!(3 as (usize) * 3, 9);
-    assert_eq!(3 as (usize) / 3, 1);
-    assert_eq!(3 as usize + 3, 6);
-    assert_eq!(3 as (usize) + 3, 6);
-}
diff --git a/tests/ui/associated-types/associated-types-eq-2.stderr b/tests/ui/associated-types/associated-types-eq-2.stderr
index e5013a35d45..ccd13123d70 100644
--- a/tests/ui/associated-types/associated-types-eq-2.stderr
+++ b/tests/ui/associated-types/associated-types-eq-2.stderr
@@ -3,8 +3,7 @@ error[E0658]: associated const equality is incomplete
    |
 LL |   impl Tr3<N
    |  __________^
-LL | |
-LL | |
+...  |
 LL | | = 42, T2 = Qux, T3 = usize> for Bar {
    | |____^
    |
@@ -198,8 +197,7 @@ error[E0229]: associated item constraints are not allowed here
    |
 LL |   impl Tr3<N
    |  __________^
-LL | |
-LL | |
+...  |
 LL | | = 42, T2 = Qux, T3 = usize> for Bar {
    | |____^ associated item constraint not allowed here
    |
diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr
index ec2890cc8e7..805c3e60bb6 100644
--- a/tests/ui/associated-types/issue-59324.stderr
+++ b/tests/ui/associated-types/issue-59324.stderr
@@ -2,8 +2,7 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied
   --> $DIR/issue-59324.rs:11:1
    |
 LL | / pub trait ThriftService<Bug: NotFoo>:
-LL | |
-LL | |
+...  |
 LL | |     Service<AssocType = <Bug as Foo>::OnlyFoo>
    | |______________________________________________^ the trait `Foo` is not implemented for `Bug`
    |
@@ -20,7 +19,6 @@ LL | |
 LL | |
 LL | |     Service<AssocType = <Bug as Foo>::OnlyFoo>
 ...  |
-LL | |
 LL | | }
    | |_^ the trait `Foo` is not implemented for `Bug`
    |
diff --git a/tests/ui/associated-types/missing-associated-types.stderr b/tests/ui/associated-types/missing-associated-types.stderr
index ce4b57e8af8..3a56c55896e 100644
--- a/tests/ui/associated-types/missing-associated-types.stderr
+++ b/tests/ui/associated-types/missing-associated-types.stderr
@@ -42,11 +42,11 @@ LL | type Bat<Rhs> = dyn Add<Rhs> + Sub<Rhs> + Fine<Rhs>;
    = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add<Rhs> + Sub<Rhs> + Fine<Rhs> {}`
    = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
-error[E0191]: the value of the associated types `Output` in `Div`, `Output` in `Mul` must be specified
+error[E0191]: the value of the associated types `Output` in `Div<Rhs>`, `Output` in `Mul<Rhs>` must be specified
   --> $DIR/missing-associated-types.rs:20:21
    |
 LL | type Bal<Rhs> = dyn X<Rhs>;
-   |                     ^^^^^^ associated types `Output` (from trait `Div`), `Output` (from trait `Mul`) must be specified
+   |                     ^^^^^^ associated types `Output` (from trait `Div<Rhs>`), `Output` (from trait `Mul<Rhs>`) must be specified
    |
    = help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types
 
diff --git a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
index 3bc467cc84d..4ed15a942c6 100644
--- a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
+++ b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
@@ -23,7 +23,6 @@ LL | |
 LL | |     let block = async {
 LL | |         return 0u8;
 ...  |
-LL | |
 LL | | }
    | |_^ expected `u8`, found `()`
 
diff --git a/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr b/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr
index 649a868faa5..b60f6a08338 100644
--- a/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr
+++ b/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr
@@ -31,7 +31,6 @@ LL | |
 LL | |         if true {
 LL | |             false
 ...  |
-LL | |
 LL | |     })
    | |_____^ expected `bool`, found `Option<()>`
    |
diff --git a/tests/ui/async-await/inference_var_self_argument.stderr b/tests/ui/async-await/inference_var_self_argument.stderr
index a33c5f7b07d..7b7b3dbc757 100644
--- a/tests/ui/async-await/inference_var_self_argument.stderr
+++ b/tests/ui/async-await/inference_var_self_argument.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `&dyn Foo`
 LL |     async fn foo(self: &dyn Foo) {
    |                        ^^^^^^^^
    |
-   = note: type of `self` must be `Self` or some type implementing `Receiver`
-   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/inference_var_self_argument.rs:5:5
diff --git a/tests/ui/async-await/issue-66312.stderr b/tests/ui/async-await/issue-66312.stderr
index f4db949a5f4..c95ae1147df 100644
--- a/tests/ui/async-await/issue-66312.stderr
+++ b/tests/ui/async-await/issue-66312.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `T`
 LL |     fn is_some(self: T);
    |                      ^
    |
-   = note: type of `self` must be `Self` or some type implementing `Receiver`
-   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error[E0308]: mismatched types
   --> $DIR/issue-66312.rs:9:8
diff --git a/tests/ui/async-await/issue-84841.stderr b/tests/ui/async-await/issue-84841.stderr
index 1e22373ba6e..69c1c882d60 100644
--- a/tests/ui/async-await/issue-84841.stderr
+++ b/tests/ui/async-await/issue-84841.stderr
@@ -14,8 +14,7 @@ LL |   async fn foo() {
 LL | |     // Adding an .await here avoids the ICE
 LL | |     test()?;
    | |           ^ cannot use the `?` operator in an async function that returns `()`
-LL | |
-LL | |
+...  |
 LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
diff --git a/tests/ui/async-await/issues/issue-72312.stderr b/tests/ui/async-await/issues/issue-72312.stderr
index cd93f8a3c55..8e6fb138a1f 100644
--- a/tests/ui/async-await/issues/issue-72312.stderr
+++ b/tests/ui/async-await/issues/issue-72312.stderr
@@ -8,10 +8,7 @@ LL |       pub async fn start(&self) {
    |                          let's call the lifetime of this reference `'1`
 ...
 LL | /         require_static(async move {
-LL | |
-LL | |
-LL | |
-LL | |             &self;
+...  |
 LL | |         });
    | |          ^
    | |          |
diff --git a/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr b/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr
index 8344b7a07dc..6887a904211 100644
--- a/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr
+++ b/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr
@@ -66,8 +66,7 @@ LL |   fn foo3() {
 LL | /     async {
 LL | |
 LL | |         let _ = #[track_caller] || {
-LL | |
-LL | |         };
+...  |
 LL | |     }
    | |_____^ expected `()`, found `async` block
    |
diff --git a/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr b/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr
index 8344b7a07dc..6887a904211 100644
--- a/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr
+++ b/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr
@@ -66,8 +66,7 @@ LL |   fn foo3() {
 LL | /     async {
 LL | |
 LL | |         let _ = #[track_caller] || {
-LL | |
-LL | |         };
+...  |
 LL | |     }
    | |_____^ expected `()`, found `async` block
    |
diff --git a/tests/ui/attributes/collapse-debuginfo-invalid.stderr b/tests/ui/attributes/collapse-debuginfo-invalid.stderr
index 7cbbd1d647e..70376f985cb 100644
--- a/tests/ui/attributes/collapse-debuginfo-invalid.stderr
+++ b/tests/ui/attributes/collapse-debuginfo-invalid.stderr
@@ -45,7 +45,6 @@ LL | |     let _ = #[collapse_debuginfo(yes)] || { };
 LL | |
 LL | |     #[collapse_debuginfo(yes)]
 ...  |
-LL | |     }
 LL | | }
    | |_- not a macro definition
 
diff --git a/tests/ui/attributes/dump_def_parents.stderr b/tests/ui/attributes/dump_def_parents.stderr
index a928e8e33a4..74ecd9b0a89 100644
--- a/tests/ui/attributes/dump_def_parents.stderr
+++ b/tests/ui/attributes/dump_def_parents.stderr
@@ -22,7 +22,6 @@ LL | |
 LL | | fn bar() {
 LL | |     fn foo() {
 ...  |
-LL | |
 LL | | fn main() {}
    | |____________^
 
@@ -66,7 +65,6 @@ LL | |
 LL | | fn bar() {
 LL | |     fn foo() {
 ...  |
-LL | |
 LL | | fn main() {}
    | |____________^
 
@@ -124,7 +122,6 @@ LL | |
 LL | | fn bar() {
 LL | |     fn foo() {
 ...  |
-LL | |
 LL | | fn main() {}
    | |____________^
 
@@ -173,7 +170,6 @@ LL | |
 LL | | fn bar() {
 LL | |     fn foo() {
 ...  |
-LL | |
 LL | | fn main() {}
    | |____________^
 
diff --git a/tests/ui/borrowck/borrowck-describe-lvalue.rs b/tests/ui/borrowck/borrowck-describe-lvalue.rs
index cdcff69d6e5..f3a4b382fa8 100644
--- a/tests/ui/borrowck/borrowck-describe-lvalue.rs
+++ b/tests/ui/borrowck/borrowck-describe-lvalue.rs
@@ -231,7 +231,6 @@ fn main() {
         let x = &mut v;
         v[0].y;
         //~^ ERROR cannot use `v[_].y` because it was mutably borrowed
-        //~| ERROR cannot use `*v` because it was mutably borrowed
         drop(x);
     }
     // Field of constant index
diff --git a/tests/ui/borrowck/borrowck-describe-lvalue.stderr b/tests/ui/borrowck/borrowck-describe-lvalue.stderr
index 11f2e42d42b..666a21808d8 100644
--- a/tests/ui/borrowck/borrowck-describe-lvalue.stderr
+++ b/tests/ui/borrowck/borrowck-describe-lvalue.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/borrowck-describe-lvalue.rs:254:13
+  --> $DIR/borrowck-describe-lvalue.rs:253:13
    |
 LL |             let y = &mut x;
    |                     ------ first mutable borrow occurs here
@@ -9,7 +9,7 @@ LL |             *y = 1;
    |             ------ first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/borrowck-describe-lvalue.rs:264:20
+  --> $DIR/borrowck-describe-lvalue.rs:263:20
    |
 LL |                    let y = &mut x;
    |                            ------ first mutable borrow occurs here
@@ -19,7 +19,7 @@ LL |                    *y = 1;
    |                    ------ first borrow later used here
 
 error: captured variable cannot escape `FnMut` closure body
-  --> $DIR/borrowck-describe-lvalue.rs:262:16
+  --> $DIR/borrowck-describe-lvalue.rs:261:16
    |
 LL |           let mut x = 0;
    |               ----- variable defined here
@@ -300,17 +300,6 @@ LL |             S  { x: F { y: ref x0, .. }, .. } =>
 LL |         drop(x);
    |              - mutable borrow later used here
 
-error[E0503]: cannot use `*v` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:232:9
-   |
-LL |         let x = &mut v;
-   |                 ------ `v` is borrowed here
-LL |         v[0].y;
-   |         ^^^^ use of borrowed `v`
-...
-LL |         drop(x);
-   |              - borrow later used here
-
 error[E0503]: cannot use `v[_].y` because it was mutably borrowed
   --> $DIR/borrowck-describe-lvalue.rs:232:9
    |
@@ -318,12 +307,12 @@ LL |         let x = &mut v;
    |                 ------ `v` is borrowed here
 LL |         v[0].y;
    |         ^^^^^^ use of borrowed `v`
-...
+LL |
 LL |         drop(x);
    |              - borrow later used here
 
 error[E0502]: cannot borrow `v[..].x` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:243:24
+  --> $DIR/borrowck-describe-lvalue.rs:242:24
    |
 LL |         let x = &mut v;
    |                 ------ mutable borrow occurs here
@@ -357,7 +346,7 @@ LL |             drop(x);
    |                  - mutable borrow later used here
 
 error[E0382]: use of moved value: `x`
-  --> $DIR/borrowck-describe-lvalue.rs:274:22
+  --> $DIR/borrowck-describe-lvalue.rs:273:22
    |
 LL |                 drop(x);
    |                      - value moved here
@@ -366,7 +355,7 @@ LL |                 drop(x);
    |
    = note: move occurs because `x` has type `Vec<i32>`, which does not implement the `Copy` trait
 
-error: aborting due to 32 previous errors
+error: aborting due to 31 previous errors
 
 Some errors have detailed explanations: E0382, E0499, E0502, E0503.
 For more information about an error, try `rustc --explain E0382`.
diff --git a/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr b/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr
index a66281a188d..aa4e5fb2f69 100644
--- a/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr
+++ b/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr
@@ -40,8 +40,6 @@ LL |       v.call(|(), this: &mut S| {
    |       | |
    |  _____| first borrow later used by call
    | |
-LL | |
-LL | |
 ...  |
 LL | |         v.set();
    | |         - first borrow occurs due to use of `v` in closure
diff --git a/tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.rs b/tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.rs
new file mode 100644
index 00000000000..5425e571af0
--- /dev/null
+++ b/tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.rs
@@ -0,0 +1,8 @@
+//! Regression test for invalid suggestion for `&raw const expr` reported in
+//! <https://github.com/rust-lang/rust/issues/127562>.
+
+fn main() {
+    let val = 2;
+    let ptr = &raw const val;
+    unsafe { *ptr = 3; } //~ ERROR cannot assign to `*ptr`, which is behind a `*const` pointer
+}
diff --git a/tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.stderr b/tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.stderr
new file mode 100644
index 00000000000..c27dcc19827
--- /dev/null
+++ b/tests/ui/borrowck/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to `*ptr`, which is behind a `*const` pointer
+  --> $DIR/no-invalid-mut-suggestion-for-raw-pointer-issue-127562.rs:7:14
+   |
+LL |     unsafe { *ptr = 3; }
+   |              ^^^^^^^^ `ptr` is a `*const` pointer, so the data it refers to cannot be written
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/tests/ui/check-cfg/auxiliary/cfg_macro.rs b/tests/ui/check-cfg/auxiliary/cfg_macro.rs
index d68accd9202..1293fd6975e 100644
--- a/tests/ui/check-cfg/auxiliary/cfg_macro.rs
+++ b/tests/ui/check-cfg/auxiliary/cfg_macro.rs
@@ -9,3 +9,19 @@ macro_rules! my_lib_macro {
         $crate::my_lib_func()
     };
 }
+
+#[macro_export]
+macro_rules! my_lib_macro_value {
+    () => {
+        #[cfg(panic = "UNEXPECTED_VALUE")]
+        $crate::my_lib_func()
+    };
+}
+
+#[macro_export]
+macro_rules! my_lib_macro_feature {
+    () => {
+        #[cfg(feature = "UNEXPECTED_FEATURE")]
+        $crate::my_lib_func()
+    };
+}
diff --git a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr
new file mode 100644
index 00000000000..6fb397b5529
--- /dev/null
+++ b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr
@@ -0,0 +1,42 @@
+warning: unexpected `cfg` condition name: `my_lib_cfg`
+  --> $DIR/report-in-external-macros.rs:13:5
+   |
+LL |     cfg_macro::my_lib_macro!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
+   = help: try refering to `cfg_macro::my_lib_macro` crate for guidance on how handle this unexpected cfg
+   = help: the macro `cfg_macro::my_lib_macro` may come from an old version of it's defining crate, try updating your dependencies with `cargo update`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+   = note: this warning originates in the macro `cfg_macro::my_lib_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: unexpected `cfg` condition value: `UNEXPECTED_VALUE`
+  --> $DIR/report-in-external-macros.rs:16:5
+   |
+LL |     cfg_macro::my_lib_macro_value!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `panic` are: `abort` and `unwind`
+   = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
+   = help: try refering to `cfg_macro::my_lib_macro_value` crate for guidance on how handle this unexpected cfg
+   = help: the macro `cfg_macro::my_lib_macro_value` may come from an old version of it's defining crate, try updating your dependencies with `cargo update`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
+   = note: this warning originates in the macro `cfg_macro::my_lib_macro_value` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: unexpected `cfg` condition value: `UNEXPECTED_FEATURE`
+  --> $DIR/report-in-external-macros.rs:19:5
+   |
+LL |     cfg_macro::my_lib_macro_feature!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: no expected values for `feature`
+   = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
+   = help: try refering to `cfg_macro::my_lib_macro_feature` crate for guidance on how handle this unexpected cfg
+   = help: the macro `cfg_macro::my_lib_macro_feature` may come from an old version of it's defining crate, try updating your dependencies with `cargo update`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
+   = note: this warning originates in the macro `cfg_macro::my_lib_macro_feature` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/check-cfg/report-in-external-macros.rs b/tests/ui/check-cfg/report-in-external-macros.rs
index 56550b04af3..72c2f6f6618 100644
--- a/tests/ui/check-cfg/report-in-external-macros.rs
+++ b/tests/ui/check-cfg/report-in-external-macros.rs
@@ -3,10 +3,19 @@
 
 //@ check-pass
 //@ no-auto-check-cfg
+//@ revisions: cargo rustc
+//@ [rustc]unset-rustc-env:CARGO_CRATE_NAME
+//@ [cargo]rustc-env:CARGO_CRATE_NAME=foo
 //@ aux-crate: cfg_macro=cfg_macro.rs
-//@ compile-flags: --check-cfg=cfg()
+//@ compile-flags: --check-cfg=cfg(feature,values())
 
 fn main() {
     cfg_macro::my_lib_macro!();
     //~^ WARNING unexpected `cfg` condition name
+
+    cfg_macro::my_lib_macro_value!();
+    //~^ WARNING unexpected `cfg` condition value
+
+    cfg_macro::my_lib_macro_feature!();
+    //~^ WARNING unexpected `cfg` condition value
 }
diff --git a/tests/ui/check-cfg/report-in-external-macros.rustc.stderr b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr
new file mode 100644
index 00000000000..1a03184ee81
--- /dev/null
+++ b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr
@@ -0,0 +1,41 @@
+warning: unexpected `cfg` condition name: `my_lib_cfg`
+  --> $DIR/report-in-external-macros.rs:13:5
+   |
+LL |     cfg_macro::my_lib_macro!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
+   = help: try refering to `cfg_macro::my_lib_macro` crate for guidance on how handle this unexpected cfg
+   = help: to expect this configuration use `--check-cfg=cfg(my_lib_cfg)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+   = note: this warning originates in the macro `cfg_macro::my_lib_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: unexpected `cfg` condition value: `UNEXPECTED_VALUE`
+  --> $DIR/report-in-external-macros.rs:16:5
+   |
+LL |     cfg_macro::my_lib_macro_value!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `panic` are: `abort` and `unwind`
+   = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
+   = help: try refering to `cfg_macro::my_lib_macro_value` crate for guidance on how handle this unexpected cfg
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: this warning originates in the macro `cfg_macro::my_lib_macro_value` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: unexpected `cfg` condition value: `UNEXPECTED_FEATURE`
+  --> $DIR/report-in-external-macros.rs:19:5
+   |
+LL |     cfg_macro::my_lib_macro_feature!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: no expected values for `feature`
+   = help: to expect this configuration use `--check-cfg=cfg(feature, values("UNEXPECTED_FEATURE"))`
+   = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
+   = help: try refering to `cfg_macro::my_lib_macro_feature` crate for guidance on how handle this unexpected cfg
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: this warning originates in the macro `cfg_macro::my_lib_macro_feature` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/check-cfg/report-in-external-macros.stderr b/tests/ui/check-cfg/report-in-external-macros.stderr
deleted file mode 100644
index 11300a4e402..00000000000
--- a/tests/ui/check-cfg/report-in-external-macros.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-warning: unexpected `cfg` condition name: `my_lib_cfg`
-  --> $DIR/report-in-external-macros.rs:10:5
-   |
-LL |     cfg_macro::my_lib_macro!();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
-   = help: to expect this configuration use `--check-cfg=cfg(my_lib_cfg)`
-   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
-   = note: `#[warn(unexpected_cfgs)]` on by default
-   = note: this warning originates in the macro `cfg_macro::my_lib_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr
index 3df1545cd4a..e2ceb669482 100644
--- a/tests/ui/check-cfg/target_feature.stderr
+++ b/tests/ui/check-cfg/target_feature.stderr
@@ -98,6 +98,7 @@ LL |     cfg!(target_feature = "_UNEXPECTED_VALUE");
 `fp8dot2`
 `fp8dot4`
 `fp8fma`
+`fpregs`
 `fpuv2_df`
 `fpuv2_sf`
 `fpuv3_df`
@@ -261,6 +262,7 @@ LL |     cfg!(target_feature = "_UNEXPECTED_VALUE");
 `vsx`
 `wfxt`
 `wide-arithmetic`
+`x87`
 `xop`
 `xsave`
 `xsavec`
diff --git a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr
index 3c4f2de73a4..cb351d3cebd 100644
--- a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr
+++ b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr
@@ -16,7 +16,6 @@ LL | |
 LL | |
 LL | |         m[0] += 10;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -39,7 +38,6 @@ LL | |
 LL | |
 LL | |         m[0] += 10;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/by_value.stderr b/tests/ui/closures/2229_closure_analysis/by_value.stderr
index f843b76d723..af4ae34ad64 100644
--- a/tests/ui/closures/2229_closure_analysis/by_value.stderr
+++ b/tests/ui/closures/2229_closure_analysis/by_value.stderr
@@ -16,7 +16,6 @@ LL | |
 LL | |
 LL | |         let p = t.0.0;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -39,7 +38,6 @@ LL | |
 LL | |
 LL | |         let p = t.0.0;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr
index 64ae704bc90..eef201792c6 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr
@@ -16,7 +16,6 @@ LL | |
 LL | |
 LL | |         println!("{:?}", p);
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -49,7 +48,6 @@ LL | |
 LL | |
 LL | |         println!("{:?}", p);
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr
index 40c075f3cc8..8fe4d2d57ab 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr
@@ -16,7 +16,6 @@ LL | |
 LL | |
 LL | |         let _x = p.x;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -39,7 +38,6 @@ LL | |
 LL | |
 LL | |         let _x = p.x;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr
index a4689f2ea96..f1dbefe15d5 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr
@@ -16,7 +16,6 @@ LL | |
 LL | |
 LL | |         let _x = a.b.c;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -39,7 +38,6 @@ LL | |
 LL | |
 LL | |         let _x = a.b.c;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr
index 9d3004dbbb0..91c3d6d1674 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr
@@ -16,7 +16,6 @@ LL | |
 LL | |
 LL | |         let _x = a.b;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -39,7 +38,6 @@ LL | |
 LL | |
 LL | |         let _x = a.b;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr
index 48fbd682a5b..c9c227335a9 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr
@@ -15,8 +15,7 @@ LL | /     || {
 LL | |
 LL | |
 LL | |         println!("{}", p.x);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -33,8 +32,7 @@ LL | /     || {
 LL | |
 LL | |
 LL | |         println!("{}", p.x);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr
index 496511d6025..84aac180fbb 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr
@@ -15,8 +15,7 @@ LL | /     || {
 LL | |
 LL | |
 LL | |         println!("{}", t.0);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -33,8 +32,7 @@ LL | /     || {
 LL | |
 LL | |
 LL | |         println!("{}", t.0);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/capture-enums.stderr b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr
index 2d70b614858..89a879cec46 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-enums.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr
@@ -26,7 +26,6 @@ LL | |
 LL | |
 LL | |         if let Info::Point(_, _, str) = point {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -59,7 +58,6 @@ LL | |
 LL | |
 LL | |         if let Info::Point(_, _, str) = point {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr
index d118f7573a4..447ad8f4a68 100644
--- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr
+++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr
@@ -16,7 +16,6 @@ LL | |
 LL | |
 LL | |         let x = &p.a.p.x;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -44,7 +43,6 @@ LL | |
 LL | |
 LL | |         let x = &p.a.p.x;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr
index cc5f74613e4..639d1714721 100644
--- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr
+++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr
@@ -16,7 +16,6 @@ LL | |
 LL | |
 LL | |         let x = &t.0.0.0;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -44,7 +43,6 @@ LL | |
 LL | |
 LL | |         let x = &t.0.0.0;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs
index 3abc81e191e..2d22c9a856f 100644
--- a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs
+++ b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs
@@ -12,8 +12,7 @@ fn arrays_1() {
     // c will capture `arr` completely, therefore another index into the
     // array can't be modified here
     arr[1] += 10;
-    //~^ ERROR: cannot use `arr` because it was mutably borrowed
-    //~| ERROR: cannot use `arr[_]` because it was mutably borrowed
+    //~^ ERROR: cannot use `arr[_]` because it was mutably borrowed
     c();
 }
 
@@ -55,8 +54,7 @@ fn arrays_4() {
     // c will capture `arr` completely, therefore we cannot borrow another index
     // into the array.
     println!("{}", arr[3]);
-    //~^ ERROR: cannot use `arr` because it was mutably borrowed
-    //~| ERROR: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable
+    //~^ ERROR: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable
 
     c();
 }
diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr
index 9e5200ef34b..97ecdfab820 100644
--- a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr
+++ b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr
@@ -1,17 +1,3 @@
-error[E0503]: cannot use `arr` because it was mutably borrowed
-  --> $DIR/arrays.rs:14:5
-   |
-LL |     let mut c = || {
-   |                 -- `arr` is borrowed here
-LL |         arr[0] += 10;
-   |         --- borrow occurs due to use of `arr` in closure
-...
-LL |     arr[1] += 10;
-   |     ^^^^^^ use of borrowed `arr`
-...
-LL |     c();
-   |     - borrow later used here
-
 error[E0503]: cannot use `arr[_]` because it was mutably borrowed
   --> $DIR/arrays.rs:14:5
    |
@@ -22,12 +8,12 @@ LL |         arr[0] += 10;
 ...
 LL |     arr[1] += 10;
    |     ^^^^^^^^^^^^ use of borrowed `arr`
-...
+LL |
 LL |     c();
    |     - borrow later used here
 
 error[E0506]: cannot assign to `arr[_]` because it is borrowed
-  --> $DIR/arrays.rs:29:5
+  --> $DIR/arrays.rs:28:5
    |
 LL |     let c = || {
    |             -- `arr[_]` is borrowed here
@@ -41,7 +27,7 @@ LL |     c();
    |     - borrow later used here
 
 error[E0506]: cannot assign to `arr[_]` because it is borrowed
-  --> $DIR/arrays.rs:43:5
+  --> $DIR/arrays.rs:42:5
    |
 LL |     let c = || {
    |             -- `arr[_]` is borrowed here
@@ -54,22 +40,8 @@ LL |
 LL |     c();
    |     - borrow later used here
 
-error[E0503]: cannot use `arr` because it was mutably borrowed
-  --> $DIR/arrays.rs:57:20
-   |
-LL |     let mut c = || {
-   |                 -- `arr` is borrowed here
-LL |         arr[1] += 10;
-   |         --- borrow occurs due to use of `arr` in closure
-...
-LL |     println!("{}", arr[3]);
-   |                    ^^^^^^ use of borrowed `arr`
-...
-LL |     c();
-   |     - borrow later used here
-
 error[E0502]: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable
-  --> $DIR/arrays.rs:57:20
+  --> $DIR/arrays.rs:56:20
    |
 LL |     let mut c = || {
    |                 -- mutable borrow occurs here
@@ -85,7 +57,7 @@ LL |     c();
    = 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[E0502]: cannot borrow `arr` as immutable because it is also borrowed as mutable
-  --> $DIR/arrays.rs:73:24
+  --> $DIR/arrays.rs:71:24
    |
 LL |     let mut c = || {
    |                 -- mutable borrow occurs here
@@ -98,7 +70,7 @@ LL |     println!("{:#?}", &arr[3..2]);
 LL |     c();
    |     - mutable borrow later used here
 
-error: aborting due to 7 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0502, E0503, E0506.
 For more information about an error, try `rustc --explain E0502`.
diff --git a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr
index 6dbe8c153c0..3e4c4d3ccd3 100644
--- a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr
+++ b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr
@@ -15,8 +15,7 @@ LL | /     || {
 LL | |
 LL | |
 LL | |         println!("This uses new capture analyysis to capture s={}", s);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -33,8 +32,7 @@ LL | /     || {
 LL | |
 LL | |
 LL | |         println!("This uses new capture analyysis to capture s={}", s);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/issue-118144.stderr b/tests/ui/closures/2229_closure_analysis/issue-118144.stderr
index 85cb5adc07e..87084e60237 100644
--- a/tests/ui/closures/2229_closure_analysis/issue-118144.stderr
+++ b/tests/ui/closures/2229_closure_analysis/issue-118144.stderr
@@ -5,6 +5,11 @@ LL |         V(x) = func_arg;
    |         ^^^^   -------- this expression has type `&mut V`
    |         |
    |         expected `&mut V`, found `V`
+   |
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |         V(x) = &*func_arg;
+   |                ~~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/closures/2229_closure_analysis/issue-87378.stderr b/tests/ui/closures/2229_closure_analysis/issue-87378.stderr
index 3273e92d9d1..862ae7445e8 100644
--- a/tests/ui/closures/2229_closure_analysis/issue-87378.stderr
+++ b/tests/ui/closures/2229_closure_analysis/issue-87378.stderr
@@ -15,8 +15,7 @@ LL | /     || {
 LL | |
 LL | |
 LL | |        unsafe { u.value }
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -33,8 +32,7 @@ LL | /     || {
 LL | |
 LL | |
 LL | |        unsafe { u.value }
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/issue-88476.stderr b/tests/ui/closures/2229_closure_analysis/issue-88476.stderr
index 1c0e254dbf7..225b0335cf5 100644
--- a/tests/ui/closures/2229_closure_analysis/issue-88476.stderr
+++ b/tests/ui/closures/2229_closure_analysis/issue-88476.stderr
@@ -23,11 +23,7 @@ error: First Pass analysis includes:
    |
 LL |       let x = #[rustc_capture_analysis] move || {
    |  _______________________________________^
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -42,11 +38,7 @@ error: Min Capture analysis includes:
    |
 LL |       let x = #[rustc_capture_analysis] move || {
    |  _______________________________________^
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -61,11 +53,7 @@ error: First Pass analysis includes:
    |
 LL |       let c = #[rustc_capture_analysis] move || {
    |  _______________________________________^
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -80,11 +68,7 @@ error: Min Capture analysis includes:
    |
 LL |       let c = #[rustc_capture_analysis] move || {
    |  _______________________________________^
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
index 7125bfa3101..e7e5e7f7fa1 100644
--- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
+++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
@@ -6,7 +6,6 @@ LL | |
 LL | |
 LL | |         match variant {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -24,7 +23,6 @@ LL | |
 LL | |
 LL | |         match variant {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -64,7 +62,6 @@ LL | |
 LL | |
 LL | |         match variant {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -87,7 +84,6 @@ LL | |
 LL | |
 LL | |         match variant {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -138,7 +134,6 @@ LL | |
 LL | |
 LL | |         match variant {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -156,7 +151,6 @@ LL | |
 LL | |
 LL | |         match variant {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -174,7 +168,6 @@ LL | |
 LL | |
 LL | |         match slice {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -192,7 +185,6 @@ LL | |
 LL | |
 LL | |         match slice {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -210,7 +202,6 @@ LL | |
 LL | |
 LL | |         match slice {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -228,7 +219,6 @@ LL | |
 LL | |
 LL | |         match slice {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -246,7 +236,6 @@ LL | |
 LL | |
 LL | |         match slice {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -264,7 +253,6 @@ LL | |
 LL | |
 LL | |         match slice {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
@@ -281,8 +269,7 @@ LL | /     || {
 LL | |
 LL | |         match slice {
 LL | |             [..] => {},
-LL | |             _ => {}
-LL | |         }
+...  |
 LL | |     };
    | |_____^
 
diff --git a/tests/ui/closures/2229_closure_analysis/move_closure.stderr b/tests/ui/closures/2229_closure_analysis/move_closure.stderr
index 68754b8f7be..a4919d488d1 100644
--- a/tests/ui/closures/2229_closure_analysis/move_closure.stderr
+++ b/tests/ui/closures/2229_closure_analysis/move_closure.stderr
@@ -139,8 +139,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         t.0.0 = "new S".into();
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -157,8 +156,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         t.0.0 = "new S".into();
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -175,8 +173,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         *ref_s += 10;
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -193,8 +190,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         *ref_s += 10;
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -211,8 +207,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         t.0.0 = "new s".into();
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -229,8 +224,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         t.0.0 = "new s".into();
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -247,8 +241,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         let _t = t.0.0;
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -265,8 +258,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         let _t = t.0.0;
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -283,8 +275,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         let _t = t.0.0;
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -301,8 +292,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         let _t = t.0.0;
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -319,8 +309,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         let _t = b.0;
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -337,8 +326,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         let _t = b.0;
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -355,8 +343,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         println!("{}", b.0);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -373,8 +360,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         println!("{}", b.0);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -391,8 +377,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         println!("{}", t.1.0);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -409,8 +394,7 @@ LL | /     move || {
 LL | |
 LL | |
 LL | |         println!("{}", t.1.0);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr
index 97f53e490e8..cbc7188a4ec 100644
--- a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr
+++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr
@@ -15,8 +15,7 @@ LL | /     || {
 LL | |
 LL | |
 LL | |         println!("{}", w.p.x);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -33,8 +32,7 @@ LL | /     || {
 LL | |
 LL | |
 LL | |         println!("{}", w.p.x);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/nested-closure.stderr b/tests/ui/closures/2229_closure_analysis/nested-closure.stderr
index 03550cb2d35..3b36069e624 100644
--- a/tests/ui/closures/2229_closure_analysis/nested-closure.stderr
+++ b/tests/ui/closures/2229_closure_analysis/nested-closure.stderr
@@ -60,7 +60,6 @@ LL | |
 LL | |
 LL | |         println!("{}", p.x);
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -88,7 +87,6 @@ LL | |
 LL | |
 LL | |         println!("{}", p.x);
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr b/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr
index e82295f047b..c6608c05900 100644
--- a/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr
+++ b/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr
@@ -15,8 +15,7 @@ LL | /     || {
 LL | |
 LL | |
 LL | |         println!("{}", pent.points[5].x);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -33,8 +32,7 @@ LL | /     || {
 LL | |
 LL | |
 LL | |         println!("{}", pent.points[5].x);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr
index 65a0a317ab6..ff3cd5b8f01 100644
--- a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr
+++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr
@@ -36,7 +36,6 @@ LL | |
 LL | |
 LL | |         println!("{:?}", a.0);
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -69,7 +68,6 @@ LL | |
 LL | |
 LL | |         println!("{:?}", a.0);
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -102,7 +100,6 @@ LL | |
 LL | |
 LL | |         println!("{:?}", a.1);
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -135,7 +132,6 @@ LL | |
 LL | |
 LL | |         println!("{:?}", a.1);
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -168,7 +164,6 @@ LL | |
 LL | |
 LL | |         println!("{:?}", b.1);
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -201,7 +196,6 @@ LL | |
 LL | |
 LL | |         println!("{:?}", b.1);
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/repr_packed.stderr b/tests/ui/closures/2229_closure_analysis/repr_packed.stderr
index d4b2f8bfeae..bab1e8f9977 100644
--- a/tests/ui/closures/2229_closure_analysis/repr_packed.stderr
+++ b/tests/ui/closures/2229_closure_analysis/repr_packed.stderr
@@ -118,7 +118,6 @@ LL | |
 LL | |
 LL | |         println!("{}", foo.x);
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -141,7 +140,6 @@ LL | |
 LL | |
 LL | |         println!("{}", foo.x);
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr
index a88bd01093a..d4201b2d4c2 100644
--- a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr
+++ b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr
@@ -16,7 +16,6 @@ LL | |
 LL | |
 LL | |         p.x += 10;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -39,7 +38,6 @@ LL | |
 LL | |
 LL | |         p.x += 10;
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr
index 54463c5277d..9f3c6576c72 100644
--- a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr
+++ b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr
@@ -25,8 +25,7 @@ LL | /      || unsafe {
 LL | |
 LL | |
 LL | |         println!("{:?}", (*t.0).s);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
@@ -43,8 +42,7 @@ LL | /      || unsafe {
 LL | |
 LL | |
 LL | |         println!("{:?}", (*t.0).s);
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr b/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr
index 4d6d85649da..4cb0f4a4a92 100644
--- a/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr
+++ b/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr
@@ -32,11 +32,7 @@ error: First Pass analysis includes:
   --> $DIR/wild_patterns.rs:26:5
    |
 LL | /     || {
-LL | |
-LL | |
-LL | |         // FIXME(arora-aman): Change `_x` to `_`
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -50,11 +46,7 @@ error: Min Capture analysis includes:
   --> $DIR/wild_patterns.rs:26:5
    |
 LL | /     || {
-LL | |
-LL | |
-LL | |         // FIXME(arora-aman): Change `_x` to `_`
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -68,11 +60,7 @@ error: First Pass analysis includes:
   --> $DIR/wild_patterns.rs:45:5
    |
 LL | /     || {
-LL | |
-LL | |
-LL | |         // FIXME(arora-aman): Change `_x` to `_`
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -86,11 +74,7 @@ error: Min Capture analysis includes:
   --> $DIR/wild_patterns.rs:45:5
    |
 LL | /     || {
-LL | |
-LL | |
-LL | |         // FIXME(arora-aman): Change `_x` to `_`
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -104,11 +88,7 @@ error: First Pass analysis includes:
   --> $DIR/wild_patterns.rs:64:5
    |
 LL | /     || {
-LL | |
-LL | |
-LL | |         // FIXME(arora-aman): Change `_x` to `_`
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
@@ -122,11 +102,7 @@ error: Min Capture analysis includes:
   --> $DIR/wild_patterns.rs:64:5
    |
 LL | /     || {
-LL | |
-LL | |
-LL | |         // FIXME(arora-aman): Change `_x` to `_`
 ...  |
-LL | |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/codegen/alias-uninit-value.rs b/tests/ui/codegen/alias-uninit-value.rs
new file mode 100644
index 00000000000..a8aa94caaf2
--- /dev/null
+++ b/tests/ui/codegen/alias-uninit-value.rs
@@ -0,0 +1,26 @@
+//! Regression test for issue #374, where previously rustc performed conditional jumps or moves that
+//! incorrectly depended on uninitialized values.
+//!
+//! Issue: <https://github.com/rust-lang/rust/issues/374>.
+
+//@ run-pass
+
+#![allow(dead_code)]
+
+enum TyS {
+    Nil,
+}
+
+struct RawT {
+    struct_: TyS,
+    cname: Option<String>,
+    hash: usize,
+}
+
+fn mk_raw_ty(st: TyS, cname: Option<String>) -> RawT {
+    return RawT { struct_: st, cname: cname, hash: 0 };
+}
+
+pub fn main() {
+    mk_raw_ty(TyS::Nil, None::<String>);
+}
diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg b/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg
index 6f46df0101e..1cedbf75e4b 100644
--- a/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg
+++ b/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg
@@ -1,4 +1,4 @@
-<svg width="743px" height="848px" xmlns="http://www.w3.org/2000/svg">
+<svg width="743px" height="758px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
     .bg { background: #000000 }
@@ -33,83 +33,73 @@
 </tspan>
     <tspan x="10px" y="136px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold"> _________________-</tspan>
 </tspan>
-    <tspan x="10px" y="154px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>             // last line shown in multispan header</tspan>
+    <tspan x="10px" y="154px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan>  </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
 </tspan>
-    <tspan x="10px" y="172px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan>  </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+    <tspan x="10px" y="172px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>         ),</tspan>
 </tspan>
-    <tspan x="10px" y="190px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+    <tspan x="10px" y="190px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `()`</tspan>
 </tspan>
-    <tspan x="10px" y="208px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>         ),</tspan>
+    <tspan x="10px" y="208px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           false =&gt; "</tspan>
 </tspan>
-    <tspan x="10px" y="226px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `()`</tspan>
+    <tspan x="10px" y="226px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold"> __________________^</tspan>
 </tspan>
-    <tspan x="10px" y="244px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           false =&gt; "</tspan>
+    <tspan x="10px" y="244px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan>  </tspan><tspan class="fg-ansi256-009 bold">|</tspan>
 </tspan>
-    <tspan x="10px" y="262px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold"> __________________^</tspan>
+    <tspan x="10px" y="262px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan>         ",</tspan>
 </tspan>
-    <tspan x="10px" y="280px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan>  </tspan><tspan class="fg-ansi256-009 bold">|</tspan>
+    <tspan x="10px" y="280px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|_________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected `()`, found `&amp;str`</tspan>
 </tspan>
-    <tspan x="10px" y="298px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan>
+    <tspan x="10px" y="298px">
 </tspan>
-    <tspan x="10px" y="316px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan>         ",</tspan>
+    <tspan x="10px" y="316px"><tspan class="fg-ansi256-009 bold">error[E0308]</tspan><tspan class="bold">: `match` arms have incompatible types</tspan>
 </tspan>
-    <tspan x="10px" y="334px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|_________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected `()`, found `&amp;str`</tspan>
+    <tspan x="10px" y="334px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/huge_multispan_highlight.rs:216:18</tspan>
 </tspan>
-    <tspan x="10px" y="352px">
+    <tspan x="10px" y="352px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
 </tspan>
-    <tspan x="10px" y="370px"><tspan class="fg-ansi256-009 bold">error[E0308]</tspan><tspan class="bold">: `match` arms have incompatible types</tspan>
+    <tspan x="10px" y="370px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>       let _ = match true {</tspan>
 </tspan>
-    <tspan x="10px" y="388px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/huge_multispan_highlight.rs:216:18</tspan>
+    <tspan x="10px" y="388px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>               </tspan><tspan class="fg-ansi256-012 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`match` arms have incompatible types</tspan>
 </tspan>
-    <tspan x="10px" y="406px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+    <tspan x="10px" y="406px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           true =&gt; (</tspan>
 </tspan>
-    <tspan x="10px" y="424px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>       let _ = match true {</tspan>
+    <tspan x="10px" y="424px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold"> _________________-</tspan>
 </tspan>
-    <tspan x="10px" y="442px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>               </tspan><tspan class="fg-ansi256-012 bold">----------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`match` arms have incompatible types</tspan>
+    <tspan x="10px" y="442px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
 </tspan>
-    <tspan x="10px" y="460px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           true =&gt; (</tspan>
+    <tspan x="10px" y="460px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>         1 // last line shown in multispan header</tspan>
 </tspan>
-    <tspan x="10px" y="478px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold"> _________________-</tspan>
+    <tspan x="10px" y="478px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan>  </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
 </tspan>
-    <tspan x="10px" y="496px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+    <tspan x="10px" y="496px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>         ),</tspan>
 </tspan>
-    <tspan x="10px" y="514px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>         1 // last line shown in multispan header</tspan>
+    <tspan x="10px" y="514px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `{integer}`</tspan>
 </tspan>
-    <tspan x="10px" y="532px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan>  </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+    <tspan x="10px" y="532px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           false =&gt; "</tspan>
 </tspan>
-    <tspan x="10px" y="550px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+    <tspan x="10px" y="550px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold"> __________________^</tspan>
 </tspan>
-    <tspan x="10px" y="568px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>         ),</tspan>
+    <tspan x="10px" y="568px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan>
 </tspan>
-    <tspan x="10px" y="586px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `{integer}`</tspan>
+    <tspan x="10px" y="586px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan>
 </tspan>
-    <tspan x="10px" y="604px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>           false =&gt; "</tspan>
+    <tspan x="10px" y="604px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan>         1 last line shown in multispan</tspan>
 </tspan>
-    <tspan x="10px" y="622px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold"> __________________^</tspan>
+    <tspan x="10px" y="622px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan>  </tspan><tspan class="fg-ansi256-009 bold">|</tspan>
 </tspan>
-    <tspan x="10px" y="640px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan>
+    <tspan x="10px" y="640px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan>         ",</tspan>
 </tspan>
-    <tspan x="10px" y="658px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan>
+    <tspan x="10px" y="658px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|_________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `&amp;str`</tspan>
 </tspan>
-    <tspan x="10px" y="676px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan>         1 last line shown in multispan</tspan>
+    <tspan x="10px" y="676px">
 </tspan>
-    <tspan x="10px" y="694px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan>  </tspan><tspan class="fg-ansi256-009 bold">|</tspan>
+    <tspan x="10px" y="694px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 2 previous errors</tspan>
 </tspan>
-    <tspan x="10px" y="712px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan>
+    <tspan x="10px" y="712px">
 </tspan>
-    <tspan x="10px" y="730px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan>         ",</tspan>
+    <tspan x="10px" y="730px"><tspan class="bold">For more information about this error, try `rustc --explain E0308`.</tspan>
 </tspan>
-    <tspan x="10px" y="748px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|_________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `&amp;str`</tspan>
-</tspan>
-    <tspan x="10px" y="766px">
-</tspan>
-    <tspan x="10px" y="784px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 2 previous errors</tspan>
-</tspan>
-    <tspan x="10px" y="802px">
-</tspan>
-    <tspan x="10px" y="820px"><tspan class="bold">For more information about this error, try `rustc --explain E0308`.</tspan>
-</tspan>
-    <tspan x="10px" y="838px">
+    <tspan x="10px" y="748px">
 </tspan>
   </text>
 
diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg b/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg
index 4e1a8d14a28..36a33b74042 100644
--- a/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg
+++ b/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg
@@ -1,4 +1,4 @@
-<svg width="743px" height="848px" xmlns="http://www.w3.org/2000/svg">
+<svg width="743px" height="758px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
     .bg { background: #000000 }
@@ -33,83 +33,73 @@
 </tspan>
     <tspan x="10px" y="136px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">┌─────────────────┘</tspan>
 </tspan>
-    <tspan x="10px" y="154px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>             // last line shown in multispan header</tspan>
+    <tspan x="10px" y="154px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
 </tspan>
-    <tspan x="10px" y="172px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
+    <tspan x="10px" y="172px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>         ),</tspan>
 </tspan>
-    <tspan x="10px" y="190px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
+    <tspan x="10px" y="190px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">└─────────┘</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `()`</tspan>
 </tspan>
-    <tspan x="10px" y="208px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>         ),</tspan>
+    <tspan x="10px" y="208px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>           false =&gt; "</tspan>
 </tspan>
-    <tspan x="10px" y="226px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">└─────────┘</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `()`</tspan>
+    <tspan x="10px" y="226px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┏━━━━━━━━━━━━━━━━━━┛</tspan>
 </tspan>
-    <tspan x="10px" y="244px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>           false =&gt; "</tspan>
+    <tspan x="10px" y="244px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan>
 </tspan>
-    <tspan x="10px" y="262px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┏━━━━━━━━━━━━━━━━━━┛</tspan>
+    <tspan x="10px" y="262px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan><tspan>         ",</tspan>
 </tspan>
-    <tspan x="10px" y="280px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan>
+    <tspan x="10px" y="280px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">╰╴</tspan><tspan class="fg-ansi256-009 bold">┗━━━━━━━━━┛</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected `()`, found `&amp;str`</tspan>
 </tspan>
-    <tspan x="10px" y="298px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan>
+    <tspan x="10px" y="298px">
 </tspan>
-    <tspan x="10px" y="316px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan><tspan>         ",</tspan>
+    <tspan x="10px" y="316px"><tspan class="fg-ansi256-009 bold">error[E0308]</tspan><tspan class="bold">: `match` arms have incompatible types</tspan>
 </tspan>
-    <tspan x="10px" y="334px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">╰╴</tspan><tspan class="fg-ansi256-009 bold">┗━━━━━━━━━┛</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected `()`, found `&amp;str`</tspan>
+    <tspan x="10px" y="334px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold"> ╭▸ </tspan><tspan>$DIR/huge_multispan_highlight.rs:216:18</tspan>
 </tspan>
-    <tspan x="10px" y="352px">
+    <tspan x="10px" y="352px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
 </tspan>
-    <tspan x="10px" y="370px"><tspan class="fg-ansi256-009 bold">error[E0308]</tspan><tspan class="bold">: `match` arms have incompatible types</tspan>
+    <tspan x="10px" y="370px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>       let _ = match true {</tspan>
 </tspan>
-    <tspan x="10px" y="388px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold"> ╭▸ </tspan><tspan>$DIR/huge_multispan_highlight.rs:216:18</tspan>
+    <tspan x="10px" y="388px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>               </tspan><tspan class="fg-ansi256-012 bold">──────────</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`match` arms have incompatible types</tspan>
 </tspan>
-    <tspan x="10px" y="406px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
+    <tspan x="10px" y="406px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>           true =&gt; (</tspan>
 </tspan>
-    <tspan x="10px" y="424px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>       let _ = match true {</tspan>
+    <tspan x="10px" y="424px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">┌─────────────────┘</tspan>
 </tspan>
-    <tspan x="10px" y="442px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>               </tspan><tspan class="fg-ansi256-012 bold">──────────</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">`match` arms have incompatible types</tspan>
+    <tspan x="10px" y="442px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
 </tspan>
-    <tspan x="10px" y="460px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>           true =&gt; (</tspan>
+    <tspan x="10px" y="460px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>         1 // last line shown in multispan header</tspan>
 </tspan>
-    <tspan x="10px" y="478px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">┌─────────────────┘</tspan>
+    <tspan x="10px" y="478px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
 </tspan>
-    <tspan x="10px" y="496px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
+    <tspan x="10px" y="496px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>         ),</tspan>
 </tspan>
-    <tspan x="10px" y="514px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>         1 // last line shown in multispan header</tspan>
+    <tspan x="10px" y="514px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">└─────────┘</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `{integer}`</tspan>
 </tspan>
-    <tspan x="10px" y="532px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
+    <tspan x="10px" y="532px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>           false =&gt; "</tspan>
 </tspan>
-    <tspan x="10px" y="550px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
+    <tspan x="10px" y="550px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┏━━━━━━━━━━━━━━━━━━┛</tspan>
 </tspan>
-    <tspan x="10px" y="568px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>         ),</tspan>
+    <tspan x="10px" y="568px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan>
 </tspan>
-    <tspan x="10px" y="586px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">└─────────┘</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this is found to be of type `{integer}`</tspan>
+    <tspan x="10px" y="586px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan>
 </tspan>
-    <tspan x="10px" y="604px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>           false =&gt; "</tspan>
+    <tspan x="10px" y="604px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan><tspan>         1 last line shown in multispan</tspan>
 </tspan>
-    <tspan x="10px" y="622px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┏━━━━━━━━━━━━━━━━━━┛</tspan>
+    <tspan x="10px" y="622px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan>
 </tspan>
-    <tspan x="10px" y="640px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan>
+    <tspan x="10px" y="640px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan><tspan>         ",</tspan>
 </tspan>
-    <tspan x="10px" y="658px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan>
+    <tspan x="10px" y="658px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">╰╴</tspan><tspan class="fg-ansi256-009 bold">┗━━━━━━━━━┛</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `&amp;str`</tspan>
 </tspan>
-    <tspan x="10px" y="676px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan><tspan>         1 last line shown in multispan</tspan>
+    <tspan x="10px" y="676px">
 </tspan>
-    <tspan x="10px" y="694px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">‡</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan>
+    <tspan x="10px" y="694px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 2 previous errors</tspan>
 </tspan>
-    <tspan x="10px" y="712px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan>
+    <tspan x="10px" y="712px">
 </tspan>
-    <tspan x="10px" y="730px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">┃</tspan><tspan>         ",</tspan>
+    <tspan x="10px" y="730px"><tspan class="bold">For more information about this error, try `rustc --explain E0308`.</tspan>
 </tspan>
-    <tspan x="10px" y="748px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">╰╴</tspan><tspan class="fg-ansi256-009 bold">┗━━━━━━━━━┛</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `&amp;str`</tspan>
-</tspan>
-    <tspan x="10px" y="766px">
-</tspan>
-    <tspan x="10px" y="784px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 2 previous errors</tspan>
-</tspan>
-    <tspan x="10px" y="802px">
-</tspan>
-    <tspan x="10px" y="820px"><tspan class="bold">For more information about this error, try `rustc --explain E0308`.</tspan>
-</tspan>
-    <tspan x="10px" y="838px">
+    <tspan x="10px" y="748px">
 </tspan>
   </text>
 
diff --git a/tests/ui/coercion/coerce-loop-issue-122561.stderr b/tests/ui/coercion/coerce-loop-issue-122561.stderr
index 90e9f41c291..3af7e7cddb3 100644
--- a/tests/ui/coercion/coerce-loop-issue-122561.stderr
+++ b/tests/ui/coercion/coerce-loop-issue-122561.stderr
@@ -189,8 +189,7 @@ error[E0308]: mismatched types
 LL |   fn while_never_type() -> ! {
    |                            - expected `!` because of return type
 LL | /     while true {
-LL | |
-LL | |
+...  |
 LL | |     }
    | |_____^ expected `!`, found `()`
    |
diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr
index a3211b77623..58d42d82998 100644
--- a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr
+++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr
@@ -2,10 +2,7 @@ error: free constant item without body
   --> $DIR/const_arg_trivial_macro_expansion-2.rs:12:1
    |
 LL | / const _: A<
-LL | |
-LL | |
-LL | |     {
-LL | |         y! { test.tou8 }
+...  |
 LL | |     },
 LL | | >;
    | |  ^ help: provide a definition for the constant: `= <expr>;`
diff --git a/tests/ui/const-generics/issues/issue-67945-2.full.stderr b/tests/ui/const-generics/issues/issue-67945-2.full.stderr
index 837927d588c..1eca3261a4a 100644
--- a/tests/ui/const-generics/issues/issue-67945-2.full.stderr
+++ b/tests/ui/const-generics/issues/issue-67945-2.full.stderr
@@ -5,8 +5,7 @@ LL |       A: [(); {
    |  _____________^
 LL | |
 LL | |         let x: Option<Box<Self>> = None;
-LL | |
-LL | |         0
+...  |
 LL | |     }],
    | |_____^ blocks are not supported in generic constants
    |
diff --git a/tests/ui/const-generics/issues/issue-71202.stderr b/tests/ui/const-generics/issues/issue-71202.stderr
index a2d38221852..cc3603d1145 100644
--- a/tests/ui/const-generics/issues/issue-71202.stderr
+++ b/tests/ui/const-generics/issues/issue-71202.stderr
@@ -4,7 +4,6 @@ error: unconstrained generic constant
 LL | /     const ITEM_IS_COPY: [(); 1 - {
 LL | |         trait NotCopy {
 LL | |             const VALUE: bool = false;
-LL | |         }
 ...  |
 LL | |         <IsCopy<T>>::VALUE
 LL | |     } as usize] = [];
diff --git a/tests/ui/const-generics/nested-type.min.stderr b/tests/ui/const-generics/nested-type.min.stderr
index 8696be3faf3..cdc0b9807d9 100644
--- a/tests/ui/const-generics/nested-type.min.stderr
+++ b/tests/ui/const-generics/nested-type.min.stderr
@@ -25,7 +25,6 @@ LL | |     struct Foo<const N: usize>;
 LL | |
 LL | |     impl<const N: usize> Foo<N> {
 ...  |
-LL | |
 LL | | }]>;
    | |__^
    |
diff --git a/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr b/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr
index d664ae88323..f326da8e26a 100644
--- a/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr
+++ b/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr
@@ -16,7 +16,6 @@ LL |       let s = [(); {
    |  __________________^
 LL | |         let mut n = 113383; // #20 in https://oeis.org/A006884
 LL | |         while n != 0 {
-LL | |
 ...  |
 LL | |         n
 LL | |     }];
diff --git a/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr b/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr
index d664ae88323..f326da8e26a 100644
--- a/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr
+++ b/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr
@@ -16,7 +16,6 @@ LL |       let s = [(); {
    |  __________________^
 LL | |         let mut n = 113383; // #20 in https://oeis.org/A006884
 LL | |         while n != 0 {
-LL | |
 ...  |
 LL | |         n
 LL | |     }];
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr
index 7f6625bcfcd..dddd79a4383 100644
--- a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr
@@ -2,10 +2,7 @@ warning: constant evaluation is taking a long time
   --> $DIR/ctfe-simple-loop.rs:10:5
    |
 LL | /     while index < n {
-LL | |
-LL | |
-LL | |
-LL | |         index = index + 1;
+...  |
 LL | |     }
    | |_____^ the const evaluator is currently interpreting this expression
    |
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr
index 657f0e5bcba..2bb9a8a98ec 100644
--- a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr
@@ -2,10 +2,7 @@ warning: constant evaluation is taking a long time
   --> $DIR/ctfe-simple-loop.rs:10:5
    |
 LL | /     while index < n {
-LL | |
-LL | |
-LL | |
-LL | |         index = index + 1;
+...  |
 LL | |     }
    | |_____^
    |
@@ -26,10 +23,7 @@ warning: constant evaluation is taking a long time
   --> $DIR/ctfe-simple-loop.rs:10:5
    |
 LL | /     while index < n {
-LL | |
-LL | |
-LL | |
-LL | |         index = index + 1;
+...  |
 LL | |     }
    | |_____^
    |
@@ -45,10 +39,7 @@ warning: constant evaluation is taking a long time
   --> $DIR/ctfe-simple-loop.rs:10:5
    |
 LL | /     while index < n {
-LL | |
-LL | |
-LL | |
-LL | |         index = index + 1;
+...  |
 LL | |     }
    | |_____^ the const evaluator is currently interpreting this expression
    |
diff --git a/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr b/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr
index cb19c59b15b..f41d2ea3e62 100644
--- a/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr
+++ b/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr
@@ -2,11 +2,7 @@ warning: constant evaluation is taking a long time
   --> $DIR/evade-deduplication-issue-118612.rs:8:5
    |
 LL | /     loop {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |         }
 LL | |     }
    | |_____^ the const evaluator is currently interpreting this expression
    |
@@ -20,11 +16,7 @@ warning: constant evaluation is taking a long time
   --> $DIR/evade-deduplication-issue-118612.rs:8:5
    |
 LL | /     loop {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |         }
 LL | |     }
    | |_____^ the const evaluator is currently interpreting this expression
    |
@@ -38,11 +30,7 @@ warning: constant evaluation is taking a long time
   --> $DIR/evade-deduplication-issue-118612.rs:8:5
    |
 LL | /     loop {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |         }
 LL | |     }
    | |_____^ the const evaluator is currently interpreting this expression
    |
@@ -56,11 +44,7 @@ warning: constant evaluation is taking a long time
   --> $DIR/evade-deduplication-issue-118612.rs:8:5
    |
 LL | /     loop {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |         }
 LL | |     }
    | |_____^ the const evaluator is currently interpreting this expression
    |
@@ -74,11 +58,7 @@ warning: constant evaluation is taking a long time
   --> $DIR/evade-deduplication-issue-118612.rs:8:5
    |
 LL | /     loop {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |         }
 LL | |     }
    | |_____^ the const evaluator is currently interpreting this expression
    |
diff --git a/tests/ui/consts/issue-65348.rs b/tests/ui/consts/issue-65348.rs
index 1443fcbe1c1..0d12da3926c 100644
--- a/tests/ui/consts/issue-65348.rs
+++ b/tests/ui/consts/issue-65348.rs
@@ -9,15 +9,17 @@ impl<T> Generic<T> {
 }
 
 pub const fn array<T>() -> &'static T {
-    #[allow(unconditional_panic)]
+    #[expect(unconditional_panic)]
     &Generic::<T>::ARRAY[0]
 }
 
 pub const fn newtype_array<T>() -> &'static T {
+    #[expect(unconditional_panic)]
     &Generic::<T>::NEWTYPE_ARRAY.0[0]
 }
 
 pub const fn array_field<T>() -> &'static T {
+    #[expect(unconditional_panic)]
     &(Generic::<T>::ARRAY_FIELD.0).1[0]
 }
 
diff --git a/tests/ui/coroutine/drop-tracking-parent-expression.stderr b/tests/ui/coroutine/drop-tracking-parent-expression.stderr
index 51fc20070bf..dc2f9768d23 100644
--- a/tests/ui/coroutine/drop-tracking-parent-expression.stderr
+++ b/tests/ui/coroutine/drop-tracking-parent-expression.stderr
@@ -7,7 +7,6 @@ LL |               assert_send(g);
 LL | /     type_combinations!(
 LL | |         // OK
 LL | |         copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
-LL | |         // NOT OK: MIR borrowck thinks that this is used after the yield, even though
 ...  |
 LL | |         };
 LL | |     );
@@ -26,7 +25,6 @@ LL |                   _ => yield,
 LL | /     type_combinations!(
 LL | |         // OK
 LL | |         copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
-LL | |         // NOT OK: MIR borrowck thinks that this is used after the yield, even though
 ...  |
 LL | |         };
 LL | |     );
@@ -47,7 +45,6 @@ LL |               assert_send(g);
 LL | /     type_combinations!(
 LL | |         // OK
 LL | |         copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
-LL | |         // NOT OK: MIR borrowck thinks that this is used after the yield, even though
 ...  |
 LL | |         };
 LL | |     );
@@ -66,7 +63,6 @@ LL |                   _ => yield,
 LL | /     type_combinations!(
 LL | |         // OK
 LL | |         copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
-LL | |         // NOT OK: MIR borrowck thinks that this is used after the yield, even though
 ...  |
 LL | |         };
 LL | |     );
@@ -87,7 +83,6 @@ LL |               assert_send(g);
 LL | /     type_combinations!(
 LL | |         // OK
 LL | |         copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
-LL | |         // NOT OK: MIR borrowck thinks that this is used after the yield, even though
 ...  |
 LL | |         };
 LL | |     );
@@ -106,7 +101,6 @@ LL |                   _ => yield,
 LL | /     type_combinations!(
 LL | |         // OK
 LL | |         copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
-LL | |         // NOT OK: MIR borrowck thinks that this is used after the yield, even though
 ...  |
 LL | |         };
 LL | |     );
diff --git a/tests/ui/coroutine/issue-88653.stderr b/tests/ui/coroutine/issue-88653.stderr
index ef0cc11dde8..772a7f8424a 100644
--- a/tests/ui/coroutine/issue-88653.stderr
+++ b/tests/ui/coroutine/issue-88653.stderr
@@ -12,8 +12,7 @@ LL |       |bar| {
 LL | |
 LL | |
 LL | |         if bar {
-LL | |             yield bar;
-LL | |         }
+...  |
 LL | |     }
    | |_____- return type was inferred to be `{coroutine@$DIR/issue-88653.rs:15:5: 15:10}` here
    |
diff --git a/tests/ui/coroutine/match-bindings.stderr b/tests/ui/coroutine/match-bindings.stderr
index 5525bfed116..1318e6931f5 100644
--- a/tests/ui/coroutine/match-bindings.stderr
+++ b/tests/ui/coroutine/match-bindings.stderr
@@ -7,7 +7,6 @@ LL | |         loop {
 LL | |             if let true = true {
 LL | |                 match Enum::A(String::new()) {
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/coroutine/parent-expression.stderr b/tests/ui/coroutine/parent-expression.stderr
index 770ffda7a26..a9125772b5a 100644
--- a/tests/ui/coroutine/parent-expression.stderr
+++ b/tests/ui/coroutine/parent-expression.stderr
@@ -7,7 +7,6 @@ LL |               assert_send(g);
 LL | /     type_combinations!(
 LL | |         // OK
 LL | |         copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
-LL | |         // NOT OK: MIR borrowck thinks that this is used after the yield, even though
 ...  |
 LL | |         };
 LL | |     );
@@ -26,7 +25,6 @@ LL |                   _ => yield,
 LL | /     type_combinations!(
 LL | |         // OK
 LL | |         copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
-LL | |         // NOT OK: MIR borrowck thinks that this is used after the yield, even though
 ...  |
 LL | |         };
 LL | |     );
@@ -47,7 +45,6 @@ LL |               assert_send(g);
 LL | /     type_combinations!(
 LL | |         // OK
 LL | |         copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
-LL | |         // NOT OK: MIR borrowck thinks that this is used after the yield, even though
 ...  |
 LL | |         };
 LL | |     );
@@ -66,7 +63,6 @@ LL |                   _ => yield,
 LL | /     type_combinations!(
 LL | |         // OK
 LL | |         copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
-LL | |         // NOT OK: MIR borrowck thinks that this is used after the yield, even though
 ...  |
 LL | |         };
 LL | |     );
@@ -87,7 +83,6 @@ LL |               assert_send(g);
 LL | /     type_combinations!(
 LL | |         // OK
 LL | |         copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
-LL | |         // NOT OK: MIR borrowck thinks that this is used after the yield, even though
 ...  |
 LL | |         };
 LL | |     );
@@ -106,7 +101,6 @@ LL |                   _ => yield,
 LL | /     type_combinations!(
 LL | |         // OK
 LL | |         copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
-LL | |         // NOT OK: MIR borrowck thinks that this is used after the yield, even though
 ...  |
 LL | |         };
 LL | |     );
diff --git a/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr b/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr
index 48df5c5beac..4fad4036300 100644
--- a/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr
+++ b/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr
@@ -3,9 +3,6 @@ warning: unused coroutine that must be used
    |
 LL |           #[coroutine] static move || {
    |  ______________________^
-LL | |             // Tests that the coroutine transformation finds out that `a` is not live
-LL | |             // during the yield expression. Type checking will also compute liveness
-LL | |             // and it should also find out that `a` is not live.
 ...  |
 LL | |             let _ = &a;
 LL | |         };
diff --git a/tests/ui/coroutine/yield-in-initializer.stderr b/tests/ui/coroutine/yield-in-initializer.stderr
index 1e22b787668..eff5a0fdccf 100644
--- a/tests/ui/coroutine/yield-in-initializer.stderr
+++ b/tests/ui/coroutine/yield-in-initializer.stderr
@@ -4,10 +4,7 @@ warning: unused coroutine that must be used
 LL |       #[coroutine] static || {
    |  __________________^
 LL | |         loop {
-LL | |             // Test that `opt` is not live across the yield, even when borrowed in a loop
-LL | |             // See https://github.com/rust-lang/rust/issues/52792
 ...  |
-LL | |         }
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/coverage-attr/name-value.stderr b/tests/ui/coverage-attr/name-value.stderr
index 986467dda69..38101764d6f 100644
--- a/tests/ui/coverage-attr/name-value.stderr
+++ b/tests/ui/coverage-attr/name-value.stderr
@@ -171,8 +171,6 @@ LL |   #[coverage = "off"]
 ...
 LL | / trait MyTrait {
 LL | |     #[coverage = "off"]
-LL | |
-LL | |
 ...  |
 LL | |     type T;
 LL | | }
diff --git a/tests/ui/coverage-attr/word-only.stderr b/tests/ui/coverage-attr/word-only.stderr
index 1ce149724c6..154ea61f3a3 100644
--- a/tests/ui/coverage-attr/word-only.stderr
+++ b/tests/ui/coverage-attr/word-only.stderr
@@ -171,8 +171,6 @@ LL |   #[coverage]
 ...
 LL | / trait MyTrait {
 LL | |     #[coverage]
-LL | |
-LL | |
 ...  |
 LL | |     type T;
 LL | | }
diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs
new file mode 100644
index 00000000000..40b9e6536f5
--- /dev/null
+++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs
@@ -0,0 +1,27 @@
+// ignore-tidy-linelength
+//! Check that `-A warnings` cli flag applies to non-lint warnings as well.
+//!
+//! This test tries to exercise that by checking that the "relaxing a default bound only does
+//! something for `?Sized`; all other traits are not bound by default" non-lint warning (normally
+//! warn-by-default) is suppressed if the `-A warnings` cli flag is passed.
+//!
+//! Take special note that `warnings` is a special pseudo lint group in relationship to non-lint
+//! warnings, which is somewhat special. This test does not exercise other `-A <other_lint_group>`
+//! that check that they are working in the same way, only `warnings` specifically.
+//!
+//! # Relevant context
+//!
+//! - Original impl PR: <https://github.com/rust-lang/rust/pull/21248>.
+//! - RFC 507 "Release channels":
+//!   <https://github.com/rust-lang/rfcs/blob/c017755b9bfa0421570d92ba38082302e0f3ad4f/text/0507-release-channels.md>.
+#![crate_type = "lib"]
+
+//@ revisions: without_flag with_flag
+
+//@[with_flag] compile-flags: -Awarnings
+
+//@ check-pass
+
+pub trait Trait {}
+pub fn f<T: ?Trait>() {}
+//[without_flag]~^ WARN relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr
new file mode 100644
index 00000000000..b037847c70f
--- /dev/null
+++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr
@@ -0,0 +1,8 @@
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/allow-non-lint-warnings.rs:26:13
+   |
+LL | pub fn f<T: ?Trait>() {}
+   |             ^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/diagnostic-width/E0271.ascii.stderr b/tests/ui/diagnostic-width/E0271.ascii.stderr
index e276299e9e8..7446b1a543e 100644
--- a/tests/ui/diagnostic-width/E0271.ascii.stderr
+++ b/tests/ui/diagnostic-width/E0271.ascii.stderr
@@ -6,7 +6,6 @@ LL | |         Ok::<_, ()>(
 LL | |             Err::<(), _>(
 LL | |                 Ok::<_, ()>(
 ...  |
-LL | |         )
 LL | |     )
    | |_____^ type mismatch resolving `<Result<Result<(), Result<Result<(), ...>, ...>>, ...> as Future>::Error == Foo`
    |
diff --git a/tests/ui/diagnostic-width/E0271.unicode.stderr b/tests/ui/diagnostic-width/E0271.unicode.stderr
index 4a96ca36cd7..72df2a381a4 100644
--- a/tests/ui/diagnostic-width/E0271.unicode.stderr
+++ b/tests/ui/diagnostic-width/E0271.unicode.stderr
@@ -6,7 +6,6 @@ LL │ ┃         Ok::<_, ()>(
 LL │ ┃             Err::<(), _>(
 LL │ ┃                 Ok::<_, ()>(
    ‡ ┃
-LL │ ┃         )
 LL │ ┃     )
    │ ┗━━━━━┛ type mismatch resolving `<Result<Result<(), Result<Result<(), ...>, ...>>, ...> as Future>::Error == Foo`
    ╰╴
diff --git a/tests/ui/drop/lint-tail-expr-drop-order.stderr b/tests/ui/drop/lint-tail-expr-drop-order.stderr
index f0da24605e6..a3084f660e4 100644
--- a/tests/ui/drop/lint-tail-expr-drop-order.stderr
+++ b/tests/ui/drop/lint-tail-expr-drop-order.stderr
@@ -22,22 +22,14 @@ note: `#1` invokes this custom destructor
   --> $DIR/lint-tail-expr-drop-order.rs:11:1
    |
 LL | / impl Drop for LoudDropper {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |     }
 LL | | }
    | |_^
 note: `x` invokes this custom destructor
   --> $DIR/lint-tail-expr-drop-order.rs:11:1
    |
 LL | / impl Drop for LoudDropper {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |     }
 LL | | }
    | |_^
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
@@ -71,22 +63,14 @@ note: `#1` invokes this custom destructor
   --> $DIR/lint-tail-expr-drop-order.rs:11:1
    |
 LL | / impl Drop for LoudDropper {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |     }
 LL | | }
    | |_^
 note: `x` invokes this custom destructor
   --> $DIR/lint-tail-expr-drop-order.rs:11:1
    |
 LL | / impl Drop for LoudDropper {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |     }
 LL | | }
    | |_^
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
@@ -115,22 +99,14 @@ note: `#1` invokes this custom destructor
   --> $DIR/lint-tail-expr-drop-order.rs:11:1
    |
 LL | / impl Drop for LoudDropper {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |     }
 LL | | }
    | |_^
 note: `x` invokes this custom destructor
   --> $DIR/lint-tail-expr-drop-order.rs:11:1
    |
 LL | / impl Drop for LoudDropper {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |     }
 LL | | }
    | |_^
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
@@ -159,22 +135,14 @@ note: `#1` invokes this custom destructor
   --> $DIR/lint-tail-expr-drop-order.rs:11:1
    |
 LL | / impl Drop for LoudDropper {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |     }
 LL | | }
    | |_^
 note: `future` invokes this custom destructor
   --> $DIR/lint-tail-expr-drop-order.rs:11:1
    |
 LL | / impl Drop for LoudDropper {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |     }
 LL | | }
    | |_^
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
@@ -225,22 +193,14 @@ note: `#1` invokes this custom destructor
   --> $DIR/lint-tail-expr-drop-order.rs:11:1
    |
 LL | / impl Drop for LoudDropper {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |     }
 LL | | }
    | |_^
 note: `x` invokes this custom destructor
   --> $DIR/lint-tail-expr-drop-order.rs:11:1
    |
 LL | / impl Drop for LoudDropper {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |     }
 LL | | }
    | |_^
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
@@ -311,22 +271,14 @@ note: `#1` invokes this custom destructor
   --> $DIR/lint-tail-expr-drop-order.rs:11:1
    |
 LL | / impl Drop for LoudDropper {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |     }
 LL | | }
    | |_^
 note: `_x` invokes this custom destructor
   --> $DIR/lint-tail-expr-drop-order.rs:11:1
    |
 LL | / impl Drop for LoudDropper {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |     }
 LL | | }
    | |_^
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds.rs b/tests/ui/dyn-compatibility/assoc_type_bounds.rs
index 8634ba626a1..6e2076a4822 100644
--- a/tests/ui/dyn-compatibility/assoc_type_bounds.rs
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds.rs
@@ -7,7 +7,7 @@ trait Foo<T> {
 trait Cake {}
 impl Cake for () {}
 
-fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
-fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
+fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<()>` must be specified
+fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<i32>` must be specified
 
 fn main() {}
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds.stderr
index 3d5482625af..21ba9030117 100644
--- a/tests/ui/dyn-compatibility/assoc_type_bounds.stderr
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds.stderr
@@ -1,4 +1,4 @@
-error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
+error[E0191]: the value of the associated type `Bar` in `Foo<()>` must be specified
   --> $DIR/assoc_type_bounds.rs:10:16
    |
 LL |     type Bar
@@ -7,7 +7,7 @@ LL |     type Bar
 LL | fn foo(_: &dyn Foo<()>) {}
    |                ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>`
 
-error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
+error[E0191]: the value of the associated type `Bar` in `Foo<i32>` must be specified
   --> $DIR/assoc_type_bounds.rs:11:16
    |
 LL |     type Bar
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds2.rs b/tests/ui/dyn-compatibility/assoc_type_bounds2.rs
index f7dc2fb8839..2b35016d774 100644
--- a/tests/ui/dyn-compatibility/assoc_type_bounds2.rs
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds2.rs
@@ -7,7 +7,7 @@ trait Foo<T> {
 trait Cake {}
 impl Cake for () {}
 
-fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
-fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo` must be specified
+fn foo(_: &dyn Foo<()>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<()>` must be specified
+fn bar(_: &dyn Foo<i32>) {} //~ ERROR: the value of the associated type `Bar` in `Foo<i32>` must be specified
 
 fn main() {}
diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr
index 815747436bf..5c4163b1969 100644
--- a/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr
+++ b/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr
@@ -1,4 +1,4 @@
-error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
+error[E0191]: the value of the associated type `Bar` in `Foo<()>` must be specified
   --> $DIR/assoc_type_bounds2.rs:10:16
    |
 LL |     type Bar
@@ -7,7 +7,7 @@ LL |     type Bar
 LL | fn foo(_: &dyn Foo<()>) {}
    |                ^^^^^^^ help: specify the associated type: `Foo<(), Bar = Type>`
 
-error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
+error[E0191]: the value of the associated type `Bar` in `Foo<i32>` must be specified
   --> $DIR/assoc_type_bounds2.rs:11:16
    |
 LL |     type Bar
diff --git a/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.rs b/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.rs
new file mode 100644
index 00000000000..1f4e1bf653a
--- /dev/null
+++ b/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.rs
@@ -0,0 +1,15 @@
+trait Sup<T> {
+    type Assoc: Default;
+}
+
+impl<T: Default> Sup<T> for () {
+    type Assoc = T;
+}
+impl<T: Default, U: Default> Dyn<T, U> for () {}
+
+trait Dyn<A, B>: Sup<A, Assoc = A> + Sup<B> {}
+
+fn main() {
+    let q: <dyn Dyn<i32, u32> as Sup<u32>>::Assoc = Default::default();
+    //~^ ERROR the value of the associated type `Assoc` in `Sup<u32>` must be specified
+}
diff --git a/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.stderr b/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.stderr
new file mode 100644
index 00000000000..3d89b52d522
--- /dev/null
+++ b/tests/ui/dyn-compatibility/require-assoc-for-all-super-substs.stderr
@@ -0,0 +1,12 @@
+error[E0191]: the value of the associated type `Assoc` in `Sup<u32>` must be specified
+  --> $DIR/require-assoc-for-all-super-substs.rs:13:17
+   |
+LL |     type Assoc: Default;
+   |     ------------------- `Assoc` defined here
+...
+LL |     let q: <dyn Dyn<i32, u32> as Sup<u32>>::Assoc = Default::default();
+   |                 ^^^^^^^^^^^^^ help: specify the associated type: `Dyn<i32, u32, Assoc = Type>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0191`.
diff --git a/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr b/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr
index 08eb8cfac49..54bde98b57f 100644
--- a/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr
+++ b/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr
@@ -3,8 +3,7 @@ warning: anonymous parameters are deprecated and will be removed in the next edi
    |
 LL |       fn test(x: u32, (
    |  _____________________^
-LL | |
-LL | |
+...  |
 LL | |     )) {}
    | |_____^
    |
diff --git a/tests/ui/expr/if/if-let-arm-types.stderr b/tests/ui/expr/if/if-let-arm-types.stderr
index 285f5c4a6f2..0a8260f0fea 100644
--- a/tests/ui/expr/if/if-let-arm-types.stderr
+++ b/tests/ui/expr/if/if-let-arm-types.stderr
@@ -5,8 +5,7 @@ LL | /     if let Some(b) = None {
 LL | |
 LL | |         ()
    | |         -- expected because of this
-LL | |
-LL | |     } else {
+...  |
 LL | |         1
    | |         ^ expected `()`, found integer
 LL | |     };
diff --git a/tests/ui/extern/issue-116203.stderr b/tests/ui/extern/issue-116203.stderr
index 86e4cc763bd..51ef1421e3e 100644
--- a/tests/ui/extern/issue-116203.stderr
+++ b/tests/ui/extern/issue-116203.stderr
@@ -22,8 +22,7 @@ LL |   extern "C" {
 LL | /     thread_local! {
 LL | |       static FOO: u32 = 0;
    | |              ^^^ cannot have a body
-LL | |
-LL | |
+...  |
 LL | |     }
    | |_____- the invalid body
    |
diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.default.stderr
index 0c5b8a4d3b6..d0a25e28a76 100644
--- a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr
+++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.default.stderr
@@ -1,5 +1,5 @@
 error[E0658]: `*const Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
-  --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:8:18
+  --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:11:18
    |
 LL |     fn foo(self: *const Self) {}
    |                  ^^^^^^^^^^^
@@ -10,7 +10,7 @@ LL |     fn foo(self: *const Self) {}
    = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `*mut Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
-  --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:12:18
+  --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:15:18
    |
 LL |     fn bar(self: *mut Self) {}
    |                  ^^^^^^^^^
@@ -21,7 +21,7 @@ LL |     fn bar(self: *mut Self) {}
    = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
-  --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:2:18
+  --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:5:18
    |
 LL |     fn foo(self: *const Self);
    |                  ^^^^^^^^^^^
diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.feature.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.feature.stderr
new file mode 100644
index 00000000000..d0a25e28a76
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.feature.stderr
@@ -0,0 +1,36 @@
+error[E0658]: `*const Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
+  --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:11:18
+   |
+LL |     fn foo(self: *const Self) {}
+   |                  ^^^^^^^^^^^
+   |
+   = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
+   = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+
+error[E0658]: `*mut Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
+  --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:15:18
+   |
+LL |     fn bar(self: *mut Self) {}
+   |                  ^^^^^^^^^
+   |
+   = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
+   = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+
+error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
+  --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:5:18
+   |
+LL |     fn foo(self: *const Self);
+   |                  ^^^^^^^^^^^
+   |
+   = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
+   = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs
index 79ceb05662b..7ea1b875f79 100644
--- a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs
+++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs
@@ -1,3 +1,6 @@
+//@ revisions: default feature
+#![cfg_attr(feature, feature(arbitrary_self_types))]
+
 trait Foo {
     fn foo(self: *const Self); //~ ERROR `*const Self` cannot be used as the type of `self`
 }
diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr
index eb9e51a04c3..2150effc3b7 100644
--- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr
+++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Cell<&Self>`
 LL |     fn cell(self: Cell<&Self>);
    |                   ^^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or some type implementing `Receiver`
-   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.rs b/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.rs
new file mode 100644
index 00000000000..f6574b48120
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let x: impl Sized = ();
+    //~^ ERROR `impl Trait` is not allowed in the type of variable bindings
+}
diff --git a/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.stderr b/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.stderr
new file mode 100644
index 00000000000..58f058fb564
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-impl-trait-in-bindings.stderr
@@ -0,0 +1,14 @@
+error[E0562]: `impl Trait` is not allowed in the type of variable bindings
+  --> $DIR/feature-gate-impl-trait-in-bindings.rs:2:12
+   |
+LL |     let x: impl Sized = ();
+   |            ^^^^^^^^^^
+   |
+   = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/tests/ui/feature-gates/feature-gate-unsafe-binders.rs b/tests/ui/feature-gates/feature-gate-unsafe-binders.rs
new file mode 100644
index 00000000000..a2997ced4fa
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-unsafe-binders.rs
@@ -0,0 +1,7 @@
+#[cfg(any())]
+fn test() {
+    let x: unsafe<> ();
+    //~^ ERROR unsafe binder types are experimental
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-unsafe-binders.stderr b/tests/ui/feature-gates/feature-gate-unsafe-binders.stderr
new file mode 100644
index 00000000000..93997d6c14a
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-unsafe-binders.stderr
@@ -0,0 +1,13 @@
+error[E0658]: unsafe binder types are experimental
+  --> $DIR/feature-gate-unsafe-binders.rs:3:12
+   |
+LL |     let x: unsafe<> ();
+   |            ^^^^^^^^^^^
+   |
+   = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
+   = help: add `#![feature(unsafe_binders)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
index fe764ff4925..db8c5295a2d 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
@@ -54,11 +54,7 @@ LL |   #[inline]
    |   ^^^^^^^^^
 LL |
 LL | / mod inline {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |
 LL | | }
    | |_- not a function or closure
 
@@ -73,7 +69,6 @@ LL | |
 LL | |
 LL | |     mod inner { #![no_link] }
 ...  |
-LL | |
 LL | | }
    | |_- not an `extern crate` item
 
@@ -88,7 +83,6 @@ LL | |
 LL | |
 LL | |     mod inner { #![export_name="2200"] }
 ...  |
-LL | |     }
 LL | | }
    | |_- not a free function, impl method or static
 
@@ -101,9 +95,7 @@ LL |
 LL | / mod repr {
 LL | |
 LL | |     mod inner { #![repr(C)] }
-LL | |
 ...  |
-LL | |
 LL | | }
    | |_- not a struct, enum, or union
 
@@ -116,9 +108,7 @@ LL |
 LL | / mod repr_rust {
 LL | |
 LL | |     mod inner { #![repr(Rust)] }
-LL | |
 ...  |
-LL | |
 LL | | }
    | |_- not a struct, enum, or union
 
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index e43cef7c150..18fb75aafbb 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -227,9 +227,7 @@ LL |   #[no_mangle]
 LL | / mod no_mangle {
 LL | |
 LL | |     mod inner { #![no_mangle] }
-LL | |
 ...  |
-LL | |     }
 LL | | }
    | |_- not a free function, impl method or static
    |
@@ -270,7 +268,6 @@ LL | |
 LL | |
 LL | |     mod inner { #![cold] }
 ...  |
-LL | |
 LL | | }
    | |_- not a function definition
    |
@@ -287,7 +284,6 @@ LL | |
 LL | |
 LL | |     #[link_name = "1900"]
 ...  |
-LL | |
 LL | | }
    | |_- not a foreign function or static
    |
@@ -304,7 +300,6 @@ LL | |
 LL | |
 LL | |     mod inner { #![link_section="1800"] }
 ...  |
-LL | |
 LL | | }
    | |_- not a function or static
    |
@@ -321,7 +316,6 @@ LL | |
 LL | |
 LL | |     mod inner { #![link()] }
 ...  |
-LL | |
 LL | | }
    | |_- not an `extern` block
    |
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-derive.stderr b/tests/ui/feature-gates/issue-43106-gating-of-derive.stderr
index 4dee7a00544..5df3e9e73fe 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-derive.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-derive.stderr
@@ -6,8 +6,6 @@ LL |   #[derive(Debug)]
 LL |
 LL | / mod derive {
 LL | |     mod inner { #![derive(Debug)] }
-LL | |
-LL | |
 ...  |
 LL | |     impl S { }
 LL | | }
diff --git a/tests/ui/for/for-else-err.stderr b/tests/ui/for/for-else-err.stderr
index bd49dc47244..a872cde5cac 100644
--- a/tests/ui/for/for-else-err.stderr
+++ b/tests/ui/for/for-else-err.stderr
@@ -6,8 +6,7 @@ LL |       for _ in 0..1 {
 LL |
 LL |       } else {
    |  _______^
-LL | |
-LL | |
+...  |
 LL | |     }
    | |_____^
    |
diff --git a/tests/ui/for/for-else-let-else-err.stderr b/tests/ui/for/for-else-let-else-err.stderr
index bb6558739ba..22432a18bbb 100644
--- a/tests/ui/for/for-else-let-else-err.stderr
+++ b/tests/ui/for/for-else-let-else-err.stderr
@@ -6,8 +6,7 @@ LL |       let _ = for _ in 0..1 {
 LL |
 LL |       } else {
    |  _______^
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/generic-associated-types/collectivity-regression.stderr b/tests/ui/generic-associated-types/collectivity-regression.stderr
index 0c395a1664f..1c081ac644a 100644
--- a/tests/ui/generic-associated-types/collectivity-regression.stderr
+++ b/tests/ui/generic-associated-types/collectivity-regression.stderr
@@ -2,10 +2,7 @@ error: `T` does not live long enough
   --> $DIR/collectivity-regression.rs:13:5
    |
 LL | /     || {
-LL | |
-LL | |         //
-LL | |         // FIXME(#98437). This regressed at some point and
-LL | |         // probably should work.
+...  |
 LL | |         let _x = x;
 LL | |     };
    | |_____^
diff --git a/tests/ui/generics/overlapping-errors-span-issue-123861.rs b/tests/ui/generics/overlapping-errors-span-issue-123861.rs
new file mode 100644
index 00000000000..e0a27f68748
--- /dev/null
+++ b/tests/ui/generics/overlapping-errors-span-issue-123861.rs
@@ -0,0 +1,8 @@
+fn mainIterator<_ = _> {}
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR   missing parameters for function definition
+//~| ERROR   defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions [invalid_type_param_default]
+//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+//~| ERROR   the placeholder `_` is not allowed within types on item signatures for functions [E0121]
+
+fn main() {}
diff --git a/tests/ui/generics/overlapping-errors-span-issue-123861.stderr b/tests/ui/generics/overlapping-errors-span-issue-123861.stderr
new file mode 100644
index 00000000000..e0a49343b0e
--- /dev/null
+++ b/tests/ui/generics/overlapping-errors-span-issue-123861.stderr
@@ -0,0 +1,52 @@
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/overlapping-errors-span-issue-123861.rs:1:17
+   |
+LL | fn mainIterator<_ = _> {}
+   |                 ^ expected identifier, found reserved identifier
+
+error: missing parameters for function definition
+  --> $DIR/overlapping-errors-span-issue-123861.rs:1:23
+   |
+LL | fn mainIterator<_ = _> {}
+   |                       ^
+   |
+help: add a parameter list
+   |
+LL | fn mainIterator<_ = _>() {}
+   |                       ++
+
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/overlapping-errors-span-issue-123861.rs:1:17
+   |
+LL | fn mainIterator<_ = _> {}
+   |                 ^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+   = note: `#[deny(invalid_type_param_default)]` on by default
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/overlapping-errors-span-issue-123861.rs:1:21
+   |
+LL | fn mainIterator<_ = _> {}
+   |                     ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | fn mainIterator<T = T> {}
+   |                 ~   ~
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
+Future incompatibility report: Future breakage diagnostic:
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/overlapping-errors-span-issue-123861.rs:1:17
+   |
+LL | fn mainIterator<_ = _> {}
+   |                 ^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+   = note: `#[deny(invalid_type_param_default)]` on by default
+
diff --git a/tests/ui/anonymous-higher-ranked-lifetime.rs b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.rs
index 898fe22fa23..8d8d0e71067 100644
--- a/tests/ui/anonymous-higher-ranked-lifetime.rs
+++ b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.rs
@@ -1,3 +1,9 @@
+//! Diagnostics test to check that higher-ranked lifetimes are properly named when being pretty
+//! printed in diagnostics.
+//!
+//! Issue: <https://github.com/rust-lang/rust/issues/44887>
+//! PR: <https://github.com/rust-lang/rust/pull/44888>
+
 fn main() {
     f1(|_: (), _: ()| {}); //~ ERROR type mismatch
     f2(|_: (), _: ()| {}); //~ ERROR type mismatch
diff --git a/tests/ui/anonymous-higher-ranked-lifetime.stderr b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.stderr
index c28d856ad55..7e0cdba6ff2 100644
--- a/tests/ui/anonymous-higher-ranked-lifetime.stderr
+++ b/tests/ui/higher-ranked/anonymous-higher-ranked-lifetime.stderr
@@ -1,5 +1,5 @@
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
    |
 LL |     f1(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -10,7 +10,7 @@ LL |     f1(|_: (), _: ()| {});
    = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `f1`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:16:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:22:25
    |
 LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
    |                         ^^^^^^^^^^^^ required by this bound in `f1`
@@ -20,7 +20,7 @@ LL |     f1(|_: &(), _: &()| {});
    |            +       +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5
    |
 LL |     f2(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -31,7 +31,7 @@ LL |     f2(|_: (), _: ()| {});
    = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `f2`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:17:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:23:25
    |
 LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2`
@@ -41,7 +41,7 @@ LL |     f2(|_: &(), _: &()| {});
    |            +       +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
    |
 LL |     f3(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -52,7 +52,7 @@ LL |     f3(|_: (), _: ()| {});
    = note: expected closure signature `for<'a> fn(&(), &'a ()) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `f3`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:18:29
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:24:29
    |
 LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
    |                             ^^^^^^^^^^^^^^^ required by this bound in `f3`
@@ -62,7 +62,7 @@ LL |     f3(|_: &(), _: &()| {});
    |            +       +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5
    |
 LL |     f4(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -73,7 +73,7 @@ LL |     f4(|_: (), _: ()| {});
    = note: expected closure signature `for<'a, 'r> fn(&'a (), &'r ()) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `f4`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:19:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:25:25
    |
 LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4`
@@ -83,7 +83,7 @@ LL |     f4(|_: &(), _: &()| {});
    |            +       +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
    |
 LL |     f5(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -94,7 +94,7 @@ LL |     f5(|_: (), _: ()| {});
    = note: expected closure signature `for<'r> fn(&'r (), &'r ()) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `f5`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:20:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:26:25
    |
 LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5`
@@ -104,7 +104,7 @@ LL |     f5(|_: &(), _: &()| {});
    |            +       +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:13:5
    |
 LL |     g1(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -115,7 +115,7 @@ LL |     g1(|_: (), _: ()| {});
    = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `g1`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:23:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:29:25
    |
 LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g1`
@@ -125,7 +125,7 @@ LL |     g1(|_: &(), _: ()| {});
    |            +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5
    |
 LL |     g2(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -136,7 +136,7 @@ LL |     g2(|_: (), _: ()| {});
    = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `g2`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:24:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:30:25
    |
 LL | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
    |                         ^^^^^^^^^^^^^^^^ required by this bound in `g2`
@@ -146,7 +146,7 @@ LL |     g2(|_: &(), _: ()| {});
    |            +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:15:5
    |
 LL |     g3(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -157,7 +157,7 @@ LL |     g3(|_: (), _: ()| {});
    = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `g3`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:25:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:31:25
    |
 LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g3`
@@ -167,7 +167,7 @@ LL |     g3(|_: &(), _: ()| {});
    |            +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5
    |
 LL |     g4(|_: (), _: ()| {});
    |     ^^^--------------^^^^
@@ -178,7 +178,7 @@ LL |     g4(|_: (), _: ()| {});
    = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _`
               found closure signature `fn((), ()) -> _`
 note: required by a bound in `g4`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:26:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:32:25
    |
 LL | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g4`
@@ -188,7 +188,7 @@ LL |     g4(|_: &(), _: ()| {});
    |            +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:17:5
    |
 LL |     h1(|_: (), _: (), _: (), _: ()| {});
    |     ^^^----------------------------^^^^
@@ -199,7 +199,7 @@ LL |     h1(|_: (), _: (), _: (), _: ()| {});
    = note: expected closure signature `for<'a, 'b> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'b (), for<'a, 'b> fn(&'a (), &'b ())) -> _`
               found closure signature `fn((), (), (), ()) -> _`
 note: required by a bound in `h1`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:29:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:35:25
    |
 LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h1`
@@ -209,7 +209,7 @@ LL |     h1(|_: &(), _: (), _: &(), _: ()| {});
    |            +              +
 
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5
    |
 LL |     h2(|_: (), _: (), _: (), _: ()| {});
    |     ^^^----------------------------^^^^
@@ -220,7 +220,7 @@ LL |     h2(|_: (), _: (), _: (), _: ()| {});
    = note: expected closure signature `for<'a, 't0> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'t0 (), for<'a, 'b> fn(&'a (), &'b ())) -> _`
               found closure signature `fn((), (), (), ()) -> _`
 note: required by a bound in `h2`
-  --> $DIR/anonymous-higher-ranked-lifetime.rs:30:25
+  --> $DIR/anonymous-higher-ranked-lifetime.rs:36:25
    |
 LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2`
diff --git a/tests/ui/impl-trait/in-bindings/bad-nesting.rs b/tests/ui/impl-trait/in-bindings/bad-nesting.rs
new file mode 100644
index 00000000000..7f4b44cc691
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/bad-nesting.rs
@@ -0,0 +1,10 @@
+#![feature(impl_trait_in_bindings)]
+
+trait Foo<T> {}
+
+impl Foo<()> for () {}
+
+fn main() {
+    let x: impl Foo<impl Sized> = ();
+    //~^ ERROR nested `impl Trait` is not allowed
+}
diff --git a/tests/ui/impl-trait/in-bindings/bad-nesting.stderr b/tests/ui/impl-trait/in-bindings/bad-nesting.stderr
new file mode 100644
index 00000000000..d82ce733254
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/bad-nesting.stderr
@@ -0,0 +1,12 @@
+error[E0666]: nested `impl Trait` is not allowed
+  --> $DIR/bad-nesting.rs:8:21
+   |
+LL |     let x: impl Foo<impl Sized> = ();
+   |            ---------^^^^^^^^^^-
+   |            |        |
+   |            |        nested `impl Trait` here
+   |            outer `impl Trait`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0666`.
diff --git a/tests/ui/impl-trait/in-bindings/escaping-bound-var.rs b/tests/ui/impl-trait/in-bindings/escaping-bound-var.rs
new file mode 100644
index 00000000000..b57fef9be21
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/escaping-bound-var.rs
@@ -0,0 +1,14 @@
+#![feature(impl_trait_in_bindings)]
+
+trait Foo<'a> {
+    type Out;
+}
+
+impl<'a> Foo<'a> for () {
+    type Out = ();
+}
+
+fn main() {
+    let x: &dyn for<'a> Foo<'a, Out = impl Sized + 'a> = &();
+    //~^ ERROR cannot capture late-bound lifetime in `impl Trait` in binding
+}
diff --git a/tests/ui/impl-trait/in-bindings/escaping-bound-var.stderr b/tests/ui/impl-trait/in-bindings/escaping-bound-var.stderr
new file mode 100644
index 00000000000..640f6f36927
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/escaping-bound-var.stderr
@@ -0,0 +1,8 @@
+error: cannot capture late-bound lifetime in `impl Trait` in binding
+  --> $DIR/escaping-bound-var.rs:12:52
+   |
+LL |     let x: &dyn for<'a> Foo<'a, Out = impl Sized + 'a> = &();
+   |                     -- lifetime defined here       ^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/impl-trait/in-bindings/lifetime-failure.rs b/tests/ui/impl-trait/in-bindings/lifetime-failure.rs
new file mode 100644
index 00000000000..df685c36c43
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/lifetime-failure.rs
@@ -0,0 +1,12 @@
+#![feature(impl_trait_in_bindings)]
+
+trait Static: 'static {}
+impl<T: 'static> Static for T {}
+
+struct W<T>(T);
+
+fn main() {
+    let local = 0;
+    let _: W<impl Static> = W(&local);
+    //~^ ERROR `local` does not live long enough
+}
diff --git a/tests/ui/impl-trait/in-bindings/lifetime-failure.stderr b/tests/ui/impl-trait/in-bindings/lifetime-failure.stderr
new file mode 100644
index 00000000000..189efcbca87
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/lifetime-failure.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `local` does not live long enough
+  --> $DIR/lifetime-failure.rs:10:31
+   |
+LL |     let local = 0;
+   |         ----- binding `local` declared here
+LL |     let _: W<impl Static> = W(&local);
+   |            --------------     ^^^^^^ borrowed value does not live long enough
+   |            |
+   |            type annotation requires that `local` is borrowed for `'static`
+LL |
+LL | }
+   | - `local` dropped here while still borrowed
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.rs b/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.rs
new file mode 100644
index 00000000000..7e5d2cf18bd
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.rs
@@ -0,0 +1,10 @@
+#![feature(impl_trait_in_bindings)]
+
+trait Static {}
+impl<T: 'static> Static for T {}
+
+fn main() {
+    let local = 0;
+    let _: impl IntoIterator<Item = impl Static> = [&local];
+    //~^ ERROR `local` does not live long enough
+}
diff --git a/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.stderr b/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.stderr
new file mode 100644
index 00000000000..c0326b37949
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/nesting-lifetime-failure.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `local` does not live long enough
+  --> $DIR/nesting-lifetime-failure.rs:8:53
+   |
+LL |     let local = 0;
+   |         ----- binding `local` declared here
+LL |     let _: impl IntoIterator<Item = impl Static> = [&local];
+   |            -------------------------------------    ^^^^^^ borrowed value does not live long enough
+   |            |
+   |            type annotation requires that `local` is borrowed for `'static`
+LL |
+LL | }
+   | - `local` dropped here while still borrowed
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/impl-trait/in-bindings/nesting.rs b/tests/ui/impl-trait/in-bindings/nesting.rs
new file mode 100644
index 00000000000..51ff42bcafe
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/nesting.rs
@@ -0,0 +1,7 @@
+//@ check-pass
+
+#![feature(impl_trait_in_bindings)]
+
+fn main() {
+    let _: impl IntoIterator<Item = impl Sized> = ["hello", " world"];
+}
diff --git a/tests/ui/impl-trait/in-bindings/simple.rs b/tests/ui/impl-trait/in-bindings/simple.rs
new file mode 100644
index 00000000000..8052f5a1880
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/simple.rs
@@ -0,0 +1,10 @@
+//@ check-pass
+
+#![feature(impl_trait_in_bindings)]
+
+trait Foo {}
+impl Foo for () {}
+
+fn main() {
+    let x: impl Foo = ();
+}
diff --git a/tests/ui/impl-trait/in-bindings/trait-failure.rs b/tests/ui/impl-trait/in-bindings/trait-failure.rs
new file mode 100644
index 00000000000..e4052437f2f
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/trait-failure.rs
@@ -0,0 +1,13 @@
+#![feature(impl_trait_in_bindings)]
+
+trait Foo {}
+
+struct W<T>(T);
+impl<T> Foo for W<T> where T: Foo {}
+
+fn main() {
+    let x: impl Foo = W(());
+    //~^ ERROR the trait bound `(): Foo` is not satisfied
+    let x: W<impl Foo> = W(());
+    //~^ ERROR the trait bound `(): Foo` is not satisfied
+}
diff --git a/tests/ui/impl-trait/in-bindings/trait-failure.stderr b/tests/ui/impl-trait/in-bindings/trait-failure.stderr
new file mode 100644
index 00000000000..332cefd796d
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/trait-failure.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `(): Foo` is not satisfied
+  --> $DIR/trait-failure.rs:9:17
+   |
+LL |     let x: impl Foo = W(());
+   |                 ^^^ the trait `Foo` is not implemented for `()`
+   |
+   = help: the trait `Foo` is implemented for `W<T>`
+note: required for `W<()>` to implement `Foo`
+  --> $DIR/trait-failure.rs:6:9
+   |
+LL | impl<T> Foo for W<T> where T: Foo {}
+   |         ^^^     ^^^^          --- unsatisfied trait bound introduced here
+
+error[E0277]: the trait bound `(): Foo` is not satisfied
+  --> $DIR/trait-failure.rs:11:19
+   |
+LL |     let x: W<impl Foo> = W(());
+   |                   ^^^ the trait `Foo` is not implemented for `()`
+   |
+   = help: the trait `Foo` is implemented for `W<T>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
index 1ddbd75142f..e38e18857ef 100644
--- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
+++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
@@ -2,9 +2,6 @@ error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
   --> $DIR/false-positive-predicate-entailment-error.rs:36:5
    |
 LL | /     fn autobatch<F>(self) -> impl Trait
-LL | |
-LL | |
-LL | |
 ...  |
 LL | |     where
 LL | |         F: Callback<Self::CallbackArg>,
@@ -52,9 +49,6 @@ error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
   --> $DIR/false-positive-predicate-entailment-error.rs:36:5
    |
 LL | /     fn autobatch<F>(self) -> impl Trait
-LL | |
-LL | |
-LL | |
 ...  |
 LL | |     where
 LL | |         F: Callback<Self::CallbackArg>,
@@ -105,9 +99,6 @@ error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
   --> $DIR/false-positive-predicate-entailment-error.rs:36:5
    |
 LL | /     fn autobatch<F>(self) -> impl Trait
-LL | |
-LL | |
-LL | |
 ...  |
 LL | |     where
 LL | |         F: Callback<Self::CallbackArg>,
diff --git a/tests/ui/impl-trait/issues/issue-54600.stderr b/tests/ui/impl-trait/issues/issue-54600.stderr
index c75c0fa0f05..02d60960233 100644
--- a/tests/ui/impl-trait/issues/issue-54600.stderr
+++ b/tests/ui/impl-trait/issues/issue-54600.stderr
@@ -5,6 +5,9 @@ LL |     let x: Option<impl Debug> = Some(44_u32);
    |                   ^^^^^^^^^^
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/issues/issue-54840.stderr b/tests/ui/impl-trait/issues/issue-54840.stderr
index de75256d5a9..805ea04f0bc 100644
--- a/tests/ui/impl-trait/issues/issue-54840.stderr
+++ b/tests/ui/impl-trait/issues/issue-54840.stderr
@@ -5,6 +5,9 @@ LL |     let j: &impl Add = &i;
    |             ^^^^^^^^
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/issues/issue-58504.stderr b/tests/ui/impl-trait/issues/issue-58504.stderr
index 8231732bba1..bc921d5cd2c 100644
--- a/tests/ui/impl-trait/issues/issue-58504.stderr
+++ b/tests/ui/impl-trait/issues/issue-58504.stderr
@@ -5,6 +5,9 @@ LL |     let gens: [impl Coroutine<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen()
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/issues/issue-58956.stderr b/tests/ui/impl-trait/issues/issue-58956.stderr
index 0c81c69def3..825777e4923 100644
--- a/tests/ui/impl-trait/issues/issue-58956.stderr
+++ b/tests/ui/impl-trait/issues/issue-58956.stderr
@@ -13,6 +13,9 @@ LL |     let x: Wrap<impl Lam> = Wrap(B);
    |                 ^^^^^^^^
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/issues/issue-70971.stderr b/tests/ui/impl-trait/issues/issue-70971.stderr
index 28c463cea85..10e5fffa430 100644
--- a/tests/ui/impl-trait/issues/issue-70971.stderr
+++ b/tests/ui/impl-trait/issues/issue-70971.stderr
@@ -5,6 +5,9 @@ LL |     let x : (impl Copy,) = (true,);
    |              ^^^^^^^^^
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/issues/issue-79099.stderr b/tests/ui/impl-trait/issues/issue-79099.stderr
index 96825eabec7..d7c0c494454 100644
--- a/tests/ui/impl-trait/issues/issue-79099.stderr
+++ b/tests/ui/impl-trait/issues/issue-79099.stderr
@@ -16,6 +16,9 @@ LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/issues/issue-84919.stderr b/tests/ui/impl-trait/issues/issue-84919.stderr
index 02d2ce28fb3..21dd355065d 100644
--- a/tests/ui/impl-trait/issues/issue-84919.stderr
+++ b/tests/ui/impl-trait/issues/issue-84919.stderr
@@ -5,6 +5,9 @@ LL |     let _x: impl Trait = ();
    |             ^^^^^^^^^^
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/issues/issue-87295.stderr b/tests/ui/impl-trait/issues/issue-87295.stderr
index 78274a056ec..31f3b2f5bf2 100644
--- a/tests/ui/impl-trait/issues/issue-87295.stderr
+++ b/tests/ui/impl-trait/issues/issue-87295.stderr
@@ -5,6 +5,9 @@ LL |     let _do_not_waste: Struct<impl Trait<Output = i32>> = Struct::new(());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr
index 13f50fcea7b..400df87ca3f 100644
--- a/tests/ui/impl-trait/where-allowed.stderr
+++ b/tests/ui/impl-trait/where-allowed.stderr
@@ -333,6 +333,9 @@ LL |     let _in_local_variable: impl Fn() = || {};
    |                             ^^^^^^^^^
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0562]: `impl Trait` is not allowed in closure return types
   --> $DIR/where-allowed.rs:253:46
diff --git a/tests/ui/issues/issue-18611.stderr b/tests/ui/issues/issue-18611.stderr
index 76848201f73..918654215b3 100644
--- a/tests/ui/issues/issue-18611.stderr
+++ b/tests/ui/issues/issue-18611.stderr
@@ -15,8 +15,7 @@ error[E0277]: the trait bound `isize: HasState` is not satisfied
    |
 LL |   fn add_state(op: <isize as HasState>::State) {
    |  ______________________________________________^
-LL | |
-LL | |
+...  |
 LL | | }
    | |_^ the trait `HasState` is not implemented for `isize`
    |
diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/issues/issue-28344.stderr
index d8febe71652..7bc965536e9 100644
--- a/tests/ui/issues/issue-28344.stderr
+++ b/tests/ui/issues/issue-28344.stderr
@@ -12,7 +12,7 @@ help: if this is a dyn-compatible trait, use `dyn`
 LL |     let x: u8 = <dyn BitXor>::bitor(0 as u8, 0 as u8);
    |                 ++++       +
 
-error[E0191]: the value of the associated type `Output` in `BitXor` must be specified
+error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be specified
   --> $DIR/issue-28344.rs:4:17
    |
 LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
@@ -31,7 +31,7 @@ help: if this is a dyn-compatible trait, use `dyn`
 LL |     let g = <dyn BitXor>::bitor;
    |             ++++       +
 
-error[E0191]: the value of the associated type `Output` in `BitXor` must be specified
+error[E0191]: the value of the associated type `Output` in `BitXor<_>` must be specified
   --> $DIR/issue-28344.rs:9:13
    |
 LL |     let g = BitXor::bitor;
diff --git a/tests/ui/issues/issue-51714.stderr b/tests/ui/issues/issue-51714.stderr
index e53e10afcaf..da3e3caea29 100644
--- a/tests/ui/issues/issue-51714.stderr
+++ b/tests/ui/issues/issue-51714.stderr
@@ -2,14 +2,10 @@ error[E0572]: return statement outside of function body
   --> $DIR/issue-51714.rs:6:13
    |
 LL | / fn main() {
-LL | |
-LL | |
-LL | |
-LL | |
+...  |
 LL | |     |_: [_; return || {}]| {};
    | |             ^^^^^^^^^^^^ the return is part of this body...
 ...  |
-LL | |
 LL | | }
    | |_- ...not the enclosing function body
 
@@ -17,14 +13,10 @@ error[E0572]: return statement outside of function body
   --> $DIR/issue-51714.rs:10:10
    |
 LL | / fn main() {
-LL | |
-LL | |
-LL | |
 ...  |
 LL | |     [(); return || {}];
    | |          ^^^^^^^^^^^^ the return is part of this body...
 ...  |
-LL | |
 LL | | }
    | |_- ...not the enclosing function body
 
@@ -32,14 +24,10 @@ error[E0572]: return statement outside of function body
   --> $DIR/issue-51714.rs:14:10
    |
 LL | / fn main() {
-LL | |
-LL | |
-LL | |
 ...  |
 LL | |     [(); return |ice| {}];
    | |          ^^^^^^^^^^^^^^^ the return is part of this body...
 ...  |
-LL | |
 LL | | }
    | |_- ...not the enclosing function body
 
@@ -47,14 +35,10 @@ error[E0572]: return statement outside of function body
   --> $DIR/issue-51714.rs:18:10
    |
 LL | / fn main() {
-LL | |
-LL | |
-LL | |
 ...  |
 LL | |     [(); return while let Some(n) = Some(0) {}];
    | |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body...
-LL | |
-LL | |
+...  |
 LL | | }
    | |_- ...not the enclosing function body
 
diff --git a/tests/ui/issues/issue-56806.stderr b/tests/ui/issues/issue-56806.stderr
index 4b0a59fe12d..ec50d863758 100644
--- a/tests/ui/issues/issue-56806.stderr
+++ b/tests/ui/issues/issue-56806.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Box<(dyn Trait + 'static)>`
 LL |     fn dyn_instead_of_self(self: Box<dyn Trait>);
    |                                  ^^^^^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or some type implementing `Receiver`
-   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.stderr b/tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.stderr
index 38014ecce75..3c19b68cffb 100644
--- a/tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.stderr
+++ b/tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.stderr
@@ -2,57 +2,61 @@ error[E0308]: mismatched types
   --> $DIR/issue-57741.rs:20:9
    |
 LL |     let y = match x {
-   |                   -
-   |                   |
-   |                   this expression has type `Box<T>`
-   |                   help: consider dereferencing the boxed value: `*x`
+   |                   - this expression has type `Box<T>`
 LL |         T::A(a) | T::B(a) => a,
    |         ^^^^^^^ expected `Box<T>`, found `T`
    |
    = note: expected struct `Box<T>`
                 found enum `T`
+help: consider dereferencing the boxed value
+   |
+LL |     let y = match *x {
+   |                   ~~
 
 error[E0308]: mismatched types
   --> $DIR/issue-57741.rs:20:19
    |
 LL |     let y = match x {
-   |                   -
-   |                   |
-   |                   this expression has type `Box<T>`
-   |                   help: consider dereferencing the boxed value: `*x`
+   |                   - this expression has type `Box<T>`
 LL |         T::A(a) | T::B(a) => a,
    |                   ^^^^^^^ expected `Box<T>`, found `T`
    |
    = note: expected struct `Box<T>`
                 found enum `T`
+help: consider dereferencing the boxed value
+   |
+LL |     let y = match *x {
+   |                   ~~
 
 error[E0308]: mismatched types
   --> $DIR/issue-57741.rs:27:9
    |
 LL |     let y = match x {
-   |                   -
-   |                   |
-   |                   this expression has type `Box<S>`
-   |                   help: consider dereferencing the boxed value: `*x`
+   |                   - this expression has type `Box<S>`
 LL |         S::A { a } | S::B { b: a } => a,
    |         ^^^^^^^^^^ expected `Box<S>`, found `S`
    |
    = note: expected struct `Box<S>`
                 found enum `S`
+help: consider dereferencing the boxed value
+   |
+LL |     let y = match *x {
+   |                   ~~
 
 error[E0308]: mismatched types
   --> $DIR/issue-57741.rs:27:22
    |
 LL |     let y = match x {
-   |                   -
-   |                   |
-   |                   this expression has type `Box<S>`
-   |                   help: consider dereferencing the boxed value: `*x`
+   |                   - this expression has type `Box<S>`
 LL |         S::A { a } | S::B { b: a } => a,
    |                      ^^^^^^^^^^^^^ expected `Box<S>`, found `S`
    |
    = note: expected struct `Box<S>`
                 found enum `S`
+help: consider dereferencing the boxed value
+   |
+LL |     let y = match *x {
+   |                   ~~
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/let-else/let-else-deref-coercion.stderr b/tests/ui/let-else/let-else-deref-coercion.stderr
index 143b838bac5..da8b1f4c48e 100644
--- a/tests/ui/let-else/let-else-deref-coercion.stderr
+++ b/tests/ui/let-else/let-else-deref-coercion.stderr
@@ -5,6 +5,11 @@ LL |         let Bar::Present(z) = self else {
    |             ^^^^^^^^^^^^^^^   ---- this expression has type `&mut Foo`
    |             |
    |             expected `Foo`, found `Bar`
+   |
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |         let Bar::Present(z) = &**self else {
+   |                               ~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/let-else-deref-coercion.rs:68:13
@@ -13,6 +18,11 @@ LL |         let Bar(z) = x;
    |             ^^^^^^   - this expression has type `&mut irrefutable::Foo`
    |             |
    |             expected `Foo`, found `Bar`
+   |
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |         let Bar(z) = &**x;
+   |                      ~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr
index e8c3ab00226..90572fed0ed 100644
--- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr
+++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr
@@ -2,9 +2,6 @@ error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
   --> $DIR/issue-76168-hr-outlives-3.rs:6:1
    |
 LL | / async fn wrapper<F>(f: F)
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | F:,
 LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
@@ -24,9 +21,6 @@ error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
   --> $DIR/issue-76168-hr-outlives-3.rs:6:1
    |
 LL | / async fn wrapper<F>(f: F)
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | F:,
 LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
@@ -38,9 +32,6 @@ error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
   --> $DIR/issue-76168-hr-outlives-3.rs:6:1
    |
 LL | / async fn wrapper<F>(f: F)
-LL | |
-LL | |
-LL | |
 ...  |
 LL | | F:,
 LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
diff --git a/tests/ui/lifetimes/issue-97194.stderr b/tests/ui/lifetimes/issue-97194.stderr
index 93bde285a99..345e21cb250 100644
--- a/tests/ui/lifetimes/issue-97194.stderr
+++ b/tests/ui/lifetimes/issue-97194.stderr
@@ -7,10 +7,7 @@ LL |       fn bget(&self, index: [usize; Self::DIM]) -> bool {
    |  ________^^^^___________________________________________-
    | |        |
    | |        cannot have a body
-LL | |
-LL | |
-LL | |
-LL | |         type T<'a> = &'a str;
+...  |
 LL | |     }
    | |_____- help: remove the invalid body: `;`
    |
diff --git a/tests/ui/lint/lints-in-foreign-macros.stderr b/tests/ui/lint/lints-in-foreign-macros.stderr
index f20e16287af..c0164bd00ff 100644
--- a/tests/ui/lint/lints-in-foreign-macros.stderr
+++ b/tests/ui/lint/lints-in-foreign-macros.stderr
@@ -34,7 +34,6 @@ LL | | #![warn(missing_docs)]
 LL | |
 LL | | #[macro_use]
 ...  |
-LL | |
 LL | | fn main() {}
    | |____________^
    |
diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr
index 20fb4a6432e..077837f4a6b 100644
--- a/tests/ui/lint/non-local-defs/consts.stderr
+++ b/tests/ui/lint/non-local-defs/consts.stderr
@@ -124,7 +124,6 @@ LL | |         impl Uto10 for Test {}
    | |              |         |
    | |              |         `Test` is not local
    | |              `Uto10` is not local
-LL | |
 ...  |
 LL | |     }];
    | |_____- move the `impl` block outside of this constant expression `<unnameable>` and up 2 bodies
diff --git a/tests/ui/lint/non-local-defs/weird-exprs.stderr b/tests/ui/lint/non-local-defs/weird-exprs.stderr
index ec3517140ef..5b7d1a83744 100644
--- a/tests/ui/lint/non-local-defs/weird-exprs.stderr
+++ b/tests/ui/lint/non-local-defs/weird-exprs.stderr
@@ -8,7 +8,6 @@ LL | |     impl Uto for *mut Test {}
    | |          |            |
    | |          |            `Test` is not local
    | |          `Uto` is not local
-LL | |
 ...  |
 LL | | }];
    | |_- move the `impl` block outside of this constant expression `<unnameable>`
@@ -26,7 +25,6 @@ LL | |         impl Uto for Test {}
    | |              |       |
    | |              |       `Test` is not local
    | |              `Uto` is not local
-LL | |
 ...  |
 LL | |     }
    | |_____- move the `impl` block outside of this constant expression `<unnameable>`
@@ -61,7 +59,6 @@ LL | |         impl Uto for &Test {}
    | |              |        |
    | |              |        `Test` is not local
    | |              `Uto` is not local
-LL | |
 ...  |
 LL | |     }];
    | |_____- move the `impl` block outside of this constant expression `<unnameable>` and up 2 bodies
@@ -78,7 +75,6 @@ LL | |         impl Uto for &(Test,) {}
    | |              |         |
    | |              |         `Test` is not local
    | |              `Uto` is not local
-LL | |
 ...  |
 LL | |     }]) {}
    | |_____- move the `impl` block outside of this constant expression `<unnameable>` and up 2 bodies
@@ -96,7 +92,6 @@ LL | |         impl Uto for &(Test,Test) {}
    | |              |         |    `Test` is not local
    | |              |         `Test` is not local
    | |              `Uto` is not local
-LL | |
 ...  |
 LL | |     }] { todo!() }
    | |_____- move the `impl` block outside of this constant expression `<unnameable>` and up 2 bodies
diff --git a/tests/ui/loops/dont-suggest-break-thru-item.stderr b/tests/ui/loops/dont-suggest-break-thru-item.stderr
index 642578ade60..e7ed7ae1501 100644
--- a/tests/ui/loops/dont-suggest-break-thru-item.stderr
+++ b/tests/ui/loops/dont-suggest-break-thru-item.stderr
@@ -4,8 +4,7 @@ error[E0308]: mismatched types
 LL | /             if true {
 LL | |                 Err(1)
    | |                 ^^^^^^ expected `()`, found `Result<_, {integer}>`
-LL | |
-LL | |
+...  |
 LL | |             }
    | |_____________- expected this to be `()`
    |
@@ -22,8 +21,7 @@ error[E0308]: mismatched types
 LL | /             if true {
 LL | |                 Err(1)
    | |                 ^^^^^^ expected `()`, found `Result<_, {integer}>`
-LL | |
-LL | |
+...  |
 LL | |             }
    | |_____________- expected this to be `()`
    |
diff --git a/tests/ui/loops/loop-else-err.stderr b/tests/ui/loops/loop-else-err.stderr
index c1cbd544afd..36ccd9c4047 100644
--- a/tests/ui/loops/loop-else-err.stderr
+++ b/tests/ui/loops/loop-else-err.stderr
@@ -6,8 +6,7 @@ LL |       loop {
 LL |
 LL |       } else {
    |  _______^
-LL | |
-LL | |
+...  |
 LL | |     }
    | |_____^
    |
diff --git a/tests/ui/loops/loop-else-let-else-err.stderr b/tests/ui/loops/loop-else-let-else-err.stderr
index 6ee77fb47af..b2d07d4b2b2 100644
--- a/tests/ui/loops/loop-else-let-else-err.stderr
+++ b/tests/ui/loops/loop-else-let-else-err.stderr
@@ -6,8 +6,7 @@ LL |       let _ = loop {
 LL |
 LL |       } else {
    |  _______^
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr
index 10e3fc92868..747d492999c 100644
--- a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr
+++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr
@@ -7,8 +7,7 @@ LL | |         0 => x,
    | |              - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
 LL | |         _ => y,
    | |              ^ one type is more general than the other
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____- `match` arms have incompatible types
    |
diff --git a/tests/ui/match/match-incompat-type-semi.stderr b/tests/ui/match/match-incompat-type-semi.stderr
index 008b1c1e93d..ca5336602c7 100644
--- a/tests/ui/match/match-incompat-type-semi.stderr
+++ b/tests/ui/match/match-incompat-type-semi.stderr
@@ -31,8 +31,7 @@ LL | |         0;
    | |         ||
    | |         |help: consider removing this semicolon
    | |         expected integer, found `()`
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____- `if` and `else` have incompatible types
 
diff --git a/tests/ui/match/match-type-err-first-arm.stderr b/tests/ui/match/match-type-err-first-arm.stderr
index 1cfe7ce1ed7..69f4e22e6ae 100644
--- a/tests/ui/match/match-type-err-first-arm.stderr
+++ b/tests/ui/match/match-type-err-first-arm.stderr
@@ -21,8 +21,7 @@ LL | |         12 => 'b',
    | |               --- this is found to be of type `char`
 LL | |         _ => 42,
    | |              ^^ expected `char`, found integer
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____- `match` arms have incompatible types
 
@@ -40,8 +39,7 @@ LL | |         6 => 'b',
 LL | |
 LL | |         _ => 42,
    | |              ^^ expected `char`, found integer
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____- `match` arms have incompatible types
 
@@ -55,8 +53,7 @@ LL | |             x
 LL | |         },
 LL | |         None => {}
    | |                 ^^ expected `u32`, found `()`
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____- `match` arms have incompatible types
 
diff --git a/tests/ui/never_type/diverging-place-match.stderr b/tests/ui/never_type/diverging-place-match.stderr
index 74e1bfa0a6b..14300c4df05 100644
--- a/tests/ui/never_type/diverging-place-match.stderr
+++ b/tests/ui/never_type/diverging-place-match.stderr
@@ -5,8 +5,7 @@ LL | /     unsafe {
 LL | |
 LL | |         let x: *const ! = 0 as _;
 LL | |         let _: ! = *x;
-LL | |         // Since `*x` "diverges" in HIR, but doesn't count as a read in MIR, this
-LL | |         // is unsound since we act as if it diverges but it doesn't.
+...  |
 LL | |     }
    | |_____^ expected `!`, found `()`
    |
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index ca7d187ac57..3c04cf300ad 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -30,10 +30,7 @@ LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
    |             |
    |             lifetime `'a` defined here
 LL | /     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
-LL | |
-LL | |
-LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get())
+...  |
 LL | |     });
    | |      ^
    | |      |
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index d11a64272a9..9f5762ccbfa 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -30,10 +30,7 @@ LL |   fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
    |             |
    |             lifetime `'a` defined here
 LL | /     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-LL | |
-LL | |
-LL | |         // Only works if 'x: 'y:
-LL | |         demand_y(x, y, x.get())
+...  |
 LL | |     });
    | |      ^
    | |      |
diff --git a/tests/ui/nll/snocat-regression.stderr b/tests/ui/nll/snocat-regression.stderr
index 135b6951537..ae61245290b 100644
--- a/tests/ui/nll/snocat-regression.stderr
+++ b/tests/ui/nll/snocat-regression.stderr
@@ -2,10 +2,7 @@ error: `S` does not live long enough
   --> $DIR/snocat-regression.rs:7:5
    |
 LL | /     || {
-LL | |
-LL | |         //
-LL | |         // FIXME(#98437). This regressed at some point and
-LL | |         // probably should work.
+...  |
 LL | |         let _x = link;
 LL | |     };
    | |_____^
diff --git a/tests/ui/or-patterns/missing-bindings.stderr b/tests/ui/or-patterns/missing-bindings.stderr
index 677b40a7f0d..6288cc58913 100644
--- a/tests/ui/or-patterns/missing-bindings.stderr
+++ b/tests/ui/or-patterns/missing-bindings.stderr
@@ -219,7 +219,6 @@ LL | |                 A(
 LL | |                     A(_, a) |
 LL | |                     B(b),
 ...  |
-LL | |
 LL | |             ) |
    | |_____________^ pattern doesn't bind `c`
 LL |               V3(c),
diff --git a/tests/ui/parser/as-precedence.rs b/tests/ui/parser/as-precedence.rs
new file mode 100644
index 00000000000..ca8328adb0e
--- /dev/null
+++ b/tests/ui/parser/as-precedence.rs
@@ -0,0 +1,18 @@
+//! Parser precedence test to help with [RFC 87 "Trait Bounds with Plus"][rfc-87], to check the
+//! precedence of the `as` operator in relation to some arithmetic bin-ops and parentheses.
+//!
+//! Editor's note: this test seems quite incomplete compared to what's possible nowadays. Maybe
+//! there's another set of tests whose coverage overshadows this test?
+//!
+//! [rfc-87]: https://rust-lang.github.io/rfcs/0087-trait-bounds-with-plus.html
+
+//@ run-pass
+
+#[allow(unused_parens)]
+fn main() {
+    assert_eq!(3 as usize * 3, 9);
+    assert_eq!(3 as (usize) * 3, 9);
+    assert_eq!(3 as (usize) / 3, 1);
+    assert_eq!(3 as usize + 3, 6);
+    assert_eq!(3 as (usize) + 3, 6);
+}
diff --git a/tests/ui/parser/brace-in-let-chain.rs b/tests/ui/parser/brace-in-let-chain.rs
index 1f34c73a2c3..2009bc88d9e 100644
--- a/tests/ui/parser/brace-in-let-chain.rs
+++ b/tests/ui/parser/brace-in-let-chain.rs
@@ -3,7 +3,7 @@
 #![feature(let_chains)]
 fn main() {
     if let () = ()
-        && let () = () { //~ERROR: found a `{` in the middle of a let-chain
+        && let () = () {
         && let () = ()
     {
     }
@@ -11,7 +11,7 @@ fn main() {
 
 fn quux() {
     while let () = ()
-        && let () = () { //~ERROR: found a `{` in the middle of a let-chain
+        && let () = () {
         && let () = ()
     {
     }
diff --git a/tests/ui/parser/brace-in-let-chain.stderr b/tests/ui/parser/brace-in-let-chain.stderr
index 913a34700df..12af95c2786 100644
--- a/tests/ui/parser/brace-in-let-chain.stderr
+++ b/tests/ui/parser/brace-in-let-chain.stderr
@@ -27,33 +27,5 @@ LL |     }
 LL | }
    |                                                     ^
 
-error: found a `{` in the middle of a let-chain
-  --> $DIR/brace-in-let-chain.rs:14:24
-   |
-LL |         && let () = () {
-   |                        ^
-LL |         && let () = ()
-   |         ------ you might have meant to continue the let-chain here
-   |
-help: consider removing this brace to parse the `let` as part of the same chain
-   |
-LL -         && let () = () {
-LL +         && let () = ()
-   |
-
-error: found a `{` in the middle of a let-chain
-  --> $DIR/brace-in-let-chain.rs:6:24
-   |
-LL |         && let () = () {
-   |                        ^
-LL |         && let () = ()
-   |         ------ you might have meant to continue the let-chain here
-   |
-help: consider removing this brace to parse the `let` as part of the same chain
-   |
-LL -         && let () = () {
-LL +         && let () = ()
-   |
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/circular_modules_main.stderr b/tests/ui/parser/circular_modules_main.stderr
index 2de70789358..e1780fe9fd9 100644
--- a/tests/ui/parser/circular_modules_main.stderr
+++ b/tests/ui/parser/circular_modules_main.stderr
@@ -4,22 +4,5 @@ error: circular modules: $DIR/circular_modules_main.rs -> $DIR/circular_modules_
 LL | mod circular_modules_main;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0425]: cannot find function `hi_str` in module `circular_modules_main`
-  --> $DIR/circular_modules_hello.rs:7:43
-   |
-LL |     println!("{}", circular_modules_main::hi_str());
-   |                                           ^^^^^^ not found in `circular_modules_main`
-   |
-help: consider importing this function
-   |
-LL + use hi_str;
-   |
-help: if you import `hi_str`, refer to it directly
-   |
-LL -     println!("{}", circular_modules_main::hi_str());
-LL +     println!("{}", hi_str());
-   |
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.rs b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.rs
index da1774acea5..41a7de03d4b 100644
--- a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.rs
+++ b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.rs
@@ -1,9 +1,11 @@
+// The diff marker detection was removed for this example, because it relied on
+// the lexer having a dependency on the parser, which was horrible.
+
 macro_rules! foo {
 <<<<<<< HEAD
-    //~^ ERROR encountered diff marker
     () {
 =======
     () { //
 >>>>>>> 7a4f13c blah blah blah
     }
-}
+} //~ this file contains an unclosed delimiter
diff --git a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr
index 927821ddfae..b33f2b5d1b8 100644
--- a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr
+++ b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr
@@ -1,23 +1,16 @@
-error: encountered diff marker
-  --> $DIR/unclosed-delims-in-macro.rs:2:1
+error: this file contains an unclosed delimiter
+  --> $DIR/unclosed-delims-in-macro.rs:11:48
    |
+LL | macro_rules! foo {
+   |                  - unclosed delimiter
 LL | <<<<<<< HEAD
-   | ^^^^^^^ between this marker and `=======` is the code that we're merging into
+LL |     () {
+   |        - this delimiter might not be properly closed...
 ...
-LL | =======
-   | ------- between this marker and `>>>>>>>` is the incoming code
-LL |     () { //
-LL | >>>>>>> 7a4f13c blah blah blah
-   | ^^^^^^^ this marker concludes the conflict region
-   |
-   = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts
-           to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers
-   = help: if you're having merge conflicts after pulling new code:
-           the top section is the code you already had and the bottom section is the remote code
-           if you're in the middle of a rebase:
-           the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased
-   = note: for an explanation on these markers from the `git` documentation:
-           visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>
+LL | }
+   | -                                             ^
+   | |
+   | ...as it matches this but it has different indentation
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/diff-markers/unclosed-delims.rs b/tests/ui/parser/diff-markers/unclosed-delims.rs
index 7d400c3827b..827c1eebb9d 100644
--- a/tests/ui/parser/diff-markers/unclosed-delims.rs
+++ b/tests/ui/parser/diff-markers/unclosed-delims.rs
@@ -1,18 +1,12 @@
+// The diff marker detection was removed for this example, because it relied on
+// the lexer having a dependency on the parser, which was horrible.
+
 mod tests {
     #[test]
 <<<<<<< HEAD
-//~^ ERROR encountered diff marker
-//~| NOTE between this marker and `=======`
-
-//~| NOTE conflict markers indicate that
-//~| HELP if you're having merge conflicts
-//~| NOTE for an explanation on these markers
-
     fn test1() {
 =======
-//~^ NOTE between this marker and `>>>>>>>`
     fn test2() {
 >>>>>>> 7a4f13c blah blah blah
-//~^ NOTE this marker concludes the conflict region
     }
-}
+} //~ this file contains an unclosed delimiter
diff --git a/tests/ui/parser/diff-markers/unclosed-delims.stderr b/tests/ui/parser/diff-markers/unclosed-delims.stderr
index 1eab96442b4..b2541aa47ba 100644
--- a/tests/ui/parser/diff-markers/unclosed-delims.stderr
+++ b/tests/ui/parser/diff-markers/unclosed-delims.stderr
@@ -1,23 +1,16 @@
-error: encountered diff marker
-  --> $DIR/unclosed-delims.rs:3:1
+error: this file contains an unclosed delimiter
+  --> $DIR/unclosed-delims.rs:12:48
    |
-LL | <<<<<<< HEAD
-   | ^^^^^^^ between this marker and `=======` is the code that we're merging into
+LL | mod tests {
+   |           - unclosed delimiter
 ...
-LL | =======
-   | ------- between this marker and `>>>>>>>` is the incoming code
+LL |     fn test1() {
+   |                - this delimiter might not be properly closed...
 ...
-LL | >>>>>>> 7a4f13c blah blah blah
-   | ^^^^^^^ this marker concludes the conflict region
-   |
-   = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts
-           to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers
-   = help: if you're having merge conflicts after pulling new code:
-           the top section is the code you already had and the bottom section is the remote code
-           if you're in the middle of a rebase:
-           the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased
-   = note: for an explanation on these markers from the `git` documentation:
-           visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>
+LL | }
+   | -                                             ^
+   | |
+   | ...as it matches this but it has different indentation
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/fn-arg-doc-comment.stderr b/tests/ui/parser/fn-arg-doc-comment.stderr
index c8d7e2efe79..1891c708903 100644
--- a/tests/ui/parser/fn-arg-doc-comment.stderr
+++ b/tests/ui/parser/fn-arg-doc-comment.stderr
@@ -30,15 +30,11 @@ note: function defined here
 LL |   pub fn f(
    |          ^
 LL | /     /// Comment
-LL | |
-LL | |
-LL | |
+...  |
 LL | |     id: u8,
    | |__________-
 LL | /     /// Other
-LL | |
-LL | |
-LL | |
+...  |
 LL | |     a: u8,
    | |_________-
 
diff --git a/tests/ui/privacy/effective_visibilities.stderr b/tests/ui/privacy/effective_visibilities.stderr
index 41d63532dea..6954279c05a 100644
--- a/tests/ui/privacy/effective_visibilities.stderr
+++ b/tests/ui/privacy/effective_visibilities.stderr
@@ -6,7 +6,6 @@ LL | | #![feature(rustc_attrs)]
 LL | |
 LL | | #[rustc_effective_visibility]
 ...  |
-LL | |
 LL | | fn main() {}
    | |____________^
 
diff --git a/tests/ui/privacy/effective_visibilities_invariants.stderr b/tests/ui/privacy/effective_visibilities_invariants.stderr
index 1c19afdcdba..64d0402f84e 100644
--- a/tests/ui/privacy/effective_visibilities_invariants.stderr
+++ b/tests/ui/privacy/effective_visibilities_invariants.stderr
@@ -16,7 +16,6 @@ LL | / #![feature(staged_api)]
 LL | |
 LL | | pub mod m {}
 ...  |
-LL | |
 LL | | fn main() {}
    | |____________^
 
diff --git a/tests/ui/privacy/issue-113860-1.stderr b/tests/ui/privacy/issue-113860-1.stderr
index c05452fb51c..dad9ebadf04 100644
--- a/tests/ui/privacy/issue-113860-1.stderr
+++ b/tests/ui/privacy/issue-113860-1.stderr
@@ -14,7 +14,6 @@ LL | |
 LL | |
 LL | | pub trait Trait {
 ...  |
-LL | |
 LL | | fn main() {}
    | |____________^
 
diff --git a/tests/ui/privacy/issue-113860-2.stderr b/tests/ui/privacy/issue-113860-2.stderr
index c53c490ca1e..9805c22dbdf 100644
--- a/tests/ui/privacy/issue-113860-2.stderr
+++ b/tests/ui/privacy/issue-113860-2.stderr
@@ -14,7 +14,6 @@ LL | |
 LL | |
 LL | | pub trait Trait {
 ...  |
-LL | |
 LL | | fn main() {}
    | |____________^
 
diff --git a/tests/ui/privacy/issue-113860.stderr b/tests/ui/privacy/issue-113860.stderr
index d813b740ac5..88efcae4a85 100644
--- a/tests/ui/privacy/issue-113860.stderr
+++ b/tests/ui/privacy/issue-113860.stderr
@@ -14,7 +14,6 @@ LL | |
 LL | |
 LL | | pub trait Trait {
 ...  |
-LL | |
 LL | | fn main() {}
    | |____________^
 
diff --git a/tests/ui/raw-ref-op/amp-raw-without-mut-const-is-a-normal-borrow.rs b/tests/ui/raw-ref-op/amp-raw-without-mut-const-is-a-normal-borrow.rs
new file mode 100644
index 00000000000..9360146a0fc
--- /dev/null
+++ b/tests/ui/raw-ref-op/amp-raw-without-mut-const-is-a-normal-borrow.rs
@@ -0,0 +1,30 @@
+//! The token sequence `&raw` *only* starts a raw borrow expr if it's immediately
+//! followed by either `const` or `mut`. If that's not the case, the `&` denotes
+//! the start of a normal borrow expr where `raw` is interpreted as a regular
+//! identifier and thus denotes the start of a path expr.
+//!
+//! This test ensures that we never commit too early/overzealously in the parser
+//! when encountering the sequence `&raw` (even during parse error recovery) so
+//! as not to regress preexisting code.
+
+//@ check-pass
+
+fn main() { // the odd formatting in here is intentional
+    let raw = 0;
+    let _ = &raw;
+
+    let raw = 0;
+    let local = 1;
+    let _: i32 = &raw *local;
+
+    let raw = |_| ();
+    let local = [0];
+    let () = &raw (local[0]);
+}
+
+macro_rules! check {
+    ($e:expr) => { compile_error!("expr"); };
+    (&raw $e:expr) => {};
+}
+
+check!(&raw local);
diff --git a/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr b/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr
index af9e7889821..0a8340545eb 100644
--- a/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr
+++ b/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr
@@ -7,8 +7,7 @@ LL | /     unsafe {
 LL | |
 LL | |         let x: *const ! = 0 as _;
 LL | |         &raw const *x;
-LL | |         // Since `*x` is `!`, HIR typeck used to think that it diverges
-LL | |         // and allowed the block to coerce to any value, leading to UB.
+...  |
 LL | |     }
    | |_____^ expected type parameter `T`, found `()`
    |
diff --git a/tests/ui/reachable/artificial-block.rs b/tests/ui/reachable/artificial-block.rs
new file mode 100644
index 00000000000..6d73ba1a972
--- /dev/null
+++ b/tests/ui/reachable/artificial-block.rs
@@ -0,0 +1,30 @@
+//! Check that we don't get compile errors on unreachable code after the `{ return 3; }` artificial
+//! block below. This test is run-pass to also exercise the codegen, but it might be possible to
+//! reduce to build-pass or even check-pass.
+//!
+//! This test was introduced as part of commit `a833f152baa17460e8414355e832d30d5161f8e8` which
+//! removes an "artificial block". See also commit `3d738e9e0634a4cd6239d1317bd7dad53be68dc8` for
+//! more elaboration, reproduced below (this is outdated for *today*'s rustc as of 2024-12-10, but
+//! is helpful to understand the original intention):
+//!
+//! > Return a fresh, unreachable context after ret, break, and cont
+//! >
+//! > This ensures we don't get compile errors on unreachable code (see
+//! > test/run-pass/artificial-block.rs for an example of sane code that wasn't compiling). In the
+//! > future, we might want to warn about non-trivial code appearing in an unreachable context,
+//! > and/or avoid generating unreachable code altogether (though I'm sure LLVM will weed it out as
+//! > well).
+//!
+//! Since then, `ret` became `return`, `int` became `isize` and `assert` became a macro.
+
+//@ run-pass
+
+fn f() -> isize {
+    {
+        return 3;
+    }
+}
+
+fn main() {
+    assert_eq!(f(), 3);
+}
diff --git a/tests/ui/resolve/parse-error-resolve.rs b/tests/ui/resolve/parse-error-resolve.rs
new file mode 100644
index 00000000000..1e0772648af
--- /dev/null
+++ b/tests/ui/resolve/parse-error-resolve.rs
@@ -0,0 +1,7 @@
+mod parse_error;
+use parse_error::Canonical; // ok, `parse_error.rs` had parse errors
+
+fn main() {
+    let _ = "" + 1; //~ ERROR E0369
+    parse_error::Canonical.foo(); // ok, `parse_error.rs` had parse errors
+}
diff --git a/tests/ui/resolve/parse-error-resolve.stderr b/tests/ui/resolve/parse-error-resolve.stderr
new file mode 100644
index 00000000000..30475aa0ee6
--- /dev/null
+++ b/tests/ui/resolve/parse-error-resolve.stderr
@@ -0,0 +1,22 @@
+error: expected one of `+`, `,`, `::`, `=`, or `>`, found `From`
+  --> $DIR/parse_error.rs:2:46
+   |
+LL | impl<S: Into<std::borrow::Cow<'static, str>> From<S> for Canonical {
+   |                                              ^^^^ expected one of `+`, `,`, `::`, `=`, or `>`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | impl<S: Into<std::borrow::Cow<'static, str>>> From<S> for Canonical {
+   |                                             +
+
+error[E0369]: cannot add `{integer}` to `&str`
+  --> $DIR/parse-error-resolve.rs:5:16
+   |
+LL |     let _ = "" + 1;
+   |             -- ^ - {integer}
+   |             |
+   |             &str
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/resolve/parse_error.rs b/tests/ui/resolve/parse_error.rs
new file mode 100644
index 00000000000..4cd025e1edf
--- /dev/null
+++ b/tests/ui/resolve/parse_error.rs
@@ -0,0 +1,5 @@
+struct Canonical;
+impl<S: Into<std::borrow::Cow<'static, str>> From<S> for Canonical { //~ ERROR expected
+    fn foo() {}
+}
+fn bar() {}
diff --git a/tests/ui/resolve/parse_error.stderr b/tests/ui/resolve/parse_error.stderr
new file mode 100644
index 00000000000..f764f08875f
--- /dev/null
+++ b/tests/ui/resolve/parse_error.stderr
@@ -0,0 +1,13 @@
+error: expected one of `+`, `,`, `::`, `=`, or `>`, found `From`
+  --> $DIR/parse_error.rs:2:46
+   |
+LL | impl<S: Into<std::borrow::Cow<'static, str>> From<S> for Canonical {
+   |                                              ^^^^ expected one of `+`, `,`, `::`, `=`, or `>`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | impl<S: Into<std::borrow::Cow<'static, str>>> From<S> for Canonical {
+   |                                             +
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/return/issue-86188-return-not-in-fn-body.stderr b/tests/ui/return/issue-86188-return-not-in-fn-body.stderr
index 4f938670e5e..abbcc21141e 100644
--- a/tests/ui/return/issue-86188-return-not-in-fn-body.stderr
+++ b/tests/ui/return/issue-86188-return-not-in-fn-body.stderr
@@ -15,8 +15,7 @@ LL | /     fn bar() {
 LL | |
 LL | |         [(); return];
    | |              ^^^^^^ the return is part of this body...
-LL | |
-LL | |
+...  |
 LL | |     }
    | |_____- ...not the enclosing function body
 
@@ -27,8 +26,7 @@ LL | /     fn foo() {
 LL | |
 LL | |         [(); return];
    | |              ^^^^^^ the return is part of this body...
-LL | |
-LL | |
+...  |
 LL | |     }
    | |_____- ...not the enclosing function body
 
diff --git a/tests/ui/return/return-match-array-const.stderr b/tests/ui/return/return-match-array-const.stderr
index 85a733adfee..c2a0ada7098 100644
--- a/tests/ui/return/return-match-array-const.stderr
+++ b/tests/ui/return/return-match-array-const.stderr
@@ -2,13 +2,10 @@ error[E0572]: return statement outside of function body
   --> $DIR/return-match-array-const.rs:5:10
    |
 LL | / fn main() {
-LL | |
-LL | |
-LL | |
+...  |
 LL | |     [(); return match 0 { n => n }];
    | |          ^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body...
 ...  |
-LL | |
 LL | | }
    | |_- ...not the enclosing function body
 
@@ -16,14 +13,10 @@ error[E0572]: return statement outside of function body
   --> $DIR/return-match-array-const.rs:9:10
    |
 LL | / fn main() {
-LL | |
-LL | |
-LL | |
 ...  |
 LL | |     [(); return match 0 { 0 => 0 }];
    | |          ^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body...
 ...  |
-LL | |
 LL | | }
    | |_- ...not the enclosing function body
 
@@ -31,14 +24,10 @@ error[E0572]: return statement outside of function body
   --> $DIR/return-match-array-const.rs:13:10
    |
 LL | / fn main() {
-LL | |
-LL | |
-LL | |
 ...  |
 LL | |     [(); return match () { 'a' => 0, _ => 0 }];
    | |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body...
 ...  |
-LL | |
 LL | | }
    | |_- ...not the enclosing function body
 
diff --git a/tests/ui/return/tail-expr-as-potential-return.stderr b/tests/ui/return/tail-expr-as-potential-return.stderr
index 635a9e06633..756de2b5a16 100644
--- a/tests/ui/return/tail-expr-as-potential-return.stderr
+++ b/tests/ui/return/tail-expr-as-potential-return.stderr
@@ -4,8 +4,7 @@ error[E0308]: mismatched types
 LL | /     if x {
 LL | |         Err(42)
    | |         ^^^^^^^ expected `()`, found `Result<_, {integer}>`
-LL | |
-LL | |
+...  |
 LL | |     }
    | |_____- expected this to be `()`
    |
@@ -22,8 +21,7 @@ error[E0308]: mismatched types
 LL | /     if true {
 LL | |         1i32
    | |         ^^^^ expected `()`, found `i32`
-LL | |
-LL | |
+...  |
 LL | |     }
    | |_____- expected this to be `()`
    |
@@ -38,8 +36,7 @@ error[E0308]: mismatched types
 LL | /     if x {
 LL | |         Err(42)
    | |         ^^^^^^^ expected `()`, found `Result<_, {integer}>`
-LL | |
-LL | |
+...  |
 LL | |     }
    | |_____- expected this to be `()`
    |
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
index cceb3bddef4..874b32346af 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
@@ -4,9 +4,7 @@ error: extern blocks must be unsafe
 LL | / extern "C" {
 LL | |
 LL | |     safe static TEST1: i32;
-LL | |
-LL | |     safe fn test1(i: i32);
-LL | |
+...  |
 LL | | }
    | |_^
 
diff --git a/tests/ui/self/arbitrary-self-opaque.stderr b/tests/ui/self/arbitrary-self-opaque.stderr
index 0469aca27dc..c75165d9f8e 100644
--- a/tests/ui/self/arbitrary-self-opaque.stderr
+++ b/tests/ui/self/arbitrary-self-opaque.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar`
 LL |     fn foo(self: Bar) {}
    |                  ^^^
    |
-   = note: type of `self` must be `Self` or some type implementing `Receiver`
-   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error: item does not constrain `Bar::{opaque#0}`, but has it in its signature
   --> $DIR/arbitrary-self-opaque.rs:7:8
diff --git a/tests/ui/self/arbitrary_self_types_nonnull.rs b/tests/ui/self/arbitrary_self_types_nonnull.rs
new file mode 100644
index 00000000000..ab1589b956e
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_nonnull.rs
@@ -0,0 +1,13 @@
+#![feature(arbitrary_self_types)]
+
+struct A;
+
+impl A {
+    fn m(self: std::ptr::NonNull<Self>) {}
+    //~^ ERROR: invalid `self` parameter type
+    fn n(self: &std::ptr::NonNull<Self>) {}
+    //~^ ERROR: invalid `self` parameter type
+}
+
+fn main() {
+}
diff --git a/tests/ui/self/arbitrary_self_types_nonnull.stderr b/tests/ui/self/arbitrary_self_types_nonnull.stderr
new file mode 100644
index 00000000000..5ebe58b4e48
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_nonnull.stderr
@@ -0,0 +1,23 @@
+error[E0307]: invalid `self` parameter type: `NonNull<A>`
+  --> $DIR/arbitrary_self_types_nonnull.rs:6:16
+   |
+LL |     fn m(self: std::ptr::NonNull<Self>) {}
+   |                ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: `NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver`
+
+error[E0307]: invalid `self` parameter type: `&NonNull<A>`
+  --> $DIR/arbitrary_self_types_nonnull.rs:8:16
+   |
+LL |     fn n(self: &std::ptr::NonNull<Self>) {}
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: `NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/self/arbitrary_self_types_weak.rs b/tests/ui/self/arbitrary_self_types_weak.rs
new file mode 100644
index 00000000000..91f2b9e0a95
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_weak.rs
@@ -0,0 +1,13 @@
+#![feature(arbitrary_self_types)]
+
+struct A;
+
+impl A {
+    fn m(self: std::rc::Weak<Self>) {}
+    //~^ ERROR: invalid `self` parameter type
+    fn n(self: std::sync::Weak<Self>) {}
+    //~^ ERROR: invalid `self` parameter type
+}
+
+fn main() {
+}
diff --git a/tests/ui/self/arbitrary_self_types_weak.stderr b/tests/ui/self/arbitrary_self_types_weak.stderr
new file mode 100644
index 00000000000..42d239419ad
--- /dev/null
+++ b/tests/ui/self/arbitrary_self_types_weak.stderr
@@ -0,0 +1,23 @@
+error[E0307]: invalid `self` parameter type: `std::rc::Weak<A>`
+  --> $DIR/arbitrary_self_types_weak.rs:6:16
+   |
+LL |     fn m(self: std::rc::Weak<Self>) {}
+   |                ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: `Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver`
+
+error[E0307]: invalid `self` parameter type: `std::sync::Weak<A>`
+  --> $DIR/arbitrary_self_types_weak.rs:8:16
+   |
+LL |     fn n(self: std::sync::Weak<Self>) {}
+   |                ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: `Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/span/issue-27522.stderr b/tests/ui/span/issue-27522.stderr
index 04904b0ddc1..c57a100bbe2 100644
--- a/tests/ui/span/issue-27522.stderr
+++ b/tests/ui/span/issue-27522.stderr
@@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `&SomeType`
 LL |     fn handler(self: &SomeType);
    |                      ^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or some type implementing `Receiver`
-   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/specialization/min_specialization/issue-79224.stderr b/tests/ui/specialization/min_specialization/issue-79224.stderr
index 84e526f4597..2b8169af6a2 100644
--- a/tests/ui/specialization/min_specialization/issue-79224.stderr
+++ b/tests/ui/specialization/min_specialization/issue-79224.stderr
@@ -39,10 +39,7 @@ error[E0277]: the trait bound `B: Clone` is not satisfied
    |
 LL |       fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    |  ______________________________________________________________^
-LL | |
-LL | |
-LL | |
-LL | |         write!(f, "foo")
+...  |
 LL | |     }
    | |_____^ the trait `Clone` is not implemented for `B`
    |
diff --git a/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr b/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr
index 3af1e82d207..fb564932cd5 100644
--- a/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr
+++ b/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr
@@ -2,8 +2,7 @@ error: module has missing stability attribute
   --> $DIR/missing-stability-attr-at-top-level.rs:1:1
    |
 LL | / #![feature(staged_api)]
-LL | |
-LL | |
+...  |
 LL | | fn main() {}
    | |____________^
 
diff --git a/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr b/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr
index 018786dd26d..c954282cbc7 100644
--- a/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr
+++ b/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr
@@ -23,7 +23,6 @@ LL | |
 LL | |
 LL | | #[stable(feature = "a", since = "3.3.3")]
 ...  |
-LL | |
 LL | | fn main() {}
    | |____________^
 
diff --git a/tests/ui/stable-mir-print/async-closure.rs b/tests/ui/stable-mir-print/async-closure.rs
new file mode 100644
index 00000000000..7da532a359f
--- /dev/null
+++ b/tests/ui/stable-mir-print/async-closure.rs
@@ -0,0 +1,12 @@
+//@ compile-flags: -Z unpretty=stable-mir --crate-type lib -C panic=abort
+//@ check-pass
+//@ only-x86_64
+//@ edition: 2024
+//@ needs-unwind unwind edges are different with panic=abort
+
+pub fn foo() {
+    let y = 0;
+    let x = async || {
+        let y = y;
+    };
+}
diff --git a/tests/ui/stable-mir-print/async-closure.stdout b/tests/ui/stable-mir-print/async-closure.stdout
new file mode 100644
index 00000000000..21df1fd3954
--- /dev/null
+++ b/tests/ui/stable-mir-print/async-closure.stdout
@@ -0,0 +1,90 @@
+// WARNING: This is highly experimental output it's intended for stable-mir developers only.
+// If you find a bug or want to improve the output open a issue at https://github.com/rust-lang/project-stable-mir.
+fn foo() -> () {
+    let mut _0: ();
+    let  _1: i32;
+    let  _2: {async closure@$DIR/async-closure.rs:9:13: 9:21};
+    let mut _3: &i32;
+    debug y => _1;
+    debug x => _2;
+    bb0: {
+        _1 = 0_i32;
+        _3 = &_1;
+        _2 = {coroutine-closure@$DIR/async-closure.rs:9:13: 9:21}(move _3);
+        return;
+    }
+}
+fn foo::{closure#0}(_1: &{async closure@$DIR/async-closure.rs:9:13: 9:21}) -> {async closure body@$DIR/async-closure.rs:9:22: 11:6} {
+    let mut _0: {async closure body@$DIR/async-closure.rs:9:22: 11:6};
+    let mut _2: &i32;
+    debug y => (*((*_1).0: &i32));
+    bb0: {
+        _2 = CopyForDeref(((*_1).0: &i32));
+        _0 = {coroutine@$DIR/async-closure.rs:9:22: 11:6}(_2);
+        return;
+    }
+}
+fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: Poll<()>;
+    let  _3: i32;
+    let mut _4: &i32;
+    let mut _5: u32;
+    let mut _6: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
+    let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
+    let mut _8: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
+    debug _task_context => _2;
+    debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32));
+    debug y => _3;
+    bb0: {
+        _6 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
+        _5 = discriminant((*_6));
+        switchInt(move _5) -> [0: bb1, 1: bb2, otherwise: bb3];
+    }
+    bb1: {
+        _7 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
+        _4 = CopyForDeref(((*_7).0: &i32));
+        _3 = (*_4);
+        _0 = std::task::Poll::Ready(());
+        _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
+        discriminant((*_8) = 1;
+        return;
+    }
+    bb2: {
+        assert(false, `async fn` resumed after completion) -> [success: bb2, unwind unreachable];
+    }
+    bb3: {
+        unreachable;
+    }
+}
+fn foo::{closure#0}::{closure#1}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
+    let mut _0: Poll<()>;
+    let  _3: i32;
+    let mut _4: &i32;
+    let mut _5: u32;
+    let mut _6: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
+    let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
+    let mut _8: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6};
+    debug _task_context => _2;
+    debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32));
+    debug y => _3;
+    bb0: {
+        _6 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
+        _5 = discriminant((*_6));
+        switchInt(move _5) -> [0: bb1, 1: bb2, otherwise: bb3];
+    }
+    bb1: {
+        _7 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
+        _4 = CopyForDeref(((*_7).0: &i32));
+        _3 = (*_4);
+        _0 = std::task::Poll::Ready(());
+        _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
+        discriminant((*_8) = 1;
+        return;
+    }
+    bb2: {
+        assert(false, `async fn` resumed after completion) -> [success: bb2, unwind unreachable];
+    }
+    bb3: {
+        unreachable;
+    }
+}
diff --git a/tests/ui/stable-mir-print/operands.stdout b/tests/ui/stable-mir-print/operands.stdout
index 3c27878b3cf..c3b1151ae24 100644
--- a/tests/ui/stable-mir-print/operands.stdout
+++ b/tests/ui/stable-mir-print/operands.stdout
@@ -5,187 +5,183 @@ fn operands(_1: u8) -> () {
     let  _2: [u8; 10];
     let  _3: u8;
     let  _4: usize;
-    let mut _5: usize;
-    let mut _6: bool;
-    let  _7: u8;
-    let  _8: usize;
-    let mut _9: (usize, bool);
-    let mut _10: usize;
-    let mut _11: bool;
-    let mut _12: (&u8, &u8);
-    let mut _13: &u8;
-    let mut _14: &u8;
-    let  _15: &u8;
-    let  _16: &u8;
-    let mut _17: bool;
-    let mut _18: u8;
-    let mut _19: u8;
-    let  _20: core::panicking::AssertKind;
-    let  _21: !;
-    let mut _22: Option<Arguments<'_>>;
-    let  _23: &u8;
-    let  _24: u8;
-    let mut _25: (&u8, &u8);
-    let mut _26: &u8;
-    let mut _27: &u8;
-    let  _28: &u8;
-    let  _29: &u8;
-    let mut _30: bool;
-    let mut _31: u8;
-    let mut _32: u8;
-    let  _33: core::panicking::AssertKind;
-    let  _34: !;
-    let mut _35: Option<Arguments<'_>>;
-    let  _36: (u8, u8);
-    let  _37: u8;
-    let  _38: u8;
-    let mut _39: (&u8, &u8);
-    let mut _40: &u8;
-    let mut _41: &u8;
-    let  _42: &u8;
-    let  _43: &u8;
-    let mut _44: bool;
-    let mut _45: u8;
-    let mut _46: u8;
-    let  _47: core::panicking::AssertKind;
-    let  _48: !;
-    let mut _49: Option<Arguments<'_>>;
-    let  _50: usize;
-    let mut _51: &[u8];
-    let mut _52: &[u8; 10];
-    let  _53: usize;
-    let  _54: &usize;
-    let mut _55: (&usize, &usize);
-    let mut _56: &usize;
-    let mut _57: &usize;
-    let  _58: &usize;
-    let  _59: &usize;
-    let mut _60: bool;
-    let mut _61: usize;
-    let mut _62: usize;
-    let  _63: core::panicking::AssertKind;
-    let  _64: !;
-    let mut _65: Option<Arguments<'_>>;
+    let mut _5: bool;
+    let  _6: u8;
+    let  _7: usize;
+    let mut _8: (usize, bool);
+    let mut _9: bool;
+    let mut _10: (&u8, &u8);
+    let mut _11: &u8;
+    let mut _12: &u8;
+    let  _13: &u8;
+    let  _14: &u8;
+    let mut _15: bool;
+    let mut _16: u8;
+    let mut _17: u8;
+    let  _18: core::panicking::AssertKind;
+    let  _19: !;
+    let mut _20: Option<Arguments<'_>>;
+    let  _21: &u8;
+    let  _22: u8;
+    let mut _23: (&u8, &u8);
+    let mut _24: &u8;
+    let mut _25: &u8;
+    let  _26: &u8;
+    let  _27: &u8;
+    let mut _28: bool;
+    let mut _29: u8;
+    let mut _30: u8;
+    let  _31: core::panicking::AssertKind;
+    let  _32: !;
+    let mut _33: Option<Arguments<'_>>;
+    let  _34: (u8, u8);
+    let  _35: u8;
+    let  _36: u8;
+    let mut _37: (&u8, &u8);
+    let mut _38: &u8;
+    let mut _39: &u8;
+    let  _40: &u8;
+    let  _41: &u8;
+    let mut _42: bool;
+    let mut _43: u8;
+    let mut _44: u8;
+    let  _45: core::panicking::AssertKind;
+    let  _46: !;
+    let mut _47: Option<Arguments<'_>>;
+    let  _48: usize;
+    let mut _49: &[u8];
+    let mut _50: &[u8; 10];
+    let  _51: usize;
+    let  _52: &usize;
+    let mut _53: (&usize, &usize);
+    let mut _54: &usize;
+    let mut _55: &usize;
+    let  _56: &usize;
+    let  _57: &usize;
+    let mut _58: bool;
+    let mut _59: usize;
+    let mut _60: usize;
+    let  _61: core::panicking::AssertKind;
+    let  _62: !;
+    let mut _63: Option<Arguments<'_>>;
     debug val => _1;
     debug array => _2;
     debug first => _3;
-    debug last => _7;
-    debug left_val => _15;
-    debug right_val => _16;
-    debug kind => _20;
-    debug reference => _23;
-    debug dereferenced => _24;
-    debug left_val => _28;
-    debug right_val => _29;
-    debug kind => _33;
-    debug tuple => _36;
-    debug first_again => _37;
-    debug first_again_again => _38;
-    debug left_val => _42;
-    debug right_val => _43;
-    debug kind => _47;
-    debug length => _50;
-    debug size_of => _53;
-    debug left_val => _58;
-    debug right_val => _59;
-    debug kind => _63;
+    debug last => _6;
+    debug left_val => _13;
+    debug right_val => _14;
+    debug kind => _18;
+    debug reference => _21;
+    debug dereferenced => _22;
+    debug left_val => _26;
+    debug right_val => _27;
+    debug kind => _31;
+    debug tuple => _34;
+    debug first_again => _35;
+    debug first_again_again => _36;
+    debug left_val => _40;
+    debug right_val => _41;
+    debug kind => _45;
+    debug length => _48;
+    debug size_of => _51;
+    debug left_val => _56;
+    debug right_val => _57;
+    debug kind => _61;
     bb0: {
         _2 = [_1; 10];
         _4 = 0_usize;
-        _5 = 10_usize;
-        _6 = Lt(_4, _5);
-        assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind unreachable];
+        _5 = Lt(_4, 10_usize);
+        assert(move _5, "index out of bounds: the length is {} but the index is {}", 10_usize, _4) -> [success: bb1, unwind unreachable];
     }
     bb1: {
         _3 = _2[_4];
-        _9 = CheckedSub(10_usize, 1_usize);
-        assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", 10_usize, 1_usize) -> [success: bb2, unwind unreachable];
+        _8 = CheckedSub(10_usize, 1_usize);
+        assert(!move (_8.1: bool), "attempt to compute `{} - {}`, which would overflow", 10_usize, 1_usize) -> [success: bb2, unwind unreachable];
     }
     bb2: {
-        _8 = move (_9.0: usize);
-        _10 = 10_usize;
-        _11 = Lt(_8, _10);
-        assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, _8) -> [success: bb3, unwind unreachable];
+        _7 = move (_8.0: usize);
+        _9 = Lt(_7, 10_usize);
+        assert(move _9, "index out of bounds: the length is {} but the index is {}", 10_usize, _7) -> [success: bb3, unwind unreachable];
     }
     bb3: {
-        _7 = _2[_8];
-        _13 = &_3;
-        _14 = &_7;
-        _12 = (move _13, move _14);
-        _15 = (_12.0: &u8);
-        _16 = (_12.1: &u8);
-        _18 = (*_15);
-        _19 = (*_16);
-        _17 = Eq(move _18, move _19);
-        switchInt(move _17) -> [0: bb5, otherwise: bb4];
+        _6 = _2[_7];
+        _11 = &_3;
+        _12 = &_6;
+        _10 = (move _11, move _12);
+        _13 = (_10.0: &u8);
+        _14 = (_10.1: &u8);
+        _16 = (*_13);
+        _17 = (*_14);
+        _15 = Eq(move _16, move _17);
+        switchInt(move _15) -> [0: bb5, otherwise: bb4];
     }
     bb4: {
-        _23 = &_3;
-        _24 = (*_23);
-        _26 = &_24;
-        _27 = &_3;
-        _25 = (move _26, move _27);
-        _28 = (_25.0: &u8);
-        _29 = (_25.1: &u8);
-        _31 = (*_28);
-        _32 = (*_29);
-        _30 = Eq(move _31, move _32);
-        switchInt(move _30) -> [0: bb7, otherwise: bb6];
+        _21 = &_3;
+        _22 = (*_21);
+        _24 = &_22;
+        _25 = &_3;
+        _23 = (move _24, move _25);
+        _26 = (_23.0: &u8);
+        _27 = (_23.1: &u8);
+        _29 = (*_26);
+        _30 = (*_27);
+        _28 = Eq(move _29, move _30);
+        switchInt(move _28) -> [0: bb7, otherwise: bb6];
     }
     bb5: {
-        _20 = core::panicking::AssertKind::Eq;
-        _22 = std::option::Option::None;
-        _21 = core::panicking::assert_failed::<u8, u8>(move _20, _15, _16, move _22) -> unwind unreachable;
+        _18 = core::panicking::AssertKind::Eq;
+        _20 = std::option::Option::None;
+        _19 = core::panicking::assert_failed::<u8, u8>(move _18, _13, _14, move _20) -> unwind unreachable;
     }
     bb6: {
-        _36 = (_3, _7);
-        _37 = (_36.0: u8);
-        _38 = (_36.0: u8);
-        _40 = &_37;
-        _41 = &_38;
-        _39 = (move _40, move _41);
-        _42 = (_39.0: &u8);
-        _43 = (_39.1: &u8);
-        _45 = (*_42);
-        _46 = (*_43);
-        _44 = Eq(move _45, move _46);
-        switchInt(move _44) -> [0: bb9, otherwise: bb8];
+        _34 = (_3, _6);
+        _35 = (_34.0: u8);
+        _36 = (_34.0: u8);
+        _38 = &_35;
+        _39 = &_36;
+        _37 = (move _38, move _39);
+        _40 = (_37.0: &u8);
+        _41 = (_37.1: &u8);
+        _43 = (*_40);
+        _44 = (*_41);
+        _42 = Eq(move _43, move _44);
+        switchInt(move _42) -> [0: bb9, otherwise: bb8];
     }
     bb7: {
-        _33 = core::panicking::AssertKind::Eq;
-        _35 = std::option::Option::None;
-        _34 = core::panicking::assert_failed::<u8, u8>(move _33, _28, _29, move _35) -> unwind unreachable;
+        _31 = core::panicking::AssertKind::Eq;
+        _33 = std::option::Option::None;
+        _32 = core::panicking::assert_failed::<u8, u8>(move _31, _26, _27, move _33) -> unwind unreachable;
     }
     bb8: {
-        _52 = &_2;
-        _51 = move _52 as &[u8];
-        _50 = PtrMetadata(move _51);
-        _54 = &_50;
-        _53 = std::mem::size_of_val::<usize>(_54) -> [return: bb10, unwind unreachable];
+        _50 = &_2;
+        _49 = move _50 as &[u8];
+        _48 = PtrMetadata(move _49);
+        _52 = &_48;
+        _51 = std::mem::size_of_val::<usize>(_52) -> [return: bb10, unwind unreachable];
     }
     bb9: {
-        _47 = core::panicking::AssertKind::Eq;
-        _49 = std::option::Option::None;
-        _48 = core::panicking::assert_failed::<u8, u8>(move _47, _42, _43, move _49) -> unwind unreachable;
+        _45 = core::panicking::AssertKind::Eq;
+        _47 = std::option::Option::None;
+        _46 = core::panicking::assert_failed::<u8, u8>(move _45, _40, _41, move _47) -> unwind unreachable;
     }
     bb10: {
-        _56 = &_50;
-        _57 = &_53;
-        _55 = (move _56, move _57);
-        _58 = (_55.0: &usize);
-        _59 = (_55.1: &usize);
-        _61 = (*_58);
-        _62 = (*_59);
-        _60 = Eq(move _61, move _62);
-        switchInt(move _60) -> [0: bb12, otherwise: bb11];
+        _54 = &_48;
+        _55 = &_51;
+        _53 = (move _54, move _55);
+        _56 = (_53.0: &usize);
+        _57 = (_53.1: &usize);
+        _59 = (*_56);
+        _60 = (*_57);
+        _58 = Eq(move _59, move _60);
+        switchInt(move _58) -> [0: bb12, otherwise: bb11];
     }
     bb11: {
         return;
     }
     bb12: {
-        _63 = core::panicking::AssertKind::Eq;
-        _65 = std::option::Option::None;
-        _64 = core::panicking::assert_failed::<usize, usize>(move _63, _58, _59, move _65) -> unwind unreachable;
+        _61 = core::panicking::AssertKind::Eq;
+        _63 = std::option::Option::None;
+        _62 = core::panicking::assert_failed::<usize, usize>(move _61, _56, _57, move _63) -> unwind unreachable;
     }
 }
 fn operands::{constant#0}() -> usize {
diff --git a/tests/ui/static/issue-24446.stderr b/tests/ui/static/issue-24446.stderr
index 9c206e5ef3c..8cb034000be 100644
--- a/tests/ui/static/issue-24446.stderr
+++ b/tests/ui/static/issue-24446.stderr
@@ -20,10 +20,7 @@ error[E0277]: the size for values of type `(dyn Fn() -> u32 + 'static)` cannot b
    |
 LL |       static foo: dyn Fn() -> u32 = || -> u32 {
    |  ___________________________________^
-LL | |
-LL | |
-LL | |
-LL | |
+...  |
 LL | |         0
 LL | |     };
    | |_____^ doesn't have a size known at compile-time
@@ -36,10 +33,7 @@ error[E0308]: mismatched types
    |
 LL |       static foo: dyn Fn() -> u32 = || -> u32 {
    |  ___________________________________^
-LL | |
-LL | |
-LL | |
-LL | |
+...  |
 LL | |         0
 LL | |     };
    | |_____^ expected `dyn Fn`, found closure
diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr
index eb9f9196a72..beafd7c2ab0 100644
--- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr
+++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr
@@ -32,8 +32,8 @@ error[E0307]: invalid `self` parameter type: `()`
 LL |     fn bar(self: ()) {}
    |                  ^^
    |
-   = note: type of `self` must be `Self` or some type implementing `Receiver`
-   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/suggestions/if-then-neeing-semi.stderr b/tests/ui/suggestions/if-then-neeing-semi.stderr
index 6833e0bab2b..0556d6c50b1 100644
--- a/tests/ui/suggestions/if-then-neeing-semi.stderr
+++ b/tests/ui/suggestions/if-then-neeing-semi.stderr
@@ -6,12 +6,10 @@ LL |       let _ = if true {
 LL | |
 LL | |         async_dummy();
    | |         -------------- expected because of this
-LL | |
-LL | |     } else {
+...  |
 LL | |         async_dummy()
    | |         ^^^^^^^^^^^^^ expected `()`, found future
 ...  |
-LL | |
 LL | |     };
    | |_____- `if` and `else` have incompatible types
    |
@@ -38,12 +36,10 @@ LL |       let _ = if true {
 LL | |
 LL | |         async_dummy();
    | |         -------------- expected because of this
-LL | |
-LL | |     } else {
+...  |
 LL | |         async_dummy2()
    | |         ^^^^^^^^^^^^^^ expected `()`, found future
 ...  |
-LL | |
 LL | |     };
    | |_____- `if` and `else` have incompatible types
    |
@@ -72,12 +68,10 @@ LL |       let _ = if true {
 LL | |
 LL | |         async_dummy()
    | |         ------------- expected because of this
-LL | |
-LL | |     } else {
+...  |
 LL | |         async_dummy2()
    | |         ^^^^^^^^^^^^^^ expected future, found a different future
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____- `if` and `else` have incompatible types
    |
@@ -101,8 +95,7 @@ LL | |         dummy();
    | |         |      |
    | |         |      help: consider removing this semicolon
    | |         expected because of this
-LL | |
-LL | |     } else {
+...  |
 LL | |         dummy()
    | |         ^^^^^^^ expected `()`, found `i32`
 LL | |
diff --git a/tests/ui/suggestions/match-prev-arm-needing-semi.stderr b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr
index cf3cf45ef40..f70f6a1e157 100644
--- a/tests/ui/suggestions/match-prev-arm-needing-semi.stderr
+++ b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr
@@ -6,12 +6,10 @@ LL |       let _ = match true {
 LL | |         true => {
 LL | |             async_dummy();
    | |             -------------- this is found to be of type `()`
-LL | |
-LL | |         }
+...  |
 LL | |         false => async_dummy(),
    | |                  ^^^^^^^^^^^^^ expected `()`, found future
 ...  |
-LL | |
 LL | |     };
    | |_____- `match` arms have incompatible types
    |
@@ -38,12 +36,10 @@ LL |       let _ = match true {
 LL | |         true => {
 LL | |             async_dummy();
    | |             -------------- this is found to be of type `()`
-LL | |
-LL | |         }
+...  |
 LL | |         false => async_dummy2(),
    | |                  ^^^^^^^^^^^^^^ expected `()`, found future
 ...  |
-LL | |
 LL | |     };
    | |_____- `match` arms have incompatible types
    |
@@ -74,8 +70,7 @@ LL | |         true => async_dummy(),
 LL | |
 LL | |         false => async_dummy2(),
    | |                  ^^^^^^^^^^^^^^ expected future, found a different future
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____- `match` arms have incompatible types
    |
@@ -98,8 +93,7 @@ LL | |             dummy();
    | |             |      |
    | |             |      help: consider removing this semicolon
    | |             this is found to be of type `()`
-LL | |
-LL | |         }
+...  |
 LL | |         false => dummy(),
    | |                  ^^^^^^^ expected `()`, found `i32`
 LL | |
diff --git a/tests/ui/suggestions/suggest-deref-in-match-issue-132784.rs b/tests/ui/suggestions/suggest-deref-in-match-issue-132784.rs
new file mode 100644
index 00000000000..205e57f4a9f
--- /dev/null
+++ b/tests/ui/suggestions/suggest-deref-in-match-issue-132784.rs
@@ -0,0 +1,84 @@
+use std::sync::Arc;
+fn main() {
+    let mut x = Arc::new(Some(1));
+    match x {
+        //~^ HELP consider dereferencing to access the inner value using the Deref trait
+        //~| HELP consider dereferencing to access the inner value using the Deref trait
+        Some(_) => {}
+        //~^ ERROR mismatched types
+        None => {}
+        //~^ ERROR mismatched types
+    }
+
+    match &x {
+        //~^ HELP consider dereferencing to access the inner value using the Deref trait
+        //~| HELP consider dereferencing to access the inner value using the Deref trait
+        Some(_) => {}
+        //~^ ERROR mismatched types
+        None => {}
+        //~^ ERROR mismatched types
+    }
+
+    let mut y = Box::new(Some(1));
+    match y {
+        //~^ HELP consider dereferencing to access the inner value using the Deref trait
+        //~| HELP consider dereferencing to access the inner value using the Deref trait
+        Some(_) => {}
+        //~^ ERROR mismatched types
+        None => {}
+        //~^ ERROR mismatched types
+    }
+
+    let mut z = Arc::new(Some(1));
+    match z as Arc<Option<i32>> {
+        //~^ HELP consider dereferencing to access the inner value using the Deref trait
+        //~| HELP consider dereferencing to access the inner value using the Deref trait
+        Some(_) => {}
+        //~^ ERROR mismatched types
+        None => {}
+        //~^ ERROR mismatched types
+    }
+
+    let z_const: &Arc<Option<i32>> = &z;
+    match z_const {
+        //~^ HELP consider dereferencing to access the inner value using the Deref trait
+        //~| HELP consider dereferencing to access the inner value using the Deref trait
+        Some(_) => {}
+        //~^ ERROR mismatched types
+        None => {}
+        //~^ ERROR mismatched types
+    }
+
+    // Normal reference because Arc doesn't implement DerefMut.
+    let z_mut: &mut Arc<Option<i32>> = &mut z;
+    match z_mut {
+        //~^ HELP consider dereferencing to access the inner value using the Deref trait
+        //~| HELP consider dereferencing to access the inner value using the Deref trait
+        Some(_) => {}
+        //~^ ERROR mismatched types
+        None => {}
+        //~^ ERROR mismatched types
+    }
+
+    // Mutable reference because Box does implement DerefMut.
+    let y_mut: &mut Box<Option<i32>> = &mut y;
+    match y_mut {
+        //~^ HELP consider dereferencing to access the inner value using the Deref trait
+        //~| HELP consider dereferencing to access the inner value using the Deref trait
+        Some(_) => {}
+        //~^ ERROR mismatched types
+        None => {}
+        //~^ ERROR mismatched types
+    }
+
+    // Difficult expression.
+    let difficult = Arc::new(Some(1));
+    match (& (&difficult)  ) {
+        //~^ HELP consider dereferencing to access the inner value using the Deref trait
+        //~| HELP consider dereferencing to access the inner value using the Deref trait
+        Some(_) => {}
+        //~^ ERROR mismatched types
+        None => {}
+        //~^ ERROR mismatched types
+    }
+}
diff --git a/tests/ui/suggestions/suggest-deref-in-match-issue-132784.stderr b/tests/ui/suggestions/suggest-deref-in-match-issue-132784.stderr
new file mode 100644
index 00000000000..9338ef19089
--- /dev/null
+++ b/tests/ui/suggestions/suggest-deref-in-match-issue-132784.stderr
@@ -0,0 +1,259 @@
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:7:9
+   |
+LL |     match x {
+   |           - this expression has type `Arc<Option<{integer}>>`
+...
+LL |         Some(_) => {}
+   |         ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
+   |
+   = note: expected struct `Arc<Option<{integer}>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match *x {
+   |           ~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:9:9
+   |
+LL |     match x {
+   |           - this expression has type `Arc<Option<{integer}>>`
+...
+LL |         None => {}
+   |         ^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
+   |
+   = note: expected struct `Arc<Option<{integer}>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match *x {
+   |           ~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:16:9
+   |
+LL |     match &x {
+   |           -- this expression has type `&Arc<Option<{integer}>>`
+...
+LL |         Some(_) => {}
+   |         ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
+   |
+   = note: expected struct `Arc<Option<{integer}>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match &*x {
+   |           ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:18:9
+   |
+LL |     match &x {
+   |           -- this expression has type `&Arc<Option<{integer}>>`
+...
+LL |         None => {}
+   |         ^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
+   |
+   = note: expected struct `Arc<Option<{integer}>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match &*x {
+   |           ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:26:9
+   |
+LL |     match y {
+   |           - this expression has type `Box<Option<{integer}>>`
+...
+LL |         Some(_) => {}
+   |         ^^^^^^^ expected `Box<Option<{integer}>>`, found `Option<_>`
+   |
+   = note: expected struct `Box<Option<{integer}>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match *y {
+   |           ~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:28:9
+   |
+LL |     match y {
+   |           - this expression has type `Box<Option<{integer}>>`
+...
+LL |         None => {}
+   |         ^^^^ expected `Box<Option<{integer}>>`, found `Option<_>`
+   |
+   = note: expected struct `Box<Option<{integer}>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match *y {
+   |           ~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:36:9
+   |
+LL |     match z as Arc<Option<i32>> {
+   |           --------------------- this expression has type `Arc<Option<i32>>`
+...
+LL |         Some(_) => {}
+   |         ^^^^^^^ expected `Arc<Option<i32>>`, found `Option<_>`
+   |
+   = note: expected struct `Arc<Option<i32>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match *(z as Arc<Option<i32>>) {
+   |           ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:38:9
+   |
+LL |     match z as Arc<Option<i32>> {
+   |           --------------------- this expression has type `Arc<Option<i32>>`
+...
+LL |         None => {}
+   |         ^^^^ expected `Arc<Option<i32>>`, found `Option<_>`
+   |
+   = note: expected struct `Arc<Option<i32>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match *(z as Arc<Option<i32>>) {
+   |           ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:46:9
+   |
+LL |     match z_const {
+   |           ------- this expression has type `&Arc<Option<i32>>`
+...
+LL |         Some(_) => {}
+   |         ^^^^^^^ expected `Arc<Option<i32>>`, found `Option<_>`
+   |
+   = note: expected struct `Arc<Option<i32>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match &**z_const {
+   |           ~~~~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:48:9
+   |
+LL |     match z_const {
+   |           ------- this expression has type `&Arc<Option<i32>>`
+...
+LL |         None => {}
+   |         ^^^^ expected `Arc<Option<i32>>`, found `Option<_>`
+   |
+   = note: expected struct `Arc<Option<i32>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match &**z_const {
+   |           ~~~~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:57:9
+   |
+LL |     match z_mut {
+   |           ----- this expression has type `&mut Arc<Option<i32>>`
+...
+LL |         Some(_) => {}
+   |         ^^^^^^^ expected `Arc<Option<i32>>`, found `Option<_>`
+   |
+   = note: expected struct `Arc<Option<i32>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match &**z_mut {
+   |           ~~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:59:9
+   |
+LL |     match z_mut {
+   |           ----- this expression has type `&mut Arc<Option<i32>>`
+...
+LL |         None => {}
+   |         ^^^^ expected `Arc<Option<i32>>`, found `Option<_>`
+   |
+   = note: expected struct `Arc<Option<i32>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match &**z_mut {
+   |           ~~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:68:9
+   |
+LL |     match y_mut {
+   |           ----- this expression has type `&mut Box<Option<i32>>`
+...
+LL |         Some(_) => {}
+   |         ^^^^^^^ expected `Box<Option<i32>>`, found `Option<_>`
+   |
+   = note: expected struct `Box<Option<i32>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match &**y_mut {
+   |           ~~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:70:9
+   |
+LL |     match y_mut {
+   |           ----- this expression has type `&mut Box<Option<i32>>`
+...
+LL |         None => {}
+   |         ^^^^ expected `Box<Option<i32>>`, found `Option<_>`
+   |
+   = note: expected struct `Box<Option<i32>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match &**y_mut {
+   |           ~~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:79:9
+   |
+LL |     match (& (&difficult)  ) {
+   |           ------------------ this expression has type `&&Arc<Option<{integer}>>`
+...
+LL |         Some(_) => {}
+   |         ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
+   |
+   = note: expected struct `Arc<Option<{integer}>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match &*difficult {
+   |           ~~~~~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-deref-in-match-issue-132784.rs:81:9
+   |
+LL |     match (& (&difficult)  ) {
+   |           ------------------ this expression has type `&&Arc<Option<{integer}>>`
+...
+LL |         None => {}
+   |         ^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
+   |
+   = note: expected struct `Arc<Option<{integer}>>`
+                found enum `Option<_>`
+help: consider dereferencing to access the inner value using the Deref trait
+   |
+LL |     match &*difficult {
+   |           ~~~~~~~~~~~
+
+error: aborting due to 16 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr
index 939285498fb..a275f0c2fa8 100644
--- a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr
+++ b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr
@@ -13,9 +13,7 @@ LL | /     if true {
 LL | |
 LL | |         x?
    | |         ^^ expected `()`, found integer
-LL | |
-LL | |
-LL | |
+...  |
 LL | |     }
    | |_____- expected this to be `()`
    |
diff --git a/tests/ui/symbol-names/types.legacy.stderr b/tests/ui/symbol-names/types.legacy.stderr
index 87c3acae0bd..c368b318609 100644
--- a/tests/ui/symbol-names/types.legacy.stderr
+++ b/tests/ui/symbol-names/types.legacy.stderr
@@ -502,5 +502,23 @@ error: demangling-alt(a::b::Type<[T; N]>)
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 84 previous errors
+error: symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$17h[HASH]E)
+  --> $DIR/types.rs:272:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(a::b::Type<[u8; 0]>::h[HASH])
+  --> $DIR/types.rs:272:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(a::b::Type<[u8; 0]>)
+  --> $DIR/types.rs:272:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 87 previous errors
 
diff --git a/tests/ui/symbol-names/types.rs b/tests/ui/symbol-names/types.rs
index 7ed19e0e5a8..38735e1aa50 100644
--- a/tests/ui/symbol-names/types.rs
+++ b/tests/ui/symbol-names/types.rs
@@ -266,6 +266,17 @@ pub fn b() {
     //[v0]~| ERROR ::b::Type<[_; _]>>)
     //[v0]~| ERROR demangling-alt(<a::b::Type<[_; _]>>)
     impl<const N: usize, T> Type<[T; N]> {}
+
+    const ZERO: usize = 0;
+
+    #[rustc_symbol_name]
+    //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$
+    //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<[u8; 0]>::
+    //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<[u8; 0]>)
+    //[v0]~^^^^ ERROR symbol-name(_RMsq_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeAhj0_E)
+    //[v0]~| ERROR ::b::Type<[u8; 0usize]>>)
+    //[v0]~| ERROR demangling-alt(<a::b::Type<[u8; 0]>>)
+    impl Type<[u8; ZERO]> {}
 }
 
 fn main() {}
diff --git a/tests/ui/symbol-names/types.v0.stderr b/tests/ui/symbol-names/types.v0.stderr
index 58680e00202..90012a2dcf7 100644
--- a/tests/ui/symbol-names/types.v0.stderr
+++ b/tests/ui/symbol-names/types.v0.stderr
@@ -502,5 +502,23 @@ error: demangling-alt(<a::b::Type<[_; _]>>)
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 84 previous errors
+error: symbol-name(_RMsq_NvCsCRATE_HASH_1a1bINtB<REF>_4TypeAhj0_E)
+  --> $DIR/types.rs:272:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<a[HASH]::b::Type<[u8; 0usize]>>)
+  --> $DIR/types.rs:272:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<a::b::Type<[u8; 0]>>)
+  --> $DIR/types.rs:272:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 87 previous errors
 
diff --git a/tests/ui/symbol-names/types.verbose-legacy.stderr b/tests/ui/symbol-names/types.verbose-legacy.stderr
index 87c3acae0bd..c368b318609 100644
--- a/tests/ui/symbol-names/types.verbose-legacy.stderr
+++ b/tests/ui/symbol-names/types.verbose-legacy.stderr
@@ -502,5 +502,23 @@ error: demangling-alt(a::b::Type<[T; N]>)
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 84 previous errors
+error: symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$17h[HASH]E)
+  --> $DIR/types.rs:272:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(a::b::Type<[u8; 0]>::h[HASH])
+  --> $DIR/types.rs:272:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(a::b::Type<[u8; 0]>)
+  --> $DIR/types.rs:272:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 87 previous errors
 
diff --git a/tests/ui/target-feature/allowed-softfloat-target-feature-attribute.rs b/tests/ui/target-feature/allowed-softfloat-target-feature-attribute.rs
new file mode 100644
index 00000000000..8b60820cc9b
--- /dev/null
+++ b/tests/ui/target-feature/allowed-softfloat-target-feature-attribute.rs
@@ -0,0 +1,11 @@
+//@ compile-flags: --target=x86_64-unknown-none --crate-type=lib
+//@ needs-llvm-components: x86
+//@ build-pass
+#![feature(no_core, lang_items, x87_target_feature)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[target_feature(enable = "x87")]
+pub unsafe fn my_fun() {}
diff --git a/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs b/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs
new file mode 100644
index 00000000000..e34faf5a983
--- /dev/null
+++ b/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.rs
@@ -0,0 +1,9 @@
+//@ compile-flags: --target=x86_64-unknown-none --crate-type=lib
+//@ needs-llvm-components: x86
+//@ compile-flags: -Ctarget-feature=-x87
+//@ build-pass
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
diff --git a/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.stderr b/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.stderr
new file mode 100644
index 00000000000..309b64afd92
--- /dev/null
+++ b/tests/ui/target-feature/allowed-softfloat-target-feature-flag-disable.stderr
@@ -0,0 +1,6 @@
+warning: unstable feature specified for `-Ctarget-feature`: `x87`
+   |
+   = note: this feature is not stably supported; its behavior can change in the future
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.rs
new file mode 100644
index 00000000000..b3171d52c51
--- /dev/null
+++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.rs
@@ -0,0 +1,11 @@
+//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
+//@ needs-llvm-components: x86
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[target_feature(enable = "x87")]
+//~^ERROR: cannot be toggled with
+pub unsafe fn my_fun() {}
diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.stderr b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.stderr
new file mode 100644
index 00000000000..3ebbe69d8ae
--- /dev/null
+++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute.stderr
@@ -0,0 +1,8 @@
+error: target feature `x87` cannot be toggled with `#[target_feature]`: unsound on hard-float targets because it changes float ABI
+  --> $DIR/forbidden-hardfloat-target-feature-attribute.rs:9:18
+   |
+LL | #[target_feature(enable = "x87")]
+   |                  ^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-cfg.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-cfg.rs
new file mode 100644
index 00000000000..8755791c1c0
--- /dev/null
+++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-cfg.rs
@@ -0,0 +1,14 @@
+//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
+//@ needs-llvm-components: x86
+//@ check-pass
+#![feature(no_core, lang_items)]
+#![no_core]
+#![allow(unexpected_cfgs)]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+// The compile_error macro does not exist, so if the `cfg` evaluates to `true` this
+// complains about the missing macro rather than showing the error... but that's good enough.
+#[cfg(not(target_feature = "x87"))]
+compile_error!("the x87 feature *should* be exposed in `cfg`");
diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs
new file mode 100644
index 00000000000..fd8023664da
--- /dev/null
+++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.rs
@@ -0,0 +1,10 @@
+//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
+//@ needs-llvm-components: x86
+//@ compile-flags: -Ctarget-feature=-x87
+// For now this is just a warning.
+//@ build-pass
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.stderr b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.stderr
new file mode 100644
index 00000000000..604ad2f991a
--- /dev/null
+++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.stderr
@@ -0,0 +1,7 @@
+warning: target feature `x87` cannot be toggled with `-Ctarget-feature`: unsound on hard-float targets because it changes float ABI
+   |
+   = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/target-feature/forbidden-target-feature-attribute.rs b/tests/ui/target-feature/forbidden-target-feature-attribute.rs
index 91c56b43689..f13cdd17da6 100644
--- a/tests/ui/target-feature/forbidden-target-feature-attribute.rs
+++ b/tests/ui/target-feature/forbidden-target-feature-attribute.rs
@@ -1,7 +1,6 @@
 //@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
 //@ needs-llvm-components: x86
 #![feature(no_core, lang_items)]
-#![no_std]
 #![no_core]
 
 #[lang = "sized"]
diff --git a/tests/ui/target-feature/forbidden-target-feature-attribute.stderr b/tests/ui/target-feature/forbidden-target-feature-attribute.stderr
index fb318531f7e..27ac4aaf960 100644
--- a/tests/ui/target-feature/forbidden-target-feature-attribute.stderr
+++ b/tests/ui/target-feature/forbidden-target-feature-attribute.stderr
@@ -1,5 +1,5 @@
 error: target feature `soft-float` cannot be toggled with `#[target_feature]`: unsound because it changes float ABI
-  --> $DIR/forbidden-target-feature-attribute.rs:10:18
+  --> $DIR/forbidden-target-feature-attribute.rs:9:18
    |
 LL | #[target_feature(enable = "soft-float")]
    |                  ^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/target-feature/forbidden-target-feature-cfg.rs b/tests/ui/target-feature/forbidden-target-feature-cfg.rs
index 5df26e26793..1f001e9f8ff 100644
--- a/tests/ui/target-feature/forbidden-target-feature-cfg.rs
+++ b/tests/ui/target-feature/forbidden-target-feature-cfg.rs
@@ -2,7 +2,6 @@
 //@ needs-llvm-components: x86
 //@ check-pass
 #![feature(no_core, lang_items)]
-#![no_std]
 #![no_core]
 #![allow(unexpected_cfgs)]
 
diff --git a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs
index b27e8a10afe..b09c53bd46a 100644
--- a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs
+++ b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs
@@ -4,7 +4,6 @@
 // For now this is just a warning.
 //@ build-pass
 #![feature(no_core, lang_items)]
-#![no_std]
 #![no_core]
 
 #[lang = "sized"]
diff --git a/tests/ui/target-feature/forbidden-target-feature-flag.rs b/tests/ui/target-feature/forbidden-target-feature-flag.rs
index 93cebc6b536..0f688fde7f4 100644
--- a/tests/ui/target-feature/forbidden-target-feature-flag.rs
+++ b/tests/ui/target-feature/forbidden-target-feature-flag.rs
@@ -4,7 +4,6 @@
 // For now this is just a warning.
 //@ build-pass
 #![feature(no_core, lang_items)]
-#![no_std]
 #![no_core]
 
 #[lang = "sized"]
diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs
index f35fbd11155..2626685fa0a 100644
--- a/tests/ui/target-feature/gate.rs
+++ b/tests/ui/target-feature/gate.rs
@@ -24,6 +24,7 @@
 // gate-test-prfchw_target_feature
 // gate-test-s390x_target_feature
 // gate-test-sparc_target_feature
+// gate-test-x87_target_feature
 
 #[target_feature(enable = "avx512bw")]
 //~^ ERROR: currently unstable
diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr
index b84bab370be..ba5ae79f942 100644
--- a/tests/ui/target-feature/gate.stderr
+++ b/tests/ui/target-feature/gate.stderr
@@ -1,5 +1,5 @@
 error[E0658]: the target feature `avx512bw` is currently unstable
-  --> $DIR/gate.rs:28:18
+  --> $DIR/gate.rs:29:18
    |
 LL | #[target_feature(enable = "avx512bw")]
    |                  ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr b/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr
index 66862d97bf9..e499451d897 100644
--- a/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr
+++ b/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr
@@ -26,11 +26,7 @@ LL |       async const fn bar(&self) {
    |       |
    |  _____`async` because of this
    | |
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |
 LL | |     }
    | |_____-
 
@@ -38,11 +34,7 @@ error[E0407]: method `bar` is not a member of trait `MyTrait`
   --> $DIR/ice-120503-async-const-method.rs:6:5
    |
 LL | /     async const fn bar(&self) {
-LL | |
-LL | |
-LL | |
 ...  |
-LL | |
 LL | |     }
    | |_____^ not a member of trait `MyTrait`
 
diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr
index 1c58915111f..86234d15a5d 100644
--- a/tests/ui/traits/issue-78372.stderr
+++ b/tests/ui/traits/issue-78372.stderr
@@ -61,8 +61,8 @@ error[E0307]: invalid `self` parameter type: `Smaht<Self, T>`
 LL |     fn foo(self: Smaht<Self, T>);
    |                  ^^^^^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or some type implementing `Receiver`
-   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
   --> $DIR/issue-78372.rs:3:1
diff --git a/tests/ui/transmutability/alignment/align-fail.stderr b/tests/ui/transmutability/alignment/align-fail.stderr
index b9801e511b2..7b69820a3c6 100644
--- a/tests/ui/transmutability/alignment/align-fail.stderr
+++ b/tests/ui/transmutability/alignment/align-fail.stderr
@@ -16,7 +16,6 @@ LL | |             Assume {
 LL | |                 alignment: false,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_maybe_transmutable`
 help: consider removing the leading `&`-reference
diff --git a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr
index c975ff276c8..7e5d0a6d412 100644
--- a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr
+++ b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr
@@ -16,7 +16,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -38,7 +37,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -60,7 +58,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -82,7 +79,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -104,7 +100,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -126,7 +121,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -148,7 +142,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -170,7 +163,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -192,7 +184,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -214,7 +205,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -236,7 +226,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -258,7 +247,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -280,7 +268,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -302,7 +289,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -324,7 +310,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -346,7 +331,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -368,7 +352,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -390,7 +373,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -412,7 +394,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
@@ -434,7 +415,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_transmutable`
 
diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr
index 1698021d554..8d3ab4868da 100644
--- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr
+++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr
@@ -16,7 +16,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: false,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_maybe_transmutable`
 
diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr
index dbd3e39b365..8651f40f3fb 100644
--- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr
+++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr
@@ -16,7 +16,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: false,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_maybe_transmutable`
 
diff --git a/tests/ui/transmutability/references/unit-to-u8.stderr b/tests/ui/transmutability/references/unit-to-u8.stderr
index b5a79b1917f..bc9f286e097 100644
--- a/tests/ui/transmutability/references/unit-to-u8.stderr
+++ b/tests/ui/transmutability/references/unit-to-u8.stderr
@@ -16,7 +16,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_maybe_transmutable`
 
diff --git a/tests/ui/transmutability/uninhabited.stderr b/tests/ui/transmutability/uninhabited.stderr
index f112d2fbe44..b8b7b67f781 100644
--- a/tests/ui/transmutability/uninhabited.stderr
+++ b/tests/ui/transmutability/uninhabited.stderr
@@ -40,7 +40,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_maybe_transmutable`
 
@@ -62,7 +61,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_maybe_transmutable`
 
@@ -84,7 +82,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_maybe_transmutable`
 
@@ -106,7 +103,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_maybe_transmutable`
 
@@ -128,7 +124,6 @@ LL | |             Assume {
 LL | |                 alignment: true,
 LL | |                 lifetimes: true,
 ...  |
-LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_maybe_transmutable`
 
diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr
index 8888f2d49df..c7c93eee63e 100644
--- a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr
+++ b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr
@@ -24,10 +24,7 @@ error: item does not constrain `Bar::{opaque#0}`, but has it in its signature
    |
 LL |   async fn test<const N: crate::Bar>() {
    |  ______________________________________^
-LL | |
-LL | |
-LL | |
-LL | |     #[cfg(infer)]
+...  |
 LL | |     let x: u32 = N;
 LL | | }
    | |_^
diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
index be68bac5575..8547fd53c18 100644
--- a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
+++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
@@ -31,8 +31,7 @@ note: this definition site has more where clauses than the opaque type
    |
 LL | /     pub fn define_tait() -> Tait
 LL | |     where
-LL | |         // this proves `Bar<()>: Copy`, but `define_tait` is
-LL | |         // now uncallable
+...  |
 LL | |         (): Proj<Assoc = i32>,
    | |______________________________^
 
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
index 08ebc3208d7..293c8ea09f1 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
@@ -15,8 +15,7 @@ error: item does not constrain `FutNothing::{opaque#0}`, but has it in its signa
   --> $DIR/hkl_forbidden4.rs:22:1
    |
 LL | / {
-LL | |
-LL | |
+...  |
 LL | | }
    | |_^
    |
@@ -55,8 +54,7 @@ LL |   type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |                   -- this generic parameter must be used with a generic lifetime parameter
 ...
 LL | / {
-LL | |
-LL | |
+...  |
 LL | | }
    | |_^
 
diff --git a/tests/ui/typeck/issue-100285.stderr b/tests/ui/typeck/issue-100285.stderr
index 6f86fd18e0f..388510b7704 100644
--- a/tests/ui/typeck/issue-100285.stderr
+++ b/tests/ui/typeck/issue-100285.stderr
@@ -8,7 +8,6 @@ LL | |        if n < 0 {
 LL | |         return i;
 LL | |         } else if n < 10 {
 ...  |
-LL | |
 LL | |     }
    | |_____^ expected `i32`, found `()`
    |
diff --git a/tests/ui/typeck/issue-104513-ice.stderr b/tests/ui/typeck/issue-104513-ice.stderr
index 37d38a76a40..c3872ea8968 100644
--- a/tests/ui/typeck/issue-104513-ice.stderr
+++ b/tests/ui/typeck/issue-104513-ice.stderr
@@ -11,6 +11,9 @@ LL |     let _: S<impl Oops> = S;
    |              ^^^^^^^^^
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/typeck/rhs-ty-hint-134162.e2018.stderr b/tests/ui/typeck/rhs-ty-hint-134162.e2018.stderr
new file mode 100644
index 00000000000..ff189e36ba0
--- /dev/null
+++ b/tests/ui/typeck/rhs-ty-hint-134162.e2018.stderr
@@ -0,0 +1,11 @@
+error[E0369]: binary operation `==` cannot be applied to type `[X; 1]`
+  --> $DIR/rhs-ty-hint-134162.rs:16:17
+   |
+LL |     let _ = [X] == [panic!(); 2];
+   |             --- ^^ ------------- [_; 2]
+   |             |
+   |             [X; 1]
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/typeck/rhs-ty-hint-134162.e2021.stderr b/tests/ui/typeck/rhs-ty-hint-134162.e2021.stderr
new file mode 100644
index 00000000000..ff189e36ba0
--- /dev/null
+++ b/tests/ui/typeck/rhs-ty-hint-134162.e2021.stderr
@@ -0,0 +1,11 @@
+error[E0369]: binary operation `==` cannot be applied to type `[X; 1]`
+  --> $DIR/rhs-ty-hint-134162.rs:16:17
+   |
+LL |     let _ = [X] == [panic!(); 2];
+   |             --- ^^ ------------- [_; 2]
+   |             |
+   |             [X; 1]
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/typeck/rhs-ty-hint-134162.e2024.stderr b/tests/ui/typeck/rhs-ty-hint-134162.e2024.stderr
new file mode 100644
index 00000000000..ff189e36ba0
--- /dev/null
+++ b/tests/ui/typeck/rhs-ty-hint-134162.e2024.stderr
@@ -0,0 +1,11 @@
+error[E0369]: binary operation `==` cannot be applied to type `[X; 1]`
+  --> $DIR/rhs-ty-hint-134162.rs:16:17
+   |
+LL |     let _ = [X] == [panic!(); 2];
+   |             --- ^^ ------------- [_; 2]
+   |             |
+   |             [X; 1]
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/typeck/rhs-ty-hint-134162.rs b/tests/ui/typeck/rhs-ty-hint-134162.rs
new file mode 100644
index 00000000000..a14b4bcfd26
--- /dev/null
+++ b/tests/ui/typeck/rhs-ty-hint-134162.rs
@@ -0,0 +1,18 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/134162>.
+//!
+//! <https://github.com/rust-lang/rust/pull/110877> introduced RHS type hints for when a ty doesn't
+//! support a bin op. In the suggestion path, there was a `delay_bug`.
+//! <https://github.com/rust-lang/rust/pull/121208> converted this `delay_bug` to `bug`, which did
+//! not trigger any test failures as we did not have test coverage for this particular case. This
+//! manifested in an ICE as reported in <https://github.com/rust-lang/rust/issues/134162>.
+
+//@ revisions: e2018 e2021 e2024
+//@[e2018] edition: 2018
+//@[e2021] edition: 2021
+//@[e2024] edition: 2024
+
+fn main() {
+    struct X;
+    let _ = [X] == [panic!(); 2];
+    //[e2018,e2021,e2024]~^ ERROR binary operation `==` cannot be applied to type `[X; 1]`
+}
diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr
index 36bdc714e05..2a8c4edbdb5 100644
--- a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr
+++ b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr
@@ -22,8 +22,8 @@ error[E0307]: invalid `self` parameter type: `isize`
 LL |     fn foo(self: isize, x: isize) -> isize {
    |                  ^^^^^
    |
-   = note: type of `self` must be `Self` or some type implementing `Receiver`
-   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error[E0307]: invalid `self` parameter type: `Bar<isize>`
   --> $DIR/ufcs-explicit-self-bad.rs:19:18
@@ -31,8 +31,8 @@ error[E0307]: invalid `self` parameter type: `Bar<isize>`
 LL |     fn foo(self: Bar<isize>, x: isize) -> isize {
    |                  ^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or some type implementing `Receiver`
-   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error[E0307]: invalid `self` parameter type: `&Bar<usize>`
   --> $DIR/ufcs-explicit-self-bad.rs:23:18
@@ -40,8 +40,8 @@ error[E0307]: invalid `self` parameter type: `&Bar<usize>`
 LL |     fn bar(self: &Bar<usize>, x: isize) -> isize {
    |                  ^^^^^^^^^^^
    |
-   = note: type of `self` must be `Self` or some type implementing `Receiver`
-   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error[E0308]: mismatched `self` parameter type
   --> $DIR/ufcs-explicit-self-bad.rs:37:21
diff --git a/tests/ui/unsafe-binders/expr.rs b/tests/ui/unsafe-binders/expr.rs
new file mode 100644
index 00000000000..d8c4c2df2cd
--- /dev/null
+++ b/tests/ui/unsafe-binders/expr.rs
@@ -0,0 +1,13 @@
+#![feature(unsafe_binders)]
+//~^ WARN the feature `unsafe_binders` is incomplete
+
+use std::unsafe_binder::{wrap_binder, unwrap_binder};
+
+fn main() {
+    let x = 1;
+    let binder: unsafe<'a> &'a i32 = wrap_binder!(x);
+    //~^ ERROR unsafe binders are not yet implemented
+    //~| ERROR unsafe binders are not yet implemented
+    let rx = *unwrap_binder!(binder);
+    //~^ ERROR unsafe binders are not yet implemented
+}
diff --git a/tests/ui/unsafe-binders/expr.stderr b/tests/ui/unsafe-binders/expr.stderr
new file mode 100644
index 00000000000..26fae1958b0
--- /dev/null
+++ b/tests/ui/unsafe-binders/expr.stderr
@@ -0,0 +1,29 @@
+warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/expr.rs:1:12
+   |
+LL | #![feature(unsafe_binders)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: unsafe binders are not yet implemented
+  --> $DIR/expr.rs:8:17
+   |
+LL |     let binder: unsafe<'a> &'a i32 = wrap_binder!(x);
+   |                 ^^^^^^^^^^^^^^^^^^
+
+error: unsafe binders are not yet implemented
+  --> $DIR/expr.rs:8:51
+   |
+LL |     let binder: unsafe<'a> &'a i32 = wrap_binder!(x);
+   |                                                   ^
+
+error: unsafe binders are not yet implemented
+  --> $DIR/expr.rs:11:30
+   |
+LL |     let rx = *unwrap_binder!(binder);
+   |                              ^^^^^^
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
diff --git a/tests/ui/unsafe-binders/lifetime-resolution.rs b/tests/ui/unsafe-binders/lifetime-resolution.rs
new file mode 100644
index 00000000000..aebed9599d4
--- /dev/null
+++ b/tests/ui/unsafe-binders/lifetime-resolution.rs
@@ -0,0 +1,19 @@
+#![feature(unsafe_binders)]
+//~^ WARN the feature `unsafe_binders` is incomplete
+
+fn foo<'a>() {
+    let good: unsafe<'b> &'a &'b ();
+    //~^ ERROR unsafe binders are not yet implemented
+
+    let missing: unsafe<> &'missing ();
+    //~^ ERROR unsafe binders are not yet implemented
+    //~| ERROR use of undeclared lifetime name `'missing`
+
+    fn inner<'b>() {
+        let outer: unsafe<> &'a &'b ();
+        //~^ ERROR unsafe binders are not yet implemented
+        //~| can't use generic parameters from outer item
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/unsafe-binders/lifetime-resolution.stderr b/tests/ui/unsafe-binders/lifetime-resolution.stderr
new file mode 100644
index 00000000000..7a8ce929df1
--- /dev/null
+++ b/tests/ui/unsafe-binders/lifetime-resolution.stderr
@@ -0,0 +1,65 @@
+error[E0261]: use of undeclared lifetime name `'missing`
+  --> $DIR/lifetime-resolution.rs:8:28
+   |
+LL |     let missing: unsafe<> &'missing ();
+   |                            ^^^^^^^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the type lifetime-generic with a new `'missing` lifetime
+   |
+LL |     let missing: unsafe<'missing, > &'missing ();
+   |                         +++++++++
+help: consider introducing lifetime `'missing` here
+   |
+LL | fn foo<'missing, 'a>() {
+   |        +++++++++
+
+error[E0401]: can't use generic parameters from outer item
+  --> $DIR/lifetime-resolution.rs:13:30
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime parameter from outer item
+...
+LL |         let outer: unsafe<> &'a &'b ();
+   |                              ^^ use of generic parameter from outer item
+   |
+help: consider making the type lifetime-generic with a new `'a` lifetime
+   |
+LL |         let outer: unsafe<'a, > &'a &'b ();
+   |                           +++
+help: consider introducing lifetime `'a` here
+   |
+LL |     fn inner<'a, 'b>() {
+   |              +++
+
+warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/lifetime-resolution.rs:1:12
+   |
+LL | #![feature(unsafe_binders)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: unsafe binders are not yet implemented
+  --> $DIR/lifetime-resolution.rs:5:15
+   |
+LL |     let good: unsafe<'b> &'a &'b ();
+   |               ^^^^^^^^^^^^^^^^^^^^^
+
+error: unsafe binders are not yet implemented
+  --> $DIR/lifetime-resolution.rs:8:18
+   |
+LL |     let missing: unsafe<> &'missing ();
+   |                  ^^^^^^^^^^^^^^^^^^^^^
+
+error: unsafe binders are not yet implemented
+  --> $DIR/lifetime-resolution.rs:13:20
+   |
+LL |         let outer: unsafe<> &'a &'b ();
+   |                    ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0261, E0401.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/unsafe-binders/simple.rs b/tests/ui/unsafe-binders/simple.rs
new file mode 100644
index 00000000000..cebff2cbfb8
--- /dev/null
+++ b/tests/ui/unsafe-binders/simple.rs
@@ -0,0 +1,7 @@
+#![feature(unsafe_binders)]
+//~^ WARN the feature `unsafe_binders` is incomplete
+
+fn main() {
+    let x: unsafe<'a> &'a ();
+    //~^ ERROR unsafe binders are not yet implemented
+}
diff --git a/tests/ui/unsafe-binders/simple.stderr b/tests/ui/unsafe-binders/simple.stderr
new file mode 100644
index 00000000000..a21dbd00b4c
--- /dev/null
+++ b/tests/ui/unsafe-binders/simple.stderr
@@ -0,0 +1,17 @@
+warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/simple.rs:1:12
+   |
+LL | #![feature(unsafe_binders)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: unsafe binders are not yet implemented
+  --> $DIR/simple.rs:5:12
+   |
+LL |     let x: unsafe<'a> &'a ();
+   |            ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error; 1 warning emitted
+
diff --git a/tests/ui/while/while-else-err.stderr b/tests/ui/while/while-else-err.stderr
index b937956108f..face0c73925 100644
--- a/tests/ui/while/while-else-err.stderr
+++ b/tests/ui/while/while-else-err.stderr
@@ -6,8 +6,7 @@ LL |       while false {
 LL |
 LL |       } else {
    |  _______^
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |
diff --git a/tests/ui/while/while-else-let-else-err.stderr b/tests/ui/while/while-else-let-else-err.stderr
index 27d68ffdb24..4fc99409f78 100644
--- a/tests/ui/while/while-else-let-else-err.stderr
+++ b/tests/ui/while/while-else-let-else-err.stderr
@@ -6,8 +6,7 @@ LL |       let _ = while false {
 LL |
 LL |       } else {
    |  _______^
-LL | |
-LL | |
+...  |
 LL | |     };
    | |_____^
    |