about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes6
-rw-r--r--.gitmodules2
-rw-r--r--Cargo.lock37
-rw-r--r--compiler/rustc/Cargo.toml6
-rw-r--r--compiler/rustc/src/main.rs2
-rw-r--r--compiler/rustc_abi/src/lib.rs30
-rw-r--r--compiler/rustc_ast/src/ast.rs85
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs12
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs23
-rw-r--r--compiler/rustc_ast/src/util/parser.rs75
-rw-r--r--compiler/rustc_ast/src/visit.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs11
-rw-r--r--compiler/rustc_ast_passes/messages.ftl2
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs8
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs10
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs3
-rw-r--r--compiler/rustc_ast_passes/src/show_span.rs68
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs4
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs94
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs51
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs10
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl15
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs97
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs9
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs9
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs96
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs56
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs34
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs52
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs17
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/apple.rs2
-rw-r--r--compiler/rustc_const_eval/messages.ftl8
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs11
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs17
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/discriminant.rs45
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs11
-rw-r--r--compiler/rustc_const_eval/src/lib.rs1
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/mod.rs4
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs9
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0060.md13
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0622.md9
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs7
-rw-r--r--compiler/rustc_expand/src/expand.rs2
-rw-r--r--compiler/rustc_feature/src/removed.rs7
-rw-r--r--compiler/rustc_feature/src/unstable.rs4
-rw-r--r--compiler/rustc_hir/src/hir.rs18
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl2
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs24
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/dump.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs96
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs243
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs88
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs26
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs72
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs2
-rw-r--r--compiler/rustc_infer/src/traits/engine.rs2
-rw-r--r--compiler/rustc_interface/src/passes.rs5
-rw-r--r--compiler/rustc_interface/src/tests.rs2
-rw-r--r--compiler/rustc_lint/messages.ftl9
-rw-r--r--compiler/rustc_lint/src/builtin.rs2
-rw-r--r--compiler/rustc_lint/src/context.rs4
-rw-r--r--compiler/rustc_lint/src/drop_forget_useless.rs2
-rw-r--r--compiler/rustc_lint/src/if_let_rescope.rs7
-rw-r--r--compiler/rustc_lint/src/internal.rs50
-rw-r--r--compiler/rustc_lint/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/lints.rs41
-rw-r--r--compiler/rustc_lint/src/types.rs138
-rw-r--r--compiler/rustc_lint/src/unused.rs2
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs2
-rw-r--r--compiler/rustc_metadata/src/creader.rs9
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs12
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs3
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs26
-rw-r--r--compiler/rustc_middle/src/query/mod.rs7
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs84
-rw-r--r--compiler/rustc_middle/src/ty/util.rs33
-rw-r--r--compiler/rustc_middle/src/util/call_kind.rs7
-rw-r--r--compiler/rustc_mir_build/messages.ftl37
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_operand.rs2
-rw-r--r--compiler/rustc_mir_build/src/errors.rs30
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs309
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs14
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/cursor.rs5
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/results.rs15
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/counters.rs374
-rw-r--r--compiler/rustc_mir_transform/src/coverage/counters/tests.rs41
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs10
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs10
-rw-r--r--compiler/rustc_mir_transform/src/pass_manager.rs2
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs81
-rw-r--r--compiler/rustc_parse/messages.ftl3
-rw-r--r--compiler/rustc_parse/src/errors.rs22
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs35
-rw-r--r--compiler/rustc_parse/src/parser/item.rs30
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs2
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs23
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs5
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs8
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs8
-rw-r--r--compiler/rustc_passes/messages.ftl2
-rw-r--r--compiler/rustc_passes/src/check_const.rs236
-rw-r--r--compiler/rustc_passes/src/errors.rs7
-rw-r--r--compiler/rustc_passes/src/lib.rs2
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs1
-rw-r--r--compiler/rustc_resolve/src/lib.rs2
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs4
-rw-r--r--compiler/rustc_session/src/options.rs4
-rw-r--r--compiler/rustc_session/src/output.rs2
-rw-r--r--compiler/rustc_session/src/session.rs6
-rw-r--r--compiler/rustc_span/src/symbol.rs18
-rw-r--r--compiler/rustc_target/src/spec/base/aix.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs5
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/normalize.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs26
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs17
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs150
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs57
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs2
-rw-r--r--compiler/rustc_ty_utils/src/layout/invariant.rs16
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs2
-rw-r--r--library/alloc/src/ffi/c_str.rs32
-rw-r--r--library/alloc/src/ffi/c_str/tests.rs2
-rw-r--r--library/alloc/src/rc/tests.rs4
-rw-r--r--library/alloc/src/sync/tests.rs4
-rw-r--r--library/core/src/alloc/layout.rs2
-rw-r--r--library/core/src/arch.rs27
-rw-r--r--library/core/src/hash/mod.rs6
-rw-r--r--library/core/src/intrinsics/mod.rs14
-rw-r--r--library/core/src/intrinsics/simd.rs14
-rw-r--r--library/core/src/mem/maybe_uninit.rs4
-rw-r--r--library/core/src/mem/mod.rs6
-rw-r--r--library/core/src/num/f16.rs2
-rw-r--r--library/core/src/num/nonzero.rs34
-rw-r--r--library/core/src/num/uint_macros.rs2
-rw-r--r--library/core/src/ptr/non_null.rs53
-rw-r--r--library/core/src/slice/mod.rs2
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/core/tests/ptr.rs1
-rw-r--r--library/std/src/collections/hash/map.rs24
-rw-r--r--library/std/src/collections/hash/set.rs24
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/sys/pal/unix/process/process_common.rs2
-rw-r--r--library/std/src/thread/mod.rs6
-rw-r--r--src/bootstrap/Cargo.lock8
-rw-r--r--src/bootstrap/Cargo.toml2
-rw-r--r--src/bootstrap/src/bin/main.rs20
-rw-r--r--src/bootstrap/src/bin/rustc.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/check.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs10
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs30
-rw-r--r--src/bootstrap/src/core/build_steps/format.rs6
-rw-r--r--src/bootstrap/src/core/build_steps/setup.rs40
-rw-r--r--src/bootstrap/src/core/build_steps/suggest.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs10
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs11
-rw-r--r--src/bootstrap/src/core/builder/mod.rs109
-rw-r--r--src/bootstrap/src/core/builder/tests.rs46
-rw-r--r--src/bootstrap/src/core/config/config.rs135
-rw-r--r--src/bootstrap/src/core/config/flags.rs4
-rw-r--r--src/bootstrap/src/core/download.rs26
-rw-r--r--src/bootstrap/src/core/sanity.rs4
-rw-r--r--src/bootstrap/src/lib.rs28
-rw-r--r--src/bootstrap/src/utils/cc_detect.rs10
-rw-r--r--src/bootstrap/src/utils/helpers.rs6
-rw-r--r--src/bootstrap/src/utils/metrics.rs9
-rw-r--r--src/bootstrap/src/utils/render_tests.rs36
-rw-r--r--src/bootstrap/src/utils/tarball.rs2
-rw-r--r--src/ci/github-actions/jobs.yml1
-rw-r--r--src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md7
-rw-r--r--src/doc/unstable-book/src/compiler-flags/randomize-layout.md23
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/formats/renderer.rs25
-rw-r--r--src/librustdoc/html/markdown.rs116
-rw-r--r--src/librustdoc/html/render/context.rs2
-rw-r--r--src/librustdoc/html/sources.rs50
-rw-r--r--src/librustdoc/json/conversions.rs29
-rw-r--r--src/librustdoc/json/mod.rs9
-rw-r--r--src/librustdoc/lib.rs2
m---------src/llvm-project0
-rw-r--r--src/rustdoc-json-types/lib.rs18
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/deprecated_lints.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_include_file.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_utils.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/neg_multiply.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_slicing.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/unnamed_address.rs60
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs2
-rw-r--r--src/tools/clippy/tests/ui/fn_address_comparisons.rs23
-rw-r--r--src/tools/clippy/tests/ui/fn_address_comparisons.stderr17
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed2
-rw-r--r--src/tools/clippy/tests/ui/rename.rs2
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr140
-rw-r--r--src/tools/compiletest/src/common.rs22
-rw-r--r--src/tools/compiletest/src/compute_diff.rs2
-rw-r--r--src/tools/compiletest/src/debuggers.rs6
-rw-r--r--src/tools/compiletest/src/directive-list.rs2
-rw-r--r--src/tools/compiletest/src/header.rs12
-rw-r--r--src/tools/compiletest/src/header/needs.rs51
-rw-r--r--src/tools/compiletest/src/header/tests.rs37
-rw-r--r--src/tools/compiletest/src/lib.rs10
-rw-r--r--src/tools/compiletest/src/runtest.rs72
-rw-r--r--src/tools/compiletest/src/runtest/codegen_units.rs22
-rw-r--r--src/tools/compiletest/src/runtest/debuginfo.rs10
-rw-r--r--src/tools/compiletest/src/runtest/rustdoc_json.rs2
-rw-r--r--src/tools/compiletest/src/runtest/ui.rs4
-rw-r--r--src/tools/compiletest/src/util.rs2
-rw-r--r--src/tools/miri/Cargo.toml4
-rw-r--r--src/tools/miri/src/bin/miri.rs2
-rw-r--r--src/tools/miri/tests/fail/breakpoint.rs4
-rw-r--r--src/tools/miri/tests/fail/breakpoint.stderr4
-rw-r--r--src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs27
-rw-r--r--src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr15
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs3
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs4
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-mem.rs10
-rw-r--r--src/tools/miri/tests/pass/async-closure-captures.rs2
-rw-r--r--src/tools/miri/tests/pass/async-closure-drop.rs2
-rw-r--r--src/tools/miri/tests/pass/function_pointers.rs2
-rw-r--r--src/tools/miri/tests/pass/issues/issue-91636.rs2
-rw-r--r--src/tools/rust-analyzer/crates/profile/src/memory_usage.rs4
-rw-r--r--src/tools/tidy/src/deps.rs2
-rw-r--r--src/tools/tidy/src/error_codes.rs6
-rw-r--r--src/tools/tidy/src/features.rs8
-rw-r--r--src/tools/tidy/src/fluent_period.rs1
-rw-r--r--src/tools/tidy/src/unstable_book.rs8
-rw-r--r--src/tools/tidy/src/x_version.rs2
-rw-r--r--src/tools/wasm-component-ld/Cargo.toml2
-rw-r--r--tests/assembly/breakpoint.rs14
-rw-r--r--tests/assembly/x86_64-bigint-helpers.rs (renamed from tests/assembly/x86_64-bigint-add.rs)25
-rw-r--r--tests/codegen/async-closure-debug.rs2
-rw-r--r--tests/codegen/issues/issue-98678-async.rs25
-rw-r--r--tests/codegen/issues/issue-98678-closure-coroutine.rs22
-rw-r--r--tests/codegen/issues/issue-98678-enum.rs40
-rw-r--r--tests/codegen/issues/issue-98678-struct-union.rs25
-rw-r--r--tests/coverage/abort.cov-map26
-rw-r--r--tests/coverage/assert.cov-map31
-rw-r--r--tests/coverage/async.cov-map27
-rw-r--r--tests/coverage/async_closure.cov-map8
-rw-r--r--tests/coverage/async_closure.coverage2
-rw-r--r--tests/coverage/async_closure.rs2
-rw-r--r--tests/coverage/branch/guard.cov-map14
-rw-r--r--tests/coverage/branch/if.cov-map28
-rw-r--r--tests/coverage/branch/lazy-boolean.cov-map170
-rw-r--r--tests/coverage/branch/match-arms.cov-map76
-rw-r--r--tests/coverage/branch/no-mir-spans.cov-map14
-rw-r--r--tests/coverage/branch/while.cov-map43
-rw-r--r--tests/coverage/closure_macro.cov-map8
-rw-r--r--tests/coverage/closure_macro_async.cov-map8
-rw-r--r--tests/coverage/condition/conditions.cov-map73
-rw-r--r--tests/coverage/conditions.cov-map508
-rw-r--r--tests/coverage/continue.cov-map18
-rw-r--r--tests/coverage/coroutine.cov-map18
-rw-r--r--tests/coverage/inline-dead.cov-map8
-rw-r--r--tests/coverage/inline.cov-map17
-rw-r--r--tests/coverage/issue-84561.cov-map192
-rw-r--r--tests/coverage/lazy_boolean.cov-map40
-rw-r--r--tests/coverage/loops_branches.cov-map223
-rw-r--r--tests/coverage/mcdc/condition-limit.cov-map154
-rw-r--r--tests/coverage/mcdc/if.cov-map262
-rw-r--r--tests/coverage/mcdc/inlined_expressions.cov-map13
-rw-r--r--tests/coverage/mcdc/nested_if.cov-map268
-rw-r--r--tests/coverage/mcdc/non_control_flow.cov-map143
-rw-r--r--tests/coverage/nested_loops.cov-map76
-rw-r--r--tests/coverage/overflow.cov-map31
-rw-r--r--tests/coverage/panic_unwind.cov-map31
-rw-r--r--tests/coverage/simple_match.cov-map20
-rw-r--r--tests/coverage/try_error_result.cov-map242
-rw-r--r--tests/coverage/unicode.cov-map24
-rw-r--r--tests/coverage/unused.cov-map20
-rw-r--r--tests/coverage/while_early_ret.cov-map19
-rw-r--r--tests/coverage/yield.cov-map24
-rw-r--r--tests/crashes/121429.rs11
-rw-r--r--tests/crashes/124020.rs4
-rw-r--r--tests/crashes/125476.rs4
-rw-r--r--tests/crashes/126267.rs30
-rw-r--r--tests/crashes/128176.rs13
-rw-r--r--tests/crashes/131538.rs13
-rw-r--r--tests/crashes/132320.rs15
-rw-r--r--tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff14
-rw-r--r--tests/mir-opt/dataflow.main.maybe_init.borrowck.dot6
-rw-r--r--tests/mir-opt/dataflow.rs6
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff12
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff12
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff12
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff12
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir184
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir134
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir118
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir118
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir132
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir132
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir12
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir12
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir58
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir58
-rw-r--r--tests/run-make/apple-deployment-target/rmake.rs34
-rw-r--r--tests/run-make/apple-sdk-version/rmake.rs3
-rw-r--r--tests/run-make/libtest-thread-limit/rmake.rs2
-rw-r--r--tests/rustdoc-json/impls/trait-for-dyn-trait.rs15
-rw-r--r--tests/rustdoc-json/statics/extern.rs39
-rw-r--r--tests/rustdoc-json/statics/statics.rs12
-rw-r--r--tests/ui-fulldeps/pprust-parenthesis-insertion.rs228
-rw-r--r--tests/ui/README.md6
-rw-r--r--tests/ui/associated-consts/associated-const-type-parameter-pattern.rs8
-rw-r--r--tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr47
-rw-r--r--tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs2
-rw-r--r--tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs2
-rw-r--r--tests/ui/async-await/async-closures/auxiliary/foreign.rs2
-rw-r--r--tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs2
-rw-r--r--tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs2
-rw-r--r--tests/ui/async-await/async-closures/brand.rs2
-rw-r--r--tests/ui/async-await/async-closures/captures.rs6
-rw-r--r--tests/ui/async-await/async-closures/clone-closure.rs2
-rw-r--r--tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs4
-rw-r--r--tests/ui/async-await/async-closures/debuginfo-by-move-body.rs2
-rw-r--r--tests/ui/async-await/async-closures/drop.rs2
-rw-r--r--tests/ui/async-await/async-closures/fn-exception-target-features.rs2
-rw-r--r--tests/ui/async-await/async-closures/fn-exception-target-features.stderr4
-rw-r--r--tests/ui/async-await/async-closures/fn-exception.rs2
-rw-r--r--tests/ui/async-await/async-closures/fn-exception.stderr8
-rw-r--r--tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs2
-rw-r--r--tests/ui/async-await/async-closures/foreign.rs2
-rw-r--r--tests/ui/async-await/async-closures/implements-fnmut.rs2
-rw-r--r--tests/ui/async-await/async-closures/inline-body.rs2
-rw-r--r--tests/ui/async-await/async-closures/mangle.rs4
-rw-r--r--tests/ui/async-await/async-closures/moro-example.rs2
-rw-r--r--tests/ui/async-await/async-closures/move-is-async-fn.rs2
-rw-r--r--tests/ui/async-await/async-closures/mut-ref-reborrow.rs2
-rw-r--r--tests/ui/async-await/async-closures/no-borrow-from-env.rs2
-rw-r--r--tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs2
-rw-r--r--tests/ui/async-await/async-closures/overlapping-projs.rs2
-rw-r--r--tests/ui/async-await/async-closures/precise-captures.rs6
-rw-r--r--tests/ui/async-await/async-closures/refd.rs8
-rw-r--r--tests/ui/async-await/async-closures/signature-deduction.rs2
-rw-r--r--tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs2
-rw-r--r--tests/ui/async-await/async-closures/wrong-fn-kind.rs4
-rw-r--r--tests/ui/async-await/async-closures/wrong-fn-kind.stderr16
-rw-r--r--tests/ui/async-await/async-fn/dyn-pos.rs2
-rw-r--r--tests/ui/async-await/async-fn/dyn-pos.stderr4
-rw-r--r--tests/ui/async-await/async-fn/edition-2015.rs4
-rw-r--r--tests/ui/async-await/async-fn/edition-2015.stderr12
-rw-r--r--tests/ui/async-await/async-fn/higher-ranked-async-fn.rs2
-rw-r--r--tests/ui/async-await/async-fn/impl-trait.rs6
-rw-r--r--tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs4
-rw-r--r--tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr12
-rw-r--r--tests/ui/async-await/async-fn/not-a-trait.rs2
-rw-r--r--tests/ui/async-await/async-fn/project.rs4
-rw-r--r--tests/ui/async-await/async-fn/sugar.rs2
-rw-r--r--tests/ui/async-await/async-fn/trait-bounds-in-macro.rs2
-rw-r--r--tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr6
-rw-r--r--tests/ui/async-await/async-fn/wrong-trait.rs2
-rw-r--r--tests/ui/attributes/dump_def_parents.rs5
-rw-r--r--tests/ui/attributes/dump_def_parents.stderr73
-rw-r--r--tests/ui/binding/const-param.rs2
-rw-r--r--tests/ui/binding/const-param.stderr7
-rw-r--r--tests/ui/binop/binary-op-on-fn-ptr-eq.rs3
-rw-r--r--tests/ui/box/unit/unique-ffi-symbols.rs3
-rw-r--r--tests/ui/check-cfg/and-more-diagnostic.rs13
-rw-r--r--tests/ui/check-cfg/and-more-diagnostic.stderr12
-rw-r--r--tests/ui/check-cfg/mix.rs2
-rw-r--r--tests/ui/check-cfg/mix.stderr11
-rw-r--r--tests/ui/check-cfg/target_feature.rs18
-rw-r--r--tests/ui/check-cfg/target_feature.stderr297
-rw-r--r--tests/ui/check-cfg/well-known-values.rs4
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr11
-rw-r--r--tests/ui/coercion/coerce-loop-issue-122561.rs12
-rw-r--r--tests/ui/coercion/coerce-loop-issue-122561.stderr73
-rw-r--r--tests/ui/const-generics/generic_arg_infer/array-repeat-expr-lib.rs12
-rw-r--r--tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr14
-rw-r--r--tests/ui/const-generics/issues/cg-in-dyn-issue-128176.rs18
-rw-r--r--tests/ui/const-generics/issues/issue-83765.stderr8
-rw-r--r--tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs3
-rw-r--r--tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr8
-rw-r--r--tests/ui/consts/const-eval-fail-too-big.rs12
-rw-r--r--tests/ui/consts/const-eval-fail-too-big.stderr9
-rw-r--r--tests/ui/consts/const-eval/const-eval-overflow-2.rs3
-rw-r--r--tests/ui/consts/const-eval/const-eval-overflow-2.stderr8
-rw-r--r--tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr8
-rw-r--r--tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr8
-rw-r--r--tests/ui/consts/const-eval/ref_to_int_match.rs2
-rw-r--r--tests/ui/consts/const-extern-function.rs2
-rw-r--r--tests/ui/consts/const-fn-error.rs5
-rw-r--r--tests/ui/consts/const-fn-error.stderr27
-rw-r--r--tests/ui/consts/const-for-feature-gate.rs5
-rw-r--r--tests/ui/consts/const-for-feature-gate.stderr22
-rw-r--r--tests/ui/consts/const-for.rs4
-rw-r--r--tests/ui/consts/const-for.stderr7
-rw-r--r--tests/ui/consts/const-integer-bool-ops.stderr60
-rw-r--r--tests/ui/consts/const-mut-refs/issue-76510.stderr6
-rw-r--r--tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs1
-rw-r--r--tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr4
-rw-r--r--tests/ui/consts/const-size_of_val-align_of_val.rs3
-rw-r--r--tests/ui/consts/const-try-feature-gate.rs5
-rw-r--r--tests/ui/consts/const-try-feature-gate.stderr23
-rw-r--r--tests/ui/consts/const-try.rs4
-rw-r--r--tests/ui/consts/const-try.stderr4
-rw-r--r--tests/ui/consts/const-tup-index-span.stderr6
-rw-r--r--tests/ui/consts/const_in_pattern/cross-crate-fail.rs6
-rw-r--r--tests/ui/consts/const_in_pattern/cross-crate-fail.stderr28
-rw-r--r--tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr36
-rw-r--r--tests/ui/consts/const_in_pattern/issue-44333.stderr18
-rw-r--r--tests/ui/consts/const_in_pattern/issue-65466.rs2
-rw-r--r--tests/ui/consts/const_in_pattern/issue-65466.stderr12
-rw-r--r--tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs3
-rw-r--r--tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr11
-rw-r--r--tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs2
-rw-r--r--tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr12
-rw-r--r--tests/ui/consts/const_in_pattern/reject_non_structural.rs90
-rw-r--r--tests/ui/consts/const_in_pattern/reject_non_structural.stderr199
-rw-r--r--tests/ui/consts/const_refs_to_static_fail_invalid.rs6
-rw-r--r--tests/ui/consts/const_refs_to_static_fail_invalid.stderr20
-rw-r--r--tests/ui/consts/control-flow/loop.rs12
-rw-r--r--tests/ui/consts/control-flow/loop.stderr47
-rw-r--r--tests/ui/consts/control-flow/try.rs6
-rw-r--r--tests/ui/consts/control-flow/try.stderr23
-rw-r--r--tests/ui/consts/invalid-inline-const-in-match-arm.stderr2
-rw-r--r--tests/ui/consts/issue-43105.rs3
-rw-r--r--tests/ui/consts/issue-43105.stderr8
-rw-r--r--tests/ui/consts/issue-54954.stderr18
-rw-r--r--tests/ui/consts/issue-73976-polymorphic.rs4
-rw-r--r--tests/ui/consts/issue-73976-polymorphic.stderr22
-rw-r--r--tests/ui/consts/issue-78655.rs3
-rw-r--r--tests/ui/consts/issue-78655.stderr8
-rw-r--r--tests/ui/consts/issue-79137-toogeneric.rs2
-rw-r--r--tests/ui/consts/issue-79137-toogeneric.stderr11
-rw-r--r--tests/ui/consts/issue-87046.stderr3
-rw-r--r--tests/ui/consts/issue-89088.rs2
-rw-r--r--tests/ui/consts/issue-89088.stderr11
-rw-r--r--tests/ui/consts/match_ice.rs3
-rw-r--r--tests/ui/consts/match_ice.stderr11
-rw-r--r--tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs12
-rw-r--r--tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr26
-rw-r--r--tests/ui/consts/missing_assoc_const_type.rs5
-rw-r--r--tests/ui/consts/missing_assoc_const_type.stderr8
-rw-r--r--tests/ui/consts/missing_assoc_const_type2.stderr6
-rw-r--r--tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr6
-rw-r--r--tests/ui/consts/promoted_size_overflow.rs7
-rw-r--r--tests/ui/consts/promoted_size_overflow.stderr9
-rw-r--r--tests/ui/consts/transmute-size-mismatch-before-typeck.rs2
-rw-r--r--tests/ui/consts/transmute-size-mismatch-before-typeck.stderr8
-rw-r--r--tests/ui/consts/try-operator.stderr16
-rw-r--r--tests/ui/consts/uninhabited-const-issue-61744.rs6
-rw-r--r--tests/ui/consts/uninhabited-const-issue-61744.stderr14
-rw-r--r--tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs2
-rw-r--r--tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr10
-rw-r--r--tests/ui/cross-crate/const-cross-crate-extern.rs2
-rw-r--r--tests/ui/deriving/deriving-coerce-pointee-neg.rs6
-rw-r--r--tests/ui/deriving/deriving-coerce-pointee-neg.stderr8
-rw-r--r--tests/ui/drop/lint-if-let-rescope.fixed24
-rw-r--r--tests/ui/drop/lint-if-let-rescope.rs22
-rw-r--r--tests/ui/drop/lint-if-let-rescope.stderr34
-rw-r--r--tests/ui/enum-discriminant/issue-41394.stderr6
-rw-r--r--tests/ui/error-codes/E0622.rs4
-rw-r--r--tests/ui/error-codes/E0622.stderr4
-rw-r--r--tests/ui/explicit-tail-calls/ctfe-id-unlimited.return.stderr6
-rw-r--r--tests/ui/extern/extern-compare-with-return-type.rs1
-rw-r--r--tests/ui/extern/extern-take-value.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-async-trait-bounds.rs7
-rw-r--r--tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr24
-rw-r--r--tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr12
-rw-r--r--tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs2
-rw-r--r--tests/ui/generic-associated-types/extended/lending_iterator.rs9
-rw-r--r--tests/ui/generic-associated-types/extended/lending_iterator.stderr (renamed from tests/ui/generic-associated-types/extended/lending_iterator.base.stderr)4
-rw-r--r--tests/ui/generic-associated-types/extended/lending_iterator_2.rs8
-rw-r--r--tests/ui/generic-associated-types/extended/lending_iterator_2.stderr (renamed from tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr)2
-rw-r--r--tests/ui/generic-associated-types/gat-in-trait-path.rs12
-rw-r--r--tests/ui/generic-associated-types/gat-in-trait-path.stderr58
-rw-r--r--tests/ui/generic-associated-types/issue-67510-pass.rs9
-rw-r--r--tests/ui/generic-associated-types/issue-67510-pass.stderr18
-rw-r--r--tests/ui/generic-associated-types/issue-76535.rs9
-rw-r--r--tests/ui/generic-associated-types/issue-76535.stderr55
-rw-r--r--tests/ui/generic-associated-types/issue-78671.rs7
-rw-r--r--tests/ui/generic-associated-types/issue-78671.stderr35
-rw-r--r--tests/ui/generic-associated-types/issue-79422.rs10
-rw-r--r--tests/ui/generic-associated-types/issue-79422.stderr57
-rw-r--r--tests/ui/generic-associated-types/trait-objects.rs12
-rw-r--r--tests/ui/generic-associated-types/trait-objects.stderr48
-rw-r--r--tests/ui/higher-ranked/structually-relate-aliases.rs1
-rw-r--r--tests/ui/higher-ranked/structually-relate-aliases.stderr13
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr14
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs1
-rw-r--r--tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr4
-rw-r--r--tests/ui/impl-trait/issues/issue-86800.rs1
-rw-r--r--tests/ui/impl-trait/issues/issue-86800.stderr20
-rw-r--r--tests/ui/impl-trait/precise-capturing/bound-modifiers.rs2
-rw-r--r--tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr6
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs1
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr20
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr10
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other2.rs2
-rw-r--r--tests/ui/inline-const/const-match-pat-generic.rs4
-rw-r--r--tests/ui/inline-const/const-match-pat-generic.stderr8
-rw-r--r--tests/ui/inline-const/pat-match-fndef.stderr4
-rw-r--r--tests/ui/issues/issue-50582.rs1
-rw-r--r--tests/ui/issues/issue-50582.stderr15
-rw-r--r--tests/ui/issues/issue-50585.rs1
-rw-r--r--tests/ui/issues/issue-50585.stderr15
-rw-r--r--tests/ui/issues/issue-54696.rs2
-rw-r--r--tests/ui/layout/base-layout-is-sized-ice-123078.stderr6
-rw-r--r--tests/ui/limits/issue-55878.stderr17
-rw-r--r--tests/ui/lint/fn-ptr-comparisons-weird.rs15
-rw-r--r--tests/ui/lint/fn-ptr-comparisons-weird.stderr43
-rw-r--r--tests/ui/lint/fn-ptr-comparisons.fixed58
-rw-r--r--tests/ui/lint/fn-ptr-comparisons.rs58
-rw-r--r--tests/ui/lint/fn-ptr-comparisons.stderr171
-rw-r--r--tests/ui/lint/forbid-group-group-2.stderr54
-rw-r--r--tests/ui/lint/forbid-group-member.stderr14
-rw-r--r--tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr396
-rw-r--r--tests/ui/lint/outer-forbid.stderr414
-rw-r--r--tests/ui/match/issue-70972-dyn-trait.stderr7
-rw-r--r--tests/ui/match/issue-72896-non-partial-eq-const.rs2
-rw-r--r--tests/ui/match/issue-72896-non-partial-eq-const.stderr12
-rw-r--r--tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs2
-rw-r--r--tests/ui/never_type/issue-52443.rs5
-rw-r--r--tests/ui/never_type/issue-52443.stderr21
-rw-r--r--tests/ui/nll/closure-requirements/thread_scope_correct_implied_bound.rs23
-rw-r--r--tests/ui/nll/closure-requirements/thread_scope_incorrect_implied_bound.rs21
-rw-r--r--tests/ui/nll/closure-requirements/thread_scope_incorrect_implied_bound.stderr17
-rw-r--r--tests/ui/nll/ty-outlives/projection-implied-bounds.rs2
-rw-r--r--tests/ui/nll/ty-outlives/projection-implied-bounds.stderr2
-rw-r--r--tests/ui/parser/bad-recover-kw-after-impl.rs2
-rw-r--r--tests/ui/parser/bad-recover-kw-after-impl.stderr6
-rw-r--r--tests/ui/parser/typed-self-param.rs14
-rw-r--r--tests/ui/parser/typed-self-param.stderr50
-rw-r--r--tests/ui/pattern/issue-115599.rs2
-rw-r--r--tests/ui/pattern/issue-115599.stderr11
-rw-r--r--tests/ui/pattern/issue-72565.stderr7
-rw-r--r--tests/ui/pattern/non-constant-in-const-path.stderr14
-rw-r--r--tests/ui/pattern/non-structural-match-types.stderr8
-rw-r--r--tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs2
-rw-r--r--tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr17
-rw-r--r--tests/ui/pattern/usefulness/consts-opaque.stderr72
-rw-r--r--tests/ui/print-request/macos-target.rs1
-rw-r--r--tests/ui/print-request/macos-target.stdout2
-rw-r--r--tests/ui/process/env-funky-keys.rs4
-rw-r--r--tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr14
-rw-r--r--tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr14
-rw-r--r--tests/ui/resolve/issue-50599.stderr6
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs2
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr17
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs2
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr17
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs2
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr17
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs2
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr17
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs2
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr17
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs2
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr17
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr90
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs3
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr12
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs12
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr38
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr18
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr35
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs4
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr19
-rw-r--r--tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr6
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs-ice.stderr6
-rw-r--r--tests/ui/self/arbitrary-self-opaque.rs1
-rw-r--r--tests/ui/self/arbitrary-self-opaque.stderr14
-rw-r--r--tests/ui/simd/intrinsic/float-math-pass.rs4
-rw-r--r--tests/ui/traits/bound/unknown-assoc-with-const-arg.rs2
-rw-r--r--tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr22
-rw-r--r--tests/ui/traits/const-traits/hir-const-check.rs6
-rw-r--r--tests/ui/traits/const-traits/hir-const-check.stderr23
-rw-r--r--tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs4
-rw-r--r--tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr4
-rw-r--r--tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr14
-rw-r--r--tests/ui/traits/const-traits/overlap-const-with-nonconst.rs38
-rw-r--r--tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr24
-rw-r--r--tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr26
-rw-r--r--tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr12
-rw-r--r--tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs8
-rw-r--r--tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr22
-rw-r--r--tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr8
-rw-r--r--tests/ui/traits/const-traits/specializing-constness.rs3
-rw-r--r--tests/ui/traits/const-traits/specializing-constness.stderr8
-rw-r--r--tests/ui/traits/const-traits/trait-default-body-stability.stderr4
-rw-r--r--tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr22
-rw-r--r--tests/ui/traits/next-solver/issue-118950-root-region.rs2
-rw-r--r--tests/ui/traits/next-solver/issue-118950-root-region.stderr13
-rw-r--r--tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs46
-rw-r--r--tests/ui/traits/next-solver/typeck/structurally-resolve-in-probe_adt.rs15
-rw-r--r--tests/ui/transmutability/uninhabited.rs16
-rw-r--r--tests/ui/transmutability/uninhabited.stderr24
-rw-r--r--tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr22
-rw-r--r--tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr16
-rw-r--r--tests/ui/type-alias-impl-trait/const_generic_type.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden4.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr22
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference3.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr7
-rw-r--r--tests/ui/type-alias-impl-trait/structural-match.stderr7
-rw-r--r--tests/ui/type/type-dependent-def-issue-49241.stderr6
-rw-r--r--tests/ui/union/union-const-pat.stderr5
-rw-r--r--triagebot.toml1
648 files changed, 9396 insertions, 5747 deletions
diff --git a/.gitattributes b/.gitattributes
index d29c15fe712..a02c95fbd48 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -4,8 +4,10 @@
 *.cpp rust
 *.h rust
 *.rs rust diff=rust
-*.fixed linguist-language=Rust
-*.mir linguist-language=Rust
+*.fixed linguist-language=Rust -merge
+*.mir linguist-language=Rust -merge
+*.stderr -merge
+*.stdout -merge
 src/etc/installer/gfx/* binary
 src/vendor/** -text
 Cargo.lock linguist-generated=false
diff --git a/.gitmodules b/.gitmodules
index 33ea0f53cf1..07fd44c2b2d 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -33,7 +33,7 @@
 [submodule "src/llvm-project"]
 	path = src/llvm-project
 	url = https://github.com/rust-lang/llvm-project.git
-	branch = rustc/19.1-2024-09-17
+	branch = rustc/19.1-2024-12-03
 	shallow = true
 [submodule "src/doc/embedded-book"]
 	path = src/doc/embedded-book
diff --git a/Cargo.lock b/Cargo.lock
index 8ccf05cc5b8..f59dcdcf28d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1878,16 +1878,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
 
 [[package]]
-name = "jemalloc-sys"
-version = "0.5.4+5.3.0-patched"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
 name = "jobserver"
 version = "0.1.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2287,7 +2277,6 @@ dependencies = [
  "ctrlc",
  "directories",
  "getrandom",
- "jemalloc-sys",
  "libc",
  "libffi",
  "libloading",
@@ -2297,6 +2286,7 @@ dependencies = [
  "rustc_version",
  "smallvec",
  "tempfile",
+ "tikv-jemalloc-sys",
  "ui_test",
  "windows-sys 0.52.0",
 ]
@@ -3151,12 +3141,12 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
 name = "rustc-main"
 version = "0.0.0"
 dependencies = [
- "jemalloc-sys",
  "rustc_codegen_ssa",
  "rustc_driver",
  "rustc_driver_impl",
  "rustc_smir",
  "stable_mir",
+ "tikv-jemalloc-sys",
 ]
 
 [[package]]
@@ -5261,6 +5251,16 @@ name = "tier-check"
 version = "0.1.0"
 
 [[package]]
+name = "tikv-jemalloc-sys"
+version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
 name = "time"
 version = "0.3.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5803,17 +5803,20 @@ checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
 
 [[package]]
 name = "wasm-component-ld"
-version = "0.5.10"
+version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d4aa6bd7fbe7cffbed29fe3e236fda74419def1bdef6f80f989ec51137edf44"
+checksum = "a2b05c3820968b335f10e703218459e4fd2cc91fdfc8f7936a993f1aacaa0938"
 dependencies = [
  "anyhow",
  "clap",
  "lexopt",
+ "libc",
  "tempfile",
  "wasi-preview1-component-adapter-provider",
  "wasmparser 0.219.1",
  "wat",
+ "windows-sys 0.59.0",
+ "winsplit",
  "wit-component",
  "wit-parser",
 ]
@@ -6186,6 +6189,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "winsplit"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ab703352da6a72f35c39a533526393725640575bb211f61987a2748323ad956"
+
+[[package]]
 name = "wit-component"
 version = "0.219.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml
index f85c30ac7ec..d24b630516a 100644
--- a/compiler/rustc/Cargo.toml
+++ b/compiler/rustc/Cargo.toml
@@ -20,14 +20,14 @@ rustc_smir = { path = "../rustc_smir" }
 stable_mir = { path = "../stable_mir" }
 # tidy-alphabetical-end
 
-[dependencies.jemalloc-sys]
-version = "0.5.0"
+[dependencies.tikv-jemalloc-sys]
+version = "0.6.0"
 optional = true
 features = ['unprefixed_malloc_on_supported_platforms']
 
 [features]
 # tidy-alphabetical-start
-jemalloc = ['dep:jemalloc-sys']
+jemalloc = ['dep:tikv-jemalloc-sys']
 llvm = ['rustc_driver_impl/llvm']
 max_level_info = ['rustc_driver_impl/max_level_info']
 rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts']
diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs
index ccf88d8ff4b..a55a63a7bf1 100644
--- a/compiler/rustc/src/main.rs
+++ b/compiler/rustc/src/main.rs
@@ -43,6 +43,8 @@ fn main() {
     {
         use std::os::raw::{c_int, c_void};
 
+        use tikv_jemalloc_sys as jemalloc_sys;
+
         #[used]
         static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc;
         #[used]
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 2e51753ede6..15a27c0b6ee 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1215,6 +1215,15 @@ impl Scalar {
             Scalar::Union { .. } => true,
         }
     }
+
+    /// Returns `true` if this is a signed integer scalar
+    #[inline]
+    pub fn is_signed(&self) -> bool {
+        match self.primitive() {
+            Primitive::Int(_, signed) => signed,
+            _ => false,
+        }
+    }
 }
 
 // NOTE: This struct is generic over the FieldIdx for rust-analyzer usage.
@@ -1401,10 +1410,7 @@ impl BackendRepr {
     #[inline]
     pub fn is_signed(&self) -> bool {
         match self {
-            BackendRepr::Scalar(scal) => match scal.primitive() {
-                Primitive::Int(_, signed) => signed,
-                _ => false,
-            },
+            BackendRepr::Scalar(scal) => scal.is_signed(),
             _ => panic!("`is_signed` on non-scalar ABI {self:?}"),
         }
     }
@@ -1499,7 +1505,11 @@ impl BackendRepr {
 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
 pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
-    Single { index: VariantIdx },
+    Single {
+        /// Always 0 for non-enums/generators.
+        /// For enums without a variant, this is an invalid index!
+        index: VariantIdx,
+    },
 
     /// Enum-likes with more than one variant: each variant comes with
     /// a *discriminant* (usually the same as the variant index but the user can
@@ -1528,14 +1538,22 @@ pub enum TagEncoding<VariantIdx: Idx> {
     /// The variant `untagged_variant` contains a niche at an arbitrary
     /// offset (field `tag_field` of the enum), which for a variant with
     /// discriminant `d` is set to
-    /// `(d - niche_variants.start).wrapping_add(niche_start)`.
+    /// `(d - niche_variants.start).wrapping_add(niche_start)`
+    /// (this is wrapping arithmetic using the type of the niche field).
     ///
     /// For example, `Option<(usize, &T)>`  is represented such that
     /// `None` has a null pointer for the second tuple field, and
     /// `Some` is the identity function (with a non-null reference).
+    ///
+    /// Other variants that are not `untagged_variant` and that are outside the `niche_variants`
+    /// range cannot be represented; they must be uninhabited.
     Niche {
         untagged_variant: VariantIdx,
+        /// This range *may* contain `untagged_variant`; that is then just a "dead value" and
+        /// not used to encode anything.
         niche_variants: RangeInclusive<VariantIdx>,
+        /// This is inbounds of the type of the niche field
+        /// (not sign-extended, i.e., all bits beyond the niche field size are 0).
         niche_start: u128,
     },
 }
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 56b20e0ad89..2f55a9eaeda 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -39,9 +39,7 @@ pub use crate::format::*;
 use crate::ptr::P;
 use crate::token::{self, CommentKind, Delimiter};
 use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
-use crate::util::parser::{
-    AssocOp, PREC_CLOSURE, PREC_JUMP, PREC_PREFIX, PREC_RANGE, PREC_UNAMBIGUOUS,
-};
+use crate::util::parser::{AssocOp, ExprPrecedence};
 
 /// A "Label" is an identifier of some point in sources,
 /// e.g. in the following code:
@@ -1317,29 +1315,29 @@ impl Expr {
         Some(P(Ty { kind, id: self.id, span: self.span, tokens: None }))
     }
 
-    pub fn precedence(&self) -> i8 {
+    pub fn precedence(&self) -> ExprPrecedence {
         match self.kind {
-            ExprKind::Closure(..) => PREC_CLOSURE,
+            ExprKind::Closure(..) => ExprPrecedence::Closure,
 
             ExprKind::Break(..)
             | ExprKind::Continue(..)
             | ExprKind::Ret(..)
             | ExprKind::Yield(..)
             | ExprKind::Yeet(..)
-            | ExprKind::Become(..) => PREC_JUMP,
+            | ExprKind::Become(..) => ExprPrecedence::Jump,
 
             // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
             // parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence
             // ensures that `pprust` will add parentheses in the right places to get the desired
             // parse.
-            ExprKind::Range(..) => PREC_RANGE,
+            ExprKind::Range(..) => ExprPrecedence::Range,
 
             // Binop-like expr kinds, handled by `AssocOp`.
-            ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence() as i8,
-            ExprKind::Cast(..) => AssocOp::As.precedence() as i8,
+            ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
+            ExprKind::Cast(..) => ExprPrecedence::Cast,
 
             ExprKind::Assign(..) |
-            ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8,
+            ExprKind::AssignOp(..) => ExprPrecedence::Assign,
 
             // Unary, prefix
             ExprKind::AddrOf(..)
@@ -1348,7 +1346,7 @@ impl Expr {
             // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`
             // but we need to print `(let _ = a) < b` as-is with parens.
             | ExprKind::Let(..)
-            | ExprKind::Unary(..) => PREC_PREFIX,
+            | ExprKind::Unary(..) => ExprPrecedence::Prefix,
 
             // Never need parens
             ExprKind::Array(_)
@@ -1381,7 +1379,7 @@ impl Expr {
             | ExprKind::Underscore
             | ExprKind::While(..)
             | ExprKind::Err(_)
-            | ExprKind::Dummy => PREC_UNAMBIGUOUS,
+            | ExprKind::Dummy => ExprPrecedence::Unambiguous,
         }
     }
 
@@ -1733,12 +1731,12 @@ pub enum AttrArgs {
     /// Delimited arguments: `#[attr()/[]/{}]`.
     Delimited(DelimArgs),
     /// Arguments of a key-value attribute: `#[attr = "value"]`.
-    Eq(
+    Eq {
         /// Span of the `=` token.
-        Span,
-        /// The "value".
-        AttrArgsEq,
-    ),
+        eq_span: Span,
+
+        value: AttrArgsEq,
+    },
 }
 
 // The RHS of an `AttrArgs::Eq` starts out as an expression. Once macro
@@ -1750,15 +1748,39 @@ pub enum AttrArgsEq {
     Hir(MetaItemLit),
 }
 
+impl AttrArgsEq {
+    pub fn span(&self) -> Span {
+        match self {
+            AttrArgsEq::Ast(p) => p.span,
+            AttrArgsEq::Hir(lit) => lit.span,
+        }
+    }
+
+    pub fn unwrap_ast(&self) -> &Expr {
+        match self {
+            AttrArgsEq::Ast(p) => p,
+            AttrArgsEq::Hir(lit) => {
+                unreachable!("in literal form when getting inner tokens: {lit:?}")
+            }
+        }
+    }
+
+    pub fn unwrap_ast_mut(&mut self) -> &mut P<Expr> {
+        match self {
+            AttrArgsEq::Ast(p) => p,
+            AttrArgsEq::Hir(lit) => {
+                unreachable!("in literal form when getting inner tokens: {lit:?}")
+            }
+        }
+    }
+}
+
 impl AttrArgs {
     pub fn span(&self) -> Option<Span> {
         match self {
             AttrArgs::Empty => None,
             AttrArgs::Delimited(args) => Some(args.dspan.entire()),
-            AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => Some(eq_span.to(expr.span)),
-            AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
-                unreachable!("in literal form when getting span: {:?}", lit);
-            }
+            AttrArgs::Eq { eq_span, value } => Some(eq_span.to(value.span())),
         }
     }
 
@@ -1768,10 +1790,7 @@ impl AttrArgs {
         match self {
             AttrArgs::Empty => TokenStream::default(),
             AttrArgs::Delimited(args) => args.tokens.clone(),
-            AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => TokenStream::from_ast(expr),
-            AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
-                unreachable!("in literal form when getting inner tokens: {:?}", lit)
-            }
+            AttrArgs::Eq { value, .. } => TokenStream::from_ast(value.unwrap_ast()),
         }
     }
 }
@@ -1785,10 +1804,10 @@ where
         match self {
             AttrArgs::Empty => {}
             AttrArgs::Delimited(args) => args.hash_stable(ctx, hasher),
-            AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => {
+            AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => {
                 unreachable!("hash_stable {:?}", expr);
             }
-            AttrArgs::Eq(eq_span, AttrArgsEq::Hir(lit)) => {
+            AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) } => {
                 eq_span.hash_stable(ctx, hasher);
                 lit.hash_stable(ctx, hasher);
             }
@@ -2547,6 +2566,18 @@ pub enum SelfKind {
     Explicit(P<Ty>, Mutability),
 }
 
+impl SelfKind {
+    pub fn to_ref_suggestion(&self) -> String {
+        match self {
+            SelfKind::Region(None, mutbl) => mutbl.ref_prefix_str().to_string(),
+            SelfKind::Region(Some(lt), mutbl) => format!("&{lt} {}", mutbl.prefix_str()),
+            SelfKind::Value(_) | SelfKind::Explicit(_, _) => {
+                unreachable!("if we had an explicit self, we wouldn't be here")
+            }
+        }
+    }
+}
+
 pub type ExplicitSelf = Spanned<SelfKind>;
 
 impl Param {
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 888b13efa31..0d79cadef34 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -250,7 +250,7 @@ impl AttrItem {
             AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => {
                 MetaItemKind::list_from_tokens(args.tokens.clone())
             }
-            AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None,
+            AttrArgs::Delimited(_) | AttrArgs::Eq { .. } | AttrArgs::Empty => None,
         }
     }
 
@@ -268,7 +268,7 @@ impl AttrItem {
     /// ```
     fn value_str(&self) -> Option<Symbol> {
         match &self.args {
-            AttrArgs::Eq(_, args) => args.value_str(),
+            AttrArgs::Eq { value, .. } => value.value_str(),
             AttrArgs::Delimited(_) | AttrArgs::Empty => None,
         }
     }
@@ -492,7 +492,7 @@ impl MetaItemKind {
                 MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List)
             }
             AttrArgs::Delimited(..) => None,
-            AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind {
+            AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => match expr.kind {
                 ExprKind::Lit(token_lit) => {
                     // Turn failures to `None`, we'll get parse errors elsewhere.
                     MetaItemLit::from_token_lit(token_lit, expr.span)
@@ -501,7 +501,9 @@ impl MetaItemKind {
                 }
                 _ => None,
             },
-            AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => Some(MetaItemKind::NameValue(lit.clone())),
+            AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => {
+                Some(MetaItemKind::NameValue(lit.clone()))
+            }
         }
     }
 }
@@ -702,7 +704,7 @@ pub fn mk_attr_name_value_str(
         tokens: None,
     });
     let path = Path::from_ident(Ident::new(name, span));
-    let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
+    let args = AttrArgs::Eq { eq_span: span, value: AttrArgsEq::Ast(expr) };
     mk_attr(g, style, unsafety, path, args, span)
 }
 
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 0aceed45028..622c260868e 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -451,13 +451,10 @@ fn visit_attr_args<T: MutVisitor>(vis: &mut T, args: &mut AttrArgs) {
     match args {
         AttrArgs::Empty => {}
         AttrArgs::Delimited(args) => visit_delim_args(vis, args),
-        AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => {
-            vis.visit_expr(expr);
+        AttrArgs::Eq { eq_span, value } => {
+            vis.visit_expr(value.unwrap_ast_mut());
             vis.visit_span(eq_span);
         }
-        AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => {
-            unreachable!("in literal form when visiting mac args eq: {:?}", lit)
-        }
     }
 }
 
@@ -1628,9 +1625,10 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
             visit_thin_exprs(vis, call_args);
             vis.visit_span(span);
         }
-        ExprKind::Binary(_binop, lhs, rhs) => {
+        ExprKind::Binary(binop, lhs, rhs) => {
             vis.visit_expr(lhs);
             vis.visit_expr(rhs);
+            vis.visit_span(&mut binop.span);
         }
         ExprKind::Unary(_unop, ohs) => vis.visit_expr(ohs),
         ExprKind::Cast(expr, ty) => {
@@ -1788,20 +1786,21 @@ pub fn noop_filter_map_expr<T: MutVisitor>(vis: &mut T, mut e: P<Expr>) -> Optio
 
 pub fn walk_flat_map_stmt<T: MutVisitor>(
     vis: &mut T,
-    Stmt { kind, mut span, mut id }: Stmt,
+    Stmt { kind, span, mut id }: Stmt,
 ) -> SmallVec<[Stmt; 1]> {
     vis.visit_id(&mut id);
-    let stmts: SmallVec<_> = walk_flat_map_stmt_kind(vis, kind)
+    let mut stmts: SmallVec<[Stmt; 1]> = walk_flat_map_stmt_kind(vis, kind)
         .into_iter()
         .map(|kind| Stmt { id, kind, span })
         .collect();
-    if stmts.len() > 1 {
-        panic!(
+    match stmts.len() {
+        0 => {}
+        1 => vis.visit_span(&mut stmts[0].span),
+        2.. => panic!(
             "cloning statement `NodeId`s is prohibited by default, \
              the visitor should implement custom statement visiting"
-        );
+        ),
     }
-    vis.visit_span(&mut span);
     stmts
 }
 
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index ed9265d5159..e88bf27021a 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -128,21 +128,21 @@ impl AssocOp {
     }
 
     /// Gets the precedence of this operator
-    pub fn precedence(&self) -> usize {
+    pub fn precedence(&self) -> ExprPrecedence {
         use AssocOp::*;
         match *self {
-            As => 14,
-            Multiply | Divide | Modulus => 13,
-            Add | Subtract => 12,
-            ShiftLeft | ShiftRight => 11,
-            BitAnd => 10,
-            BitXor => 9,
-            BitOr => 8,
-            Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7,
-            LAnd => 6,
-            LOr => 5,
-            DotDot | DotDotEq => 4,
-            Assign | AssignOp(_) => 2,
+            As => ExprPrecedence::Cast,
+            Multiply | Divide | Modulus => ExprPrecedence::Product,
+            Add | Subtract => ExprPrecedence::Sum,
+            ShiftLeft | ShiftRight => ExprPrecedence::Shift,
+            BitAnd => ExprPrecedence::BitAnd,
+            BitXor => ExprPrecedence::BitXor,
+            BitOr => ExprPrecedence::BitOr,
+            Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => ExprPrecedence::Compare,
+            LAnd => ExprPrecedence::LAnd,
+            LOr => ExprPrecedence::LOr,
+            DotDot | DotDotEq => ExprPrecedence::Range,
+            Assign | AssignOp(_) => ExprPrecedence::Assign,
         }
     }
 
@@ -229,17 +229,44 @@ impl AssocOp {
     }
 }
 
-pub const PREC_CLOSURE: i8 = -40;
-pub const PREC_JUMP: i8 = -30;
-pub const PREC_RANGE: i8 = -10;
-// The range 2..=14 is reserved for AssocOp binary operator precedences.
-pub const PREC_PREFIX: i8 = 50;
-pub const PREC_UNAMBIGUOUS: i8 = 60;
-pub const PREC_FORCE_PAREN: i8 = 100;
+#[derive(Clone, Copy, PartialEq, PartialOrd)]
+pub enum ExprPrecedence {
+    Closure,
+    // return, break, yield
+    Jump,
+    // = += -= *= /= %= &= |= ^= <<= >>=
+    Assign,
+    // .. ..=
+    Range,
+    // ||
+    LOr,
+    // &&
+    LAnd,
+    // == != < > <= >=
+    Compare,
+    // |
+    BitOr,
+    // ^
+    BitXor,
+    // &
+    BitAnd,
+    // << >>
+    Shift,
+    // + -
+    Sum,
+    // * / %
+    Product,
+    // as
+    Cast,
+    // unary - * ! & &mut
+    Prefix,
+    // paths, loops, function calls, array indexing, field expressions, method calls
+    Unambiguous,
+}
 
 /// In `let p = e`, operators with precedence `<=` this one requires parentheses in `e`.
-pub fn prec_let_scrutinee_needs_par() -> usize {
-    AssocOp::LAnd.precedence()
+pub fn prec_let_scrutinee_needs_par() -> ExprPrecedence {
+    ExprPrecedence::LAnd
 }
 
 /// Suppose we have `let _ = e` and the `order` of `e`.
@@ -247,8 +274,8 @@ pub fn prec_let_scrutinee_needs_par() -> usize {
 ///
 /// Conversely, suppose that we have `(let _ = a) OP b` and `order` is that of `OP`.
 /// Can we print this as `let _ = a OP b`?
-pub fn needs_par_as_let_scrutinee(order: i8) -> bool {
-    order <= prec_let_scrutinee_needs_par() as i8
+pub fn needs_par_as_let_scrutinee(order: ExprPrecedence) -> bool {
+    order <= prec_let_scrutinee_needs_par()
 }
 
 /// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 718397e8ca0..2f6998783fa 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -1273,10 +1273,7 @@ pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -
     match args {
         AttrArgs::Empty => {}
         AttrArgs::Delimited(_args) => {}
-        AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => try_visit!(visitor.visit_expr(expr)),
-        AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => {
-            unreachable!("in literal form when walking mac args eq: {:?}", lit)
-        }
+        AttrArgs::Eq { value, .. } => try_visit!(visitor.visit_expr(value.unwrap_ast())),
     }
     V::Result::output()
 }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 7ffe4db6e45..bac3f974cca 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -889,7 +889,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // This is an inert key-value attribute - it will never be visible to macros
             // after it gets lowered to HIR. Therefore, we can extract literals to handle
             // nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
-            AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => {
+            &AttrArgs::Eq { eq_span, ref value } => {
+                let expr = value.unwrap_ast();
                 // In valid code the value always ends up as a single literal. Otherwise, a dummy
                 // literal suffices because the error is handled elsewhere.
                 let lit = if let ExprKind::Lit(token_lit) = expr.kind
@@ -905,10 +906,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         span: DUMMY_SP,
                     }
                 };
-                AttrArgs::Eq(*eq_span, AttrArgsEq::Hir(lit))
-            }
-            AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
-                unreachable!("in literal form when lowering mac args eq: {:?}", lit)
+                AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) }
             }
         }
     }
@@ -2013,7 +2011,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             ExprKind::Underscore => {
                 if self.tcx.features().generic_arg_infer() {
                     let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span));
-                    self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind: ct_kind })
+                    self.arena
+                        .alloc(hir::ConstArg { hir_id: self.lower_node_id(c.id), kind: ct_kind })
                 } else {
                     feature_err(
                         &self.tcx.sess,
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index d81fd53938b..5a0ec865f9d 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -207,8 +207,6 @@ ast_passes_precise_capturing_duplicated = duplicate `use<...>` precise capturing
 
 ast_passes_precise_capturing_not_allowed_here = `use<...>` precise capturing syntax not allowed in {$loc}
 
-ast_passes_show_span = {$msg}
-
 ast_passes_stability_outside_std = stability attributes may not be used outside of the standard library
 
 ast_passes_static_without_body =
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index f65056a494b..9b600e3ee92 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -780,14 +780,6 @@ pub(crate) struct IncompatibleFeatures {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_show_span)]
-pub(crate) struct ShowSpan {
-    #[primary_span]
-    pub span: Span,
-    pub msg: &'static str,
-}
-
-#[derive(Diagnostic)]
 #[diag(ast_passes_negative_bound_not_supported)]
 pub(crate) struct NegativeBoundUnsupported {
     #[primary_span]
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 8cdc7133cc0..89311516081 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -4,9 +4,9 @@ use rustc_ast::{NodeId, PatKind, attr, token};
 use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features, GateIssue};
 use rustc_session::Session;
 use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
+use rustc_span::Span;
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::sym;
-use rustc_span::{Span, Symbol};
+use rustc_span::symbol::{Symbol, sym};
 use rustc_target::spec::abi;
 use thin_vec::ThinVec;
 
@@ -516,6 +516,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
         "async closures are unstable",
         "to use an async block, remove the `||`: `async {`"
     );
+    gate_all!(
+        async_trait_bounds,
+        "`async` trait bounds are unstable",
+        "use the desugared name of the async trait, such as `AsyncFn`"
+    );
     gate_all!(async_for_loop, "`for await` loops are experimental");
     gate_all!(
         closure_lifetime_binder,
@@ -690,6 +695,7 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) {
         .find(|feat| feat.gate_name == sym::generic_const_exprs)
         .map(|feat| feat.attr_sp)
     {
+        #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
         sess.dcx().emit_err(errors::IncompatibleFeatures {
             spans: vec![gce_span],
             f1: Symbol::intern("-Znext-solver=globally"),
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index 86752da79ae..b4ed70d83e5 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -1,8 +1,6 @@
 //! The `rustc_ast_passes` crate contains passes which validate the AST in `syntax`
 //! parsed by `rustc_parse` and then lowered, after the passes in this crate,
 //! by `rustc_ast_lowering`.
-//!
-//! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`.
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
@@ -18,6 +16,5 @@
 pub mod ast_validation;
 mod errors;
 pub mod feature_gate;
-pub mod show_span;
 
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_ast_passes/src/show_span.rs b/compiler/rustc_ast_passes/src/show_span.rs
deleted file mode 100644
index e7ba2e7fc30..00000000000
--- a/compiler/rustc_ast_passes/src/show_span.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-//! Span debugger
-//!
-//! This module shows spans for all expressions in the crate
-//! to help with compiler debugging.
-
-use std::str::FromStr;
-
-use rustc_ast as ast;
-use rustc_ast::visit;
-use rustc_ast::visit::Visitor;
-use rustc_errors::DiagCtxtHandle;
-
-use crate::errors;
-
-enum Mode {
-    Expression,
-    Pattern,
-    Type,
-}
-
-impl FromStr for Mode {
-    type Err = ();
-    fn from_str(s: &str) -> Result<Mode, ()> {
-        let mode = match s {
-            "expr" => Mode::Expression,
-            "pat" => Mode::Pattern,
-            "ty" => Mode::Type,
-            _ => return Err(()),
-        };
-        Ok(mode)
-    }
-}
-
-struct ShowSpanVisitor<'a> {
-    dcx: DiagCtxtHandle<'a>,
-    mode: Mode,
-}
-
-impl<'a> Visitor<'a> for ShowSpanVisitor<'a> {
-    fn visit_expr(&mut self, e: &'a ast::Expr) {
-        if let Mode::Expression = self.mode {
-            self.dcx.emit_warn(errors::ShowSpan { span: e.span, msg: "expression" });
-        }
-        visit::walk_expr(self, e);
-    }
-
-    fn visit_pat(&mut self, p: &'a ast::Pat) {
-        if let Mode::Pattern = self.mode {
-            self.dcx.emit_warn(errors::ShowSpan { span: p.span, msg: "pattern" });
-        }
-        visit::walk_pat(self, p);
-    }
-
-    fn visit_ty(&mut self, t: &'a ast::Ty) {
-        if let Mode::Type = self.mode {
-            self.dcx.emit_warn(errors::ShowSpan { span: t.span, msg: "type" });
-        }
-        visit::walk_ty(self, t);
-    }
-}
-
-pub fn run(dcx: DiagCtxtHandle<'_>, mode: &str, krate: &ast::Crate) {
-    let Ok(mode) = mode.parse() else {
-        return;
-    };
-    let mut v = ShowSpanVisitor { dcx, mode };
-    visit::walk_crate(&mut v, krate);
-}
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index d7c531f3760..479677b0a5a 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -648,14 +648,14 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
             AttrArgs::Empty => {
                 self.print_path(&item.path, false, 0);
             }
-            AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => {
+            AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => {
                 self.print_path(&item.path, false, 0);
                 self.space();
                 self.word_space("=");
                 let token_str = self.expr_to_string(expr);
                 self.word(token_str);
             }
-            AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
+            AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => {
                 self.print_path(&item.path, false, 0);
                 self.space();
                 self.word_space("=");
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index e9c49e9f682..c239cb249c3 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -5,7 +5,7 @@ use itertools::{Itertools, Position};
 use rustc_ast::ptr::P;
 use rustc_ast::util::classify;
 use rustc_ast::util::literal::escape_byte_str_symbol;
-use rustc_ast::util::parser::{self, AssocOp, Fixity};
+use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity};
 use rustc_ast::{
     self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount,
     FormatDebugHex, FormatSign, FormatTrait, token,
@@ -212,9 +212,9 @@ impl<'a> State<'a> {
     }
 
     fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>], fixup: FixupContext) {
-        let prec = match func.kind {
-            ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
-            _ => parser::PREC_UNAMBIGUOUS,
+        let needs_paren = match func.kind {
+            ast::ExprKind::Field(..) => true,
+            _ => func.precedence() < ExprPrecedence::Unambiguous,
         };
 
         // Independent of parenthesization related to precedence, we must
@@ -233,7 +233,7 @@ impl<'a> State<'a> {
         // because the latter is valid syntax but with the incorrect meaning.
         // It's a match-expression followed by tuple-expression, not a function
         // call.
-        self.print_expr_cond_paren(func, func.precedence() < prec, fixup.leftmost_subexpression());
+        self.print_expr_cond_paren(func, needs_paren, fixup.leftmost_subexpression());
 
         self.print_call_post(args)
     }
@@ -256,7 +256,7 @@ impl<'a> State<'a> {
         // a statement containing an expression.
         self.print_expr_cond_paren(
             receiver,
-            receiver.precedence() < parser::PREC_UNAMBIGUOUS,
+            receiver.precedence() < ExprPrecedence::Unambiguous,
             fixup,
         );
 
@@ -276,21 +276,22 @@ impl<'a> State<'a> {
         fixup: FixupContext,
     ) {
         let assoc_op = AssocOp::from_ast_binop(op.node);
-        let prec = assoc_op.precedence() as i8;
-        let fixity = assoc_op.fixity();
-
-        let (left_prec, right_prec) = match fixity {
-            Fixity::Left => (prec, prec + 1),
-            Fixity::Right => (prec + 1, prec),
-            Fixity::None => (prec + 1, prec + 1),
+        let binop_prec = assoc_op.precedence();
+        let left_prec = lhs.precedence();
+        let right_prec = rhs.precedence();
+
+        let (mut left_needs_paren, right_needs_paren) = match assoc_op.fixity() {
+            Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
+            Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
+            Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),
         };
 
-        let left_prec = match (&lhs.kind, op.node) {
+        match (&lhs.kind, op.node) {
             // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
             // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
             // of `(x as i32) < ...`. We need to convince it _not_ to do that.
             (&ast::ExprKind::Cast { .. }, ast::BinOpKind::Lt | ast::BinOpKind::Shl) => {
-                parser::PREC_FORCE_PAREN
+                left_needs_paren = true;
             }
             // We are given `(let _ = a) OP b`.
             //
@@ -300,33 +301,23 @@ impl<'a> State<'a> {
             // - Otherwise, e.g. when we have `(let a = b) < c` in AST,
             //   parens are required since the parser would interpret `let a = b < c` as
             //   `let a = (b < c)`. To achieve this, we force parens.
-            (&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(prec) => {
-                parser::PREC_FORCE_PAREN
+            (&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(binop_prec) => {
+                left_needs_paren = true;
             }
-            _ => left_prec,
-        };
-
-        self.print_expr_cond_paren(
-            lhs,
-            lhs.precedence() < left_prec,
-            fixup.leftmost_subexpression(),
-        );
+            _ => {}
+        }
 
+        self.print_expr_cond_paren(lhs, left_needs_paren, fixup.leftmost_subexpression());
         self.space();
         self.word_space(op.node.as_str());
-
-        self.print_expr_cond_paren(
-            rhs,
-            rhs.precedence() < right_prec,
-            fixup.subsequent_subexpression(),
-        );
+        self.print_expr_cond_paren(rhs, right_needs_paren, fixup.subsequent_subexpression());
     }
 
     fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr, fixup: FixupContext) {
         self.word(op.as_str());
         self.print_expr_cond_paren(
             expr,
-            expr.precedence() < parser::PREC_PREFIX,
+            expr.precedence() < ExprPrecedence::Prefix,
             fixup.subsequent_subexpression(),
         );
     }
@@ -348,7 +339,7 @@ impl<'a> State<'a> {
         }
         self.print_expr_cond_paren(
             expr,
-            expr.precedence() < parser::PREC_PREFIX,
+            expr.precedence() < ExprPrecedence::Prefix,
             fixup.subsequent_subexpression(),
         );
     }
@@ -432,10 +423,9 @@ impl<'a> State<'a> {
                 self.print_token_literal(lit, expr.span)
             }
             ast::ExprKind::Cast(expr, ty) => {
-                let prec = AssocOp::As.precedence() as i8;
                 self.print_expr_cond_paren(
                     expr,
-                    expr.precedence() < prec,
+                    expr.precedence() < ExprPrecedence::Cast,
                     fixup.leftmost_subexpression(),
                 );
                 self.space();
@@ -512,7 +502,7 @@ impl<'a> State<'a> {
                     MatchKind::Postfix => {
                         self.print_expr_cond_paren(
                             expr,
-                            expr.precedence() < parser::PREC_UNAMBIGUOUS,
+                            expr.precedence() < ExprPrecedence::Unambiguous,
                             fixup,
                         );
                         self.word_nbsp(".match");
@@ -576,31 +566,31 @@ impl<'a> State<'a> {
             ast::ExprKind::Await(expr, _) => {
                 self.print_expr_cond_paren(
                     expr,
-                    expr.precedence() < parser::PREC_UNAMBIGUOUS,
+                    expr.precedence() < ExprPrecedence::Unambiguous,
                     fixup,
                 );
                 self.word(".await");
             }
             ast::ExprKind::Assign(lhs, rhs, _) => {
-                let prec = AssocOp::Assign.precedence() as i8;
                 self.print_expr_cond_paren(
                     lhs,
-                    lhs.precedence() <= prec,
+                    // Ranges are allowed on the right-hand side of assignment,
+                    // but not the left. `(a..b) = c` needs parentheses.
+                    lhs.precedence() <= ExprPrecedence::Range,
                     fixup.leftmost_subexpression(),
                 );
                 self.space();
                 self.word_space("=");
                 self.print_expr_cond_paren(
                     rhs,
-                    rhs.precedence() < prec,
+                    rhs.precedence() < ExprPrecedence::Assign,
                     fixup.subsequent_subexpression(),
                 );
             }
             ast::ExprKind::AssignOp(op, lhs, rhs) => {
-                let prec = AssocOp::Assign.precedence() as i8;
                 self.print_expr_cond_paren(
                     lhs,
-                    lhs.precedence() <= prec,
+                    lhs.precedence() <= ExprPrecedence::Range,
                     fixup.leftmost_subexpression(),
                 );
                 self.space();
@@ -608,14 +598,14 @@ impl<'a> State<'a> {
                 self.word_space("=");
                 self.print_expr_cond_paren(
                     rhs,
-                    rhs.precedence() < prec,
+                    rhs.precedence() < ExprPrecedence::Assign,
                     fixup.subsequent_subexpression(),
                 );
             }
             ast::ExprKind::Field(expr, ident) => {
                 self.print_expr_cond_paren(
                     expr,
-                    expr.precedence() < parser::PREC_UNAMBIGUOUS,
+                    expr.precedence() < ExprPrecedence::Unambiguous,
                     fixup,
                 );
                 self.word(".");
@@ -624,7 +614,7 @@ impl<'a> State<'a> {
             ast::ExprKind::Index(expr, index, _) => {
                 self.print_expr_cond_paren(
                     expr,
-                    expr.precedence() < parser::PREC_UNAMBIGUOUS,
+                    expr.precedence() < ExprPrecedence::Unambiguous,
                     fixup.leftmost_subexpression(),
                 );
                 self.word("[");
@@ -636,7 +626,7 @@ impl<'a> State<'a> {
                 // than `Assign`, but `x .. x = x` gives a parse error instead of `x .. (x = x)`.
                 // Here we use a fake precedence value so that any child with lower precedence than
                 // a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.)
-                let fake_prec = AssocOp::LOr.precedence() as i8;
+                let fake_prec = ExprPrecedence::LOr;
                 if let Some(e) = start {
                     self.print_expr_cond_paren(
                         e,
@@ -671,7 +661,7 @@ impl<'a> State<'a> {
                         expr,
                         // Parenthesize if required by precedence, or in the
                         // case of `break 'inner: loop { break 'inner 1 } + 1`
-                        expr.precedence() < parser::PREC_JUMP
+                        expr.precedence() < ExprPrecedence::Jump
                             || (opt_label.is_none() && classify::leading_labeled_expr(expr)),
                         fixup.subsequent_subexpression(),
                     );
@@ -690,7 +680,7 @@ impl<'a> State<'a> {
                     self.word(" ");
                     self.print_expr_cond_paren(
                         expr,
-                        expr.precedence() < parser::PREC_JUMP,
+                        expr.precedence() < ExprPrecedence::Jump,
                         fixup.subsequent_subexpression(),
                     );
                 }
@@ -703,7 +693,7 @@ impl<'a> State<'a> {
                     self.word(" ");
                     self.print_expr_cond_paren(
                         expr,
-                        expr.precedence() < parser::PREC_JUMP,
+                        expr.precedence() < ExprPrecedence::Jump,
                         fixup.subsequent_subexpression(),
                     );
                 }
@@ -713,7 +703,7 @@ impl<'a> State<'a> {
                 self.word(" ");
                 self.print_expr_cond_paren(
                     result,
-                    result.precedence() < parser::PREC_JUMP,
+                    result.precedence() < ExprPrecedence::Jump,
                     fixup.subsequent_subexpression(),
                 );
             }
@@ -767,13 +757,13 @@ impl<'a> State<'a> {
                     self.space();
                     self.print_expr_cond_paren(
                         expr,
-                        expr.precedence() < parser::PREC_JUMP,
+                        expr.precedence() < ExprPrecedence::Jump,
                         fixup.subsequent_subexpression(),
                     );
                 }
             }
             ast::ExprKind::Try(e) => {
-                self.print_expr_cond_paren(e, e.precedence() < parser::PREC_UNAMBIGUOUS, fixup);
+                self.print_expr_cond_paren(e, e.precedence() < ExprPrecedence::Unambiguous, fixup);
                 self.word("?")
             }
             ast::ExprKind::TryBlock(blk) => {
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 99af5500ac6..0eecf98a6ed 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -973,25 +973,20 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         propagated_outlives_requirements: &mut Vec<ClosureOutlivesRequirement<'tcx>>,
     ) -> bool {
         let tcx = infcx.tcx;
-
-        let TypeTest { generic_kind, lower_bound, span: _, verify_bound: _ } = type_test;
+        let TypeTest { generic_kind, lower_bound, span: blame_span, ref verify_bound } = *type_test;
 
         let generic_ty = generic_kind.to_ty(tcx);
         let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else {
             return false;
         };
 
-        debug!("subject = {:?}", subject);
-
-        let r_scc = self.constraint_sccs.scc(*lower_bound);
-
+        let r_scc = self.constraint_sccs.scc(lower_bound);
         debug!(
             "lower_bound = {:?} r_scc={:?} universe={:?}",
             lower_bound,
             r_scc,
             self.constraint_sccs.annotation(r_scc).min_universe()
         );
-
         // If the type test requires that `T: 'a` where `'a` is a
         // placeholder from another universe, that effectively requires
         // `T: 'static`, so we have to propagate that requirement.
@@ -1004,7 +999,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             propagated_outlives_requirements.push(ClosureOutlivesRequirement {
                 subject,
                 outlived_free_region: static_r,
-                blame_span: type_test.span,
+                blame_span,
                 category: ConstraintCategory::Boring,
             });
 
@@ -1031,12 +1026,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             // where `ur` is a local bound -- we are sometimes in a
             // position to prove things that our caller cannot. See
             // #53570 for an example.
-            if self.eval_verify_bound(infcx, generic_ty, ur, &type_test.verify_bound) {
+            if self.eval_verify_bound(infcx, generic_ty, ur, &verify_bound) {
                 continue;
             }
 
             let non_local_ub = self.universal_region_relations.non_local_upper_bounds(ur);
-            debug!("try_promote_type_test: non_local_ub={:?}", non_local_ub);
+            debug!(?non_local_ub);
 
             // This is slightly too conservative. To show T: '1, given `'2: '1`
             // and `'3: '1` we only need to prove that T: '2 *or* T: '3, but to
@@ -1049,10 +1044,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 let requirement = ClosureOutlivesRequirement {
                     subject,
                     outlived_free_region: upper_bound,
-                    blame_span: type_test.span,
+                    blame_span,
                     category: ConstraintCategory::Boring,
                 };
-                debug!("try_promote_type_test: pushing {:#?}", requirement);
+                debug!(?requirement, "adding closure requirement");
                 propagated_outlives_requirements.push(requirement);
             }
         }
@@ -1063,44 +1058,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// variables in the type `T` with an equal universal region from the
     /// closure signature.
     /// This is not always possible, so this is a fallible process.
-    #[instrument(level = "debug", skip(self, infcx))]
+    #[instrument(level = "debug", skip(self, infcx), ret)]
     fn try_promote_type_test_subject(
         &self,
         infcx: &InferCtxt<'tcx>,
         ty: Ty<'tcx>,
     ) -> Option<ClosureOutlivesSubject<'tcx>> {
         let tcx = infcx.tcx;
-
-        // Opaque types' args may include useless lifetimes.
-        // We will replace them with ReStatic.
-        struct OpaqueFolder<'tcx> {
-            tcx: TyCtxt<'tcx>,
-        }
-        impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for OpaqueFolder<'tcx> {
-            fn cx(&self) -> TyCtxt<'tcx> {
-                self.tcx
-            }
-            fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-                use ty::TypeSuperFoldable as _;
-                let tcx = self.tcx;
-                let &ty::Alias(ty::Opaque, ty::AliasTy { args, def_id, .. }) = t.kind() else {
-                    return t.super_fold_with(self);
-                };
-                let args = std::iter::zip(args, tcx.variances_of(def_id)).map(|(arg, v)| {
-                    match (arg.unpack(), v) {
-                        (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => {
-                            tcx.lifetimes.re_static.into()
-                        }
-                        _ => arg.fold_with(self),
-                    }
-                });
-                Ty::new_opaque(tcx, def_id, tcx.mk_args_from_iter(args))
-            }
-        }
-
-        let ty = ty.fold_with(&mut OpaqueFolder { tcx });
         let mut failed = false;
-
         let ty = fold_regions(tcx, ty, |r, _depth| {
             let r_vid = self.to_region_vid(r);
             let r_scc = self.constraint_sccs.scc(r_vid);
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 86a0111db49..bb64d646ff3 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -33,8 +33,8 @@ use rustc_middle::ty::{
     TyCtxt, TypeVisitableExt,
 };
 use rustc_middle::{bug, span_bug};
+use rustc_span::ErrorGuaranteed;
 use rustc_span::symbol::{kw, sym};
-use rustc_span::{ErrorGuaranteed, Symbol};
 use tracing::{debug, instrument};
 
 use crate::BorrowckInferCtxt;
@@ -524,7 +524,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
 
                 let reg_vid = self
                     .infcx
-                    .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("c-variadic")))
+                    .next_nll_region_var(FR, || RegionCtxt::Free(sym::c_dash_variadic))
                     .as_var();
 
                 let region = ty::Region::new_var(self.infcx.tcx, reg_vid);
@@ -540,10 +540,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
             }
         }
 
-        let fr_fn_body = self
-            .infcx
-            .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("fn_body")))
-            .as_var();
+        let fr_fn_body =
+            self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(sym::fn_body)).as_var();
 
         let num_universals = self.infcx.num_region_vars();
 
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 6ebc2fd870c..c05d44cb452 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -94,6 +94,21 @@ builtin_macros_cfg_accessible_indeterminate = cannot determine whether the path
 builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a literal
 builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
 builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
+
+builtin_macros_coerce_pointee_requires_maybe_sized = `derive(CoercePointee)` requires `{$name}` to be marked `?Sized`
+
+builtin_macros_coerce_pointee_requires_one_field = `CoercePointee` can only be derived on `struct`s with at least one field
+
+builtin_macros_coerce_pointee_requires_one_generic = `CoercePointee` can only be derived on `struct`s that are generic over at least one type
+
+builtin_macros_coerce_pointee_requires_one_pointee = exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits
+
+builtin_macros_coerce_pointee_requires_transparent = `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
+
+builtin_macros_coerce_pointee_too_many_pointees = only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits
+    .label = here another type parameter is marked as `#[pointee]`
+
+
 builtin_macros_concat_bytes_array = cannot concatenate doubly nested array
     .note = byte strings are treated as arrays of bytes
     .help = try flattening the array
diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
index 8adb9a3f4b0..3bd8f899a4a 100644
--- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
@@ -9,6 +9,7 @@ use rustc_ast::{
 use rustc_attr as attr;
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_expand::base::{Annotatable, ExtCtxt};
+use rustc_macros::Diagnostic;
 use rustc_span::symbol::{Ident, sym};
 use rustc_span::{Span, Symbol};
 use thin_vec::{ThinVec, thin_vec};
@@ -38,12 +39,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
                 .any(|r| matches!(r, attr::ReprTransparent))
         });
         if !is_transparent {
-            cx.dcx()
-                .struct_span_err(
-                    span,
-                    "`CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`",
-                )
-                .emit();
+            cx.dcx().emit_err(RequireTransparent { span });
             return;
         }
         if !matches!(
@@ -51,22 +47,12 @@ pub(crate) fn expand_deriving_coerce_pointee(
             VariantData::Struct { fields, recovered: _ } | VariantData::Tuple(fields, _)
                 if !fields.is_empty())
         {
-            cx.dcx()
-                .struct_span_err(
-                    span,
-                    "`CoercePointee` can only be derived on `struct`s with at least one field",
-                )
-                .emit();
+            cx.dcx().emit_err(RequireOneField { span });
             return;
         }
         (aitem.ident, g)
     } else {
-        cx.dcx()
-            .struct_span_err(
-                span,
-                "`CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`",
-            )
-            .emit();
+        cx.dcx().emit_err(RequireTransparent { span });
         return;
     };
 
@@ -95,10 +81,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
 
     let pointee_param_idx = if type_params.is_empty() {
         // `#[derive(CoercePointee)]` requires at least one generic type on the target `struct`
-        cx.dcx().struct_span_err(
-            span,
-            "`CoercePointee` can only be derived on `struct`s that are generic over at least one type",
-        ).emit();
+        cx.dcx().emit_err(RequireOneGeneric { span });
         return;
     } else if type_params.len() == 1 {
         // Regardless of the only type param being designed as `#[pointee]` or not, we can just use it as such
@@ -111,19 +94,11 @@ pub(crate) fn expand_deriving_coerce_pointee(
         match (pointees.next(), pointees.next()) {
             (Some((idx, _span)), None) => idx,
             (None, _) => {
-                cx.dcx().struct_span_err(
-                    span,
-                    "exactly one generic type parameter must be marked as #[pointee] to derive CoercePointee traits",
-                ).emit();
+                cx.dcx().emit_err(RequireOnePointee { span });
                 return;
             }
             (Some((_, one)), Some((_, another))) => {
-                cx.dcx()
-                    .struct_span_err(
-                        vec![one, another],
-                        "only one type parameter can be marked as `#[pointee]` when deriving CoercePointee traits",
-                    )
-                    .emit();
+                cx.dcx().emit_err(TooManyPointees { one, another });
                 return;
             }
         }
@@ -181,15 +156,10 @@ pub(crate) fn expand_deriving_coerce_pointee(
                 pointee_ty_ident.name,
             )
         {
-            cx.dcx()
-                .struct_span_err(
-                    pointee_ty_ident.span,
-                    format!(
-                        "`derive(CoercePointee)` requires {} to be marked `?Sized`",
-                        pointee_ty_ident.name
-                    ),
-                )
-                .emit();
+            cx.dcx().emit_err(RequiresMaybeSized {
+                span: pointee_ty_ident.span,
+                name: pointee_ty_ident.name.to_ident_string(),
+            });
             return;
         }
         let arg = GenericArg::Type(s_ty.clone());
@@ -459,3 +429,48 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for AlwaysErrorOnGenericParam<'a, 'b>
         }
     }
 }
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_coerce_pointee_requires_transparent)]
+struct RequireTransparent {
+    #[primary_span]
+    span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_coerce_pointee_requires_one_field)]
+struct RequireOneField {
+    #[primary_span]
+    span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_coerce_pointee_requires_one_generic)]
+struct RequireOneGeneric {
+    #[primary_span]
+    span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_coerce_pointee_requires_one_pointee)]
+struct RequireOnePointee {
+    #[primary_span]
+    span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_coerce_pointee_too_many_pointees)]
+struct TooManyPointees {
+    #[primary_span]
+    one: Span,
+    #[label]
+    another: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_coerce_pointee_requires_maybe_sized)]
+struct RequiresMaybeSized {
+    #[primary_span]
+    span: Span,
+    name: String,
+}
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 0d62a13b472..ae9578eeffb 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -74,7 +74,7 @@ fn create_jit_module(
     jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8);
     let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false);
 
-    let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, Symbol::intern("dummy_cgu_name"));
+    let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
 
     crate::allocator::codegen(tcx, &mut jit_module);
 
@@ -276,12 +276,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
 
             jit_module.module.prepare_for_function_redefine(func_id).unwrap();
 
-            let mut cx = crate::CodegenCx::new(
-                tcx,
-                jit_module.isa(),
-                false,
-                Symbol::intern("dummy_cgu_name"),
-            );
+            let mut cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
             codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance);
 
             assert!(cx.global_asm.is_empty());
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index f787b8a6fd9..e0ebe30752a 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -415,7 +415,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
             });
         }
 
-        sym::simd_fma => {
+        // FIXME: simd_relaxed_fma doesn't relax to non-fused multiply-add
+        sym::simd_fma | sym::simd_relaxed_fma => {
             intrinsic_args!(fx, args => (a, b, c); intrinsic);
 
             if !a.layout().ty.is_simd() {
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index e6f6ae30581..cac9975f04c 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -189,18 +189,13 @@ impl CodegenBackend for CraneliftCodegenBackend {
         // 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
-            vec![Symbol::intern("fxsr"), sym::sse, Symbol::intern("sse2")]
+            vec![sym::fsxr, sym::sse, sym::sse2]
         } else if sess.target.arch == "aarch64" {
             match &*sess.target.os {
                 "none" => vec![],
                 // On macOS the aes, sha2 and sha3 features are enabled by default and ring
                 // fails to compile on macOS when they are not present.
-                "macos" => vec![
-                    sym::neon,
-                    Symbol::intern("aes"),
-                    Symbol::intern("sha2"),
-                    Symbol::intern("sha3"),
-                ],
+                "macos" => vec![sym::neon, sym::aes, sym::sha2, sym::sha3],
                 // AArch64 mandates Neon support
                 _ => vec![sym::neon],
             }
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index 604678a9af4..79d1a06dd46 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -772,6 +772,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
             sym::simd_flog => "log",
             sym::simd_floor => "floor",
             sym::simd_fma => "fma",
+            sym::simd_relaxed_fma => "fma", // FIXME: this should relax to non-fused multiply-add when necessary
             sym::simd_fpowi => "__builtin_powi",
             sym::simd_fpow => "pow",
             sym::simd_fsin => "sin",
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 48beb9be2b2..f6d2ec24da6 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -148,7 +148,7 @@ fn prepare_lto(
     // __llvm_profile_counter_bias is pulled in at link time by an undefined reference to
     // __llvm_profile_runtime, therefore we won't know until link time if this symbol
     // should have default visibility.
-    symbols_below_threshold.push(CString::new("__llvm_profile_counter_bias").unwrap());
+    symbols_below_threshold.push(c"__llvm_profile_counter_bias".to_owned());
     Ok((symbols_below_threshold, upstream_modules))
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 2744795d998..bde6668929c 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -509,7 +509,7 @@ fn get_pgo_sample_use_path(config: &ModuleConfig) -> Option<CString> {
 }
 
 fn get_instr_profile_output_path(config: &ModuleConfig) -> Option<CString> {
-    config.instrument_coverage.then(|| CString::new("default_%m_%p.profraw").unwrap())
+    config.instrument_coverage.then(|| c"default_%m_%p.profraw".to_owned())
 }
 
 pub(crate) unsafe fn llvm_optimize(
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index ef16e5bb459..dee67baaee9 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -203,6 +203,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
                     Stub::Struct,
                     unique_type_id,
                     &ptr_type_debuginfo_name,
+                    None,
                     cx.size_and_align_of(ptr_type),
                     NO_SCOPE_METADATA,
                     DIFlags::FlagZero,
@@ -259,6 +260,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
                             layout.fields.offset(abi::WIDE_PTR_ADDR),
                             DIFlags::FlagZero,
                             data_ptr_type_di_node,
+                            None,
                         ),
                         build_field_di_node(
                             cx,
@@ -268,6 +270,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
                             layout.fields.offset(abi::WIDE_PTR_EXTRA),
                             DIFlags::FlagZero,
                             type_di_node(cx, extra_field.ty),
+                            None,
                         ),
                     ]
                 },
@@ -369,6 +372,7 @@ fn build_dyn_type_di_node<'ll, 'tcx>(
                 Stub::Struct,
                 unique_type_id,
                 &type_name,
+                None,
                 cx.size_and_align_of(dyn_type),
                 NO_SCOPE_METADATA,
                 DIFlags::FlagZero,
@@ -722,6 +726,14 @@ fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreation
     // `f16`'s value to be displayed using a Natvis visualiser in `intrinsic.natvis`.
     let float_ty = cx.tcx.types.f16;
     let bits_ty = cx.tcx.types.u16;
+    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+        match float_ty.kind() {
+            ty::Adt(def, _) => Some(file_metadata_from_def_id(cx, Some(def.did()))),
+            _ => None,
+        }
+    } else {
+        None
+    };
     type_map::build_type_with_children(
         cx,
         type_map::stub(
@@ -729,12 +741,21 @@ fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreation
             Stub::Struct,
             UniqueTypeId::for_ty(cx.tcx, float_ty),
             "f16",
+            def_location,
             cx.size_and_align_of(float_ty),
             NO_SCOPE_METADATA,
             DIFlags::FlagZero,
         ),
         // Fields:
         |cx, float_di_node| {
+            let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+                match bits_ty.kind() {
+                    ty::Adt(def, _) => Some(def.did()),
+                    _ => None,
+                }
+            } else {
+                None
+            };
             smallvec![build_field_di_node(
                 cx,
                 float_di_node,
@@ -743,6 +764,7 @@ fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreation
                 Size::ZERO,
                 DIFlags::FlagZero,
                 type_di_node(cx, bits_ty),
+                def_id,
             )]
         },
         NO_GENERICS,
@@ -839,6 +861,7 @@ fn build_foreign_type_di_node<'ll, 'tcx>(
             Stub::Struct,
             unique_type_id,
             &compute_debuginfo_type_name(cx.tcx, t, false),
+            None,
             cx.size_and_align_of(t),
             Some(get_namespace_for_item(cx, def_id)),
             DIFlags::FlagZero,
@@ -989,15 +1012,22 @@ fn build_field_di_node<'ll, 'tcx>(
     offset: Size,
     flags: DIFlags,
     type_di_node: &'ll DIType,
+    def_id: Option<DefId>,
 ) -> &'ll DIType {
+    let (file_metadata, line_number) = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers
+    {
+        file_metadata_from_def_id(cx, def_id)
+    } else {
+        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
+    };
     unsafe {
         llvm::LLVMRustDIBuilderCreateMemberType(
             DIB(cx),
             owner,
             name.as_c_char_ptr(),
             name.len(),
-            unknown_file_metadata(cx),
-            UNKNOWN_LINE_NUMBER,
+            file_metadata,
+            line_number,
             size_and_align.0.bits(),
             size_and_align.1.bits() as u32,
             offset.bits(),
@@ -1041,6 +1071,11 @@ fn build_struct_type_di_node<'ll, 'tcx>(
     let containing_scope = get_namespace_for_item(cx, adt_def.did());
     let struct_type_and_layout = cx.layout_of(struct_type);
     let variant_def = adt_def.non_enum_variant();
+    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+        Some(file_metadata_from_def_id(cx, Some(adt_def.did())))
+    } else {
+        None
+    };
 
     type_map::build_type_with_children(
         cx,
@@ -1049,6 +1084,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
             Stub::Struct,
             unique_type_id,
             &compute_debuginfo_type_name(cx.tcx, struct_type, false),
+            def_location,
             size_and_align_of(struct_type_and_layout),
             Some(containing_scope),
             visibility_di_flags(cx, adt_def.did(), adt_def.did()),
@@ -1068,6 +1104,11 @@ fn build_struct_type_di_node<'ll, 'tcx>(
                         Cow::Borrowed(f.name.as_str())
                     };
                     let field_layout = struct_type_and_layout.field(cx, i);
+                    let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+                        Some(f.did)
+                    } else {
+                        None
+                    };
                     build_field_di_node(
                         cx,
                         owner,
@@ -1076,6 +1117,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
                         struct_type_and_layout.fields.offset(i),
                         visibility_di_flags(cx, f.did, adt_def.did()),
                         type_di_node(cx, field_layout.ty),
+                        def_id,
                     )
                 })
                 .collect()
@@ -1125,6 +1167,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
                 layout.fields.offset(index),
                 DIFlags::FlagZero,
                 type_di_node(cx, up_var_ty),
+                None,
             )
         })
         .collect()
@@ -1150,6 +1193,7 @@ fn build_tuple_type_di_node<'ll, 'tcx>(
             Stub::Struct,
             unique_type_id,
             &type_name,
+            None,
             size_and_align_of(tuple_type_and_layout),
             NO_SCOPE_METADATA,
             DIFlags::FlagZero,
@@ -1168,6 +1212,7 @@ fn build_tuple_type_di_node<'ll, 'tcx>(
                         tuple_type_and_layout.fields.offset(index),
                         DIFlags::FlagZero,
                         type_di_node(cx, component_type),
+                        None,
                     )
                 })
                 .collect()
@@ -1189,6 +1234,12 @@ fn build_closure_env_di_node<'ll, 'tcx>(
     let containing_scope = get_namespace_for_item(cx, def_id);
     let type_name = compute_debuginfo_type_name(cx.tcx, closure_env_type, false);
 
+    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+        Some(file_metadata_from_def_id(cx, Some(def_id)))
+    } else {
+        None
+    };
+
     type_map::build_type_with_children(
         cx,
         type_map::stub(
@@ -1196,6 +1247,7 @@ fn build_closure_env_di_node<'ll, 'tcx>(
             Stub::Struct,
             unique_type_id,
             &type_name,
+            def_location,
             cx.size_and_align_of(closure_env_type),
             Some(containing_scope),
             DIFlags::FlagZero,
@@ -1219,6 +1271,11 @@ fn build_union_type_di_node<'ll, 'tcx>(
     let containing_scope = get_namespace_for_item(cx, union_def_id);
     let union_ty_and_layout = cx.layout_of(union_type);
     let type_name = compute_debuginfo_type_name(cx.tcx, union_type, false);
+    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+        Some(file_metadata_from_def_id(cx, Some(union_def_id)))
+    } else {
+        None
+    };
 
     type_map::build_type_with_children(
         cx,
@@ -1227,6 +1284,7 @@ fn build_union_type_di_node<'ll, 'tcx>(
             Stub::Union,
             unique_type_id,
             &type_name,
+            def_location,
             size_and_align_of(union_ty_and_layout),
             Some(containing_scope),
             DIFlags::FlagZero,
@@ -1239,6 +1297,11 @@ fn build_union_type_di_node<'ll, 'tcx>(
                 .enumerate()
                 .map(|(i, f)| {
                     let field_layout = union_ty_and_layout.field(cx, i);
+                    let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+                        Some(f.did)
+                    } else {
+                        None
+                    };
                     build_field_di_node(
                         cx,
                         owner,
@@ -1247,6 +1310,7 @@ fn build_union_type_di_node<'ll, 'tcx>(
                         Size::ZERO,
                         DIFlags::FlagZero,
                         type_di_node(cx, field_layout.ty),
+                        def_id,
                     )
                 })
                 .collect()
@@ -1321,14 +1385,7 @@ pub(crate) fn build_global_var_di_node<'ll>(
     // We may want to remove the namespace scope if we're in an extern block (see
     // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952).
     let var_scope = get_namespace_for_item(cx, def_id);
-    let span = hygiene::walk_chain_collapsed(tcx.def_span(def_id), DUMMY_SP);
-
-    let (file_metadata, line_number) = if !span.is_dummy() {
-        let loc = cx.lookup_debug_loc(span.lo());
-        (file_metadata(cx, &loc.file), loc.line)
-    } else {
-        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
-    };
+    let (file_metadata, line_number) = file_metadata_from_def_id(cx, Some(def_id));
 
     let is_local_to_unit = is_node_local_to_unit(cx, def_id);
 
@@ -1418,6 +1475,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>(
             Stub::VTableTy { vtable_holder },
             unique_type_id,
             &vtable_type_name,
+            None,
             (size, pointer_align),
             NO_SCOPE_METADATA,
             DIFlags::FlagArtificial,
@@ -1455,6 +1513,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>(
                         field_offset,
                         DIFlags::FlagZero,
                         field_type_di_node,
+                        None,
                     ))
                 })
                 .collect()
@@ -1606,3 +1665,20 @@ fn tuple_field_name(field_index: usize) -> Cow<'static, str> {
         .map(|s| Cow::from(*s))
         .unwrap_or_else(|| Cow::from(format!("__{field_index}")))
 }
+
+pub(crate) type DefinitionLocation<'ll> = (&'ll DIFile, c_uint);
+
+pub(crate) fn file_metadata_from_def_id<'ll>(
+    cx: &CodegenCx<'ll, '_>,
+    def_id: Option<DefId>,
+) -> DefinitionLocation<'ll> {
+    if let Some(def_id) = def_id
+        && let span = hygiene::walk_chain_collapsed(cx.tcx.def_span(def_id), DUMMY_SP)
+        && !span.is_dummy()
+    {
+        let loc = cx.lookup_debug_loc(span.lo());
+        (file_metadata(cx, &loc.file), loc.line)
+    } else {
+        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
+    }
+}
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index 100b046cee2..d374767f187 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -4,7 +4,7 @@ use libc::c_uint;
 use rustc_abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants};
 use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name;
 use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo};
-use rustc_codegen_ssa::traits::ConstCodegenMethods;
+use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods};
 use rustc_index::IndexVec;
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
@@ -16,8 +16,8 @@ use crate::debuginfo::metadata::enums::DiscrResult;
 use crate::debuginfo::metadata::type_map::{self, Stub, UniqueTypeId};
 use crate::debuginfo::metadata::{
     DINodeCreationResult, NO_GENERICS, NO_SCOPE_METADATA, SmallVec, UNKNOWN_LINE_NUMBER,
-    build_field_di_node, file_metadata, size_and_align_of, type_di_node, unknown_file_metadata,
-    visibility_di_flags,
+    build_field_di_node, file_metadata, file_metadata_from_def_id, size_and_align_of, type_di_node,
+    unknown_file_metadata, visibility_di_flags,
 };
 use crate::debuginfo::utils::DIB;
 use crate::llvm::debuginfo::{DIFile, DIFlags, DIType};
@@ -192,6 +192,12 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
 
     assert!(!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout));
 
+    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+        Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did())))
+    } else {
+        None
+    };
+
     type_map::build_type_with_children(
         cx,
         type_map::stub(
@@ -199,6 +205,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
             type_map::Stub::Union,
             unique_type_id,
             &enum_type_name,
+            def_location,
             cx.size_and_align_of(enum_type),
             NO_SCOPE_METADATA,
             visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()),
@@ -262,6 +269,14 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
     unique_type_id: UniqueTypeId<'tcx>,
 ) -> DINodeCreationResult<'ll> {
     let coroutine_type = unique_type_id.expect_ty();
+    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+        let &ty::Coroutine(coroutine_def_id, _) = coroutine_type.kind() else {
+            bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type)
+        };
+        Some(file_metadata_from_def_id(cx, Some(coroutine_def_id)))
+    } else {
+        None
+    };
     let coroutine_type_and_layout = cx.layout_of(coroutine_type);
     let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false);
 
@@ -274,6 +289,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
             type_map::Stub::Union,
             unique_type_id,
             &coroutine_type_name,
+            def_location,
             size_and_align_of(coroutine_type_and_layout),
             NO_SCOPE_METADATA,
             DIFlags::FlagZero,
@@ -321,6 +337,12 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
     let tag_base_type_di_node = type_di_node(cx, tag_base_type);
     let tag_base_type_align = cx.align_of(tag_base_type);
 
+    let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+        Some(enum_adt_def.did())
+    } else {
+        None
+    };
+
     let variant_names_type_di_node = build_variant_names_type_di_node(
         cx,
         enum_type_di_node,
@@ -328,6 +350,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
             variant_index,
             Cow::from(enum_adt_def.variant(variant_index).name.as_str()),
         )),
+        enum_adt_def_id,
     );
 
     let variant_struct_type_wrapper_di_node = build_variant_struct_wrapper_type_di_node(
@@ -341,6 +364,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
         tag_base_type_di_node,
         tag_base_type,
         DiscrResult::NoDiscriminant,
+        None,
     );
 
     smallvec![
@@ -354,6 +378,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
             Size::ZERO,
             visibility_flags,
             variant_struct_type_wrapper_di_node,
+            None,
         ),
         unsafe {
             llvm::LLVMRustDIBuilderCreateStaticMemberType(
@@ -383,6 +408,12 @@ fn build_union_fields_for_enum<'ll, 'tcx>(
 ) -> SmallVec<&'ll DIType> {
     let tag_base_type = tag_base_type(cx.tcx, enum_type_and_layout);
 
+    let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+        Some(enum_adt_def.did())
+    } else {
+        None
+    };
+
     let variant_names_type_di_node = build_variant_names_type_di_node(
         cx,
         enum_type_di_node,
@@ -390,6 +421,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>(
             let variant_name = Cow::from(enum_adt_def.variant(variant_index).name.as_str());
             (variant_index, variant_name)
         }),
+        enum_adt_def_id,
     );
     let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did());
 
@@ -447,6 +479,7 @@ fn build_variant_names_type_di_node<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     containing_scope: &'ll DIType,
     variants: impl Iterator<Item = (VariantIdx, Cow<'tcx, str>)>,
+    enum_def_id: Option<rustc_span::def_id::DefId>,
 ) -> &'ll DIType {
     // Create an enumerator for each variant.
     super::build_enumeration_type_di_node(
@@ -454,6 +487,7 @@ fn build_variant_names_type_di_node<'ll, 'tcx>(
         "VariantNames",
         variant_names_enum_base_type(cx),
         variants.map(|(variant_index, variant_name)| (variant_name, variant_index.as_u32().into())),
+        enum_def_id,
         containing_scope,
     )
 }
@@ -469,6 +503,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
     tag_base_type_di_node: &'ll DIType,
     tag_base_type: Ty<'tcx>,
     discr: DiscrResult,
+    source_info: Option<(&'ll DIFile, c_uint)>,
 ) -> &'ll DIType {
     type_map::build_type_with_children(
         cx,
@@ -481,6 +516,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
                 variant_index,
             ),
             &variant_struct_wrapper_type_name(variant_index),
+            source_info,
             // NOTE: We use size and align of enum_type, not from variant_layout:
             size_and_align_of(enum_or_coroutine_type_and_layout),
             Some(enum_or_coroutine_type_di_node),
@@ -530,6 +566,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
                 Size::ZERO,
                 DIFlags::FlagZero,
                 variant_struct_type_di_node,
+                None,
             ));
 
             let build_assoc_const =
@@ -684,6 +721,11 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
         variant_range
             .clone()
             .map(|variant_index| (variant_index, CoroutineArgs::variant_name(variant_index))),
+        if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+            Some(coroutine_def_id)
+        } else {
+            None
+        },
     );
 
     let discriminants: IndexVec<VariantIdx, DiscrResult> = {
@@ -776,6 +818,11 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
             tag_base_type_di_node,
             tag_base_type,
             variant_member_info.discr,
+            if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+                variant_member_info.source_info
+            } else {
+                None
+            },
         );
 
         // We use LLVMRustDIBuilderCreateMemberType() member type directly because
@@ -831,6 +878,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
             lo_offset,
             di_flags,
             type_di_node,
+            None,
         ));
 
         unions_fields.push(build_field_di_node(
@@ -841,6 +889,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
             hi_offset,
             DIFlags::FlagZero,
             type_di_node,
+            None,
         ));
     } else {
         unions_fields.push(build_field_di_node(
@@ -851,6 +900,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
             enum_type_and_layout.fields.offset(tag_field),
             di_flags,
             tag_base_type_di_node,
+            None,
         ));
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index b3d4a6642a1..65ab22ad89e 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -3,6 +3,7 @@ use std::borrow::Cow;
 use rustc_abi::{FieldIdx, TagEncoding, VariantIdx, Variants};
 use rustc_codegen_ssa::debuginfo::type_names::{compute_debuginfo_type_name, cpp_like_debuginfo};
 use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo};
+use rustc_codegen_ssa::traits::MiscCodegenMethods;
 use rustc_hir::def::CtorKind;
 use rustc_index::IndexSlice;
 use rustc_middle::bug;
@@ -16,8 +17,8 @@ use super::{SmallVec, size_and_align_of};
 use crate::common::{AsCCharPtr, CodegenCx};
 use crate::debuginfo::metadata::type_map::{self, Stub};
 use crate::debuginfo::metadata::{
-    UNKNOWN_LINE_NUMBER, build_field_di_node, build_generic_type_param_di_nodes, type_di_node,
-    unknown_file_metadata,
+    UNKNOWN_LINE_NUMBER, build_field_di_node, build_generic_type_param_di_nodes,
+    file_metadata_from_def_id, type_di_node, unknown_file_metadata,
 };
 use crate::debuginfo::utils::{DIB, create_DIArray, get_namespace_for_item};
 use crate::llvm::debuginfo::{DIFlags, DIType};
@@ -68,6 +69,11 @@ fn build_c_style_enum_di_node<'ll, 'tcx>(
     enum_type_and_layout: TyAndLayout<'tcx>,
 ) -> DINodeCreationResult<'ll> {
     let containing_scope = get_namespace_for_item(cx, enum_adt_def.did());
+    let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+        Some(enum_adt_def.did())
+    } else {
+        None
+    };
     DINodeCreationResult {
         di_node: build_enumeration_type_di_node(
             cx,
@@ -77,6 +83,7 @@ fn build_c_style_enum_di_node<'ll, 'tcx>(
                 let name = Cow::from(enum_adt_def.variant(variant_index).name.as_str());
                 (name, discr.val)
             }),
+            enum_adt_def_id,
             containing_scope,
         ),
         already_stored_in_typemap: false,
@@ -92,6 +99,7 @@ fn build_enumeration_type_di_node<'ll, 'tcx>(
     type_name: &str,
     base_type: Ty<'tcx>,
     enumerators: impl Iterator<Item = (Cow<'tcx, str>, u128)>,
+    def_id: Option<rustc_span::def_id::DefId>,
     containing_scope: &'ll DIType,
 ) -> &'ll DIType {
     let is_unsigned = match base_type.kind() {
@@ -115,14 +123,21 @@ fn build_enumeration_type_di_node<'ll, 'tcx>(
         })
         .collect();
 
+    let (file_metadata, line_number) = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers
+    {
+        file_metadata_from_def_id(cx, def_id)
+    } else {
+        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
+    };
+
     unsafe {
         llvm::LLVMRustDIBuilderCreateEnumerationType(
             DIB(cx),
             containing_scope,
             type_name.as_c_char_ptr(),
             type_name.len(),
-            unknown_file_metadata(cx),
-            UNKNOWN_LINE_NUMBER,
+            file_metadata,
+            line_number,
             size.bits(),
             align.bits() as u32,
             create_DIArray(DIB(cx), &enumerator_di_nodes[..]),
@@ -193,6 +208,12 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
 ) -> &'ll DIType {
     assert_eq!(variant_layout.ty, enum_type_and_layout.ty);
 
+    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+        Some(file_metadata_from_def_id(cx, Some(variant_def.def_id)))
+    } else {
+        None
+    };
+
     type_map::build_type_with_children(
         cx,
         type_map::stub(
@@ -204,6 +225,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
                 variant_index,
             ),
             variant_def.name.as_str(),
+            def_location,
             // NOTE: We use size and align of enum_type, not from variant_layout:
             size_and_align_of(enum_type_and_layout),
             Some(enum_type_di_node),
@@ -231,6 +253,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
                         variant_layout.fields.offset(field_index),
                         di_flags,
                         type_di_node(cx, field_layout.ty),
+                        None,
                     )
                 })
                 .collect::<SmallVec<_>>()
@@ -286,6 +309,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
             Stub::Struct,
             unique_type_id,
             &variant_name,
+            None,
             size_and_align_of(coroutine_type_and_layout),
             Some(coroutine_type_di_node),
             DIFlags::FlagZero,
@@ -312,6 +336,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
                         variant_layout.fields.offset(field_index),
                         DIFlags::FlagZero,
                         type_di_node(cx, field_type),
+                        None,
                     )
                 })
                 .collect();
@@ -331,6 +356,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
                         coroutine_type_and_layout.fields.offset(index),
                         DIFlags::FlagZero,
                         type_di_node(cx, upvar_ty),
+                        None,
                     )
                 })
                 .collect();
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
index d4006691d37..241bf167a81 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
@@ -4,7 +4,7 @@ use libc::c_uint;
 use rustc_abi::{Size, TagEncoding, VariantIdx, Variants};
 use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name;
 use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo};
-use rustc_codegen_ssa::traits::ConstCodegenMethods;
+use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods};
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self};
@@ -14,7 +14,8 @@ use crate::common::{AsCCharPtr, CodegenCx};
 use crate::debuginfo::metadata::type_map::{self, Stub, StubInfo, UniqueTypeId};
 use crate::debuginfo::metadata::{
     DINodeCreationResult, NO_GENERICS, SmallVec, UNKNOWN_LINE_NUMBER, file_metadata,
-    size_and_align_of, type_di_node, unknown_file_metadata, visibility_di_flags,
+    file_metadata_from_def_id, size_and_align_of, type_di_node, unknown_file_metadata,
+    visibility_di_flags,
 };
 use crate::debuginfo::utils::{DIB, create_DIArray, get_namespace_for_item};
 use crate::llvm::debuginfo::{DIFile, DIFlags, DIType};
@@ -55,6 +56,12 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
 
     assert!(!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout));
 
+    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+        Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did())))
+    } else {
+        None
+    };
+
     type_map::build_type_with_children(
         cx,
         type_map::stub(
@@ -62,6 +69,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
             Stub::Struct,
             unique_type_id,
             &enum_type_name,
+            def_location,
             size_and_align_of(enum_type_and_layout),
             Some(containing_scope),
             visibility_flags,
@@ -84,14 +92,27 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
                         enum_type_and_layout.for_variant(cx, variant_index),
                         visibility_flags,
                     ),
-                    source_info: None,
+                    source_info: if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+                        Some(file_metadata_from_def_id(
+                            cx,
+                            Some(enum_adt_def.variant(variant_index).def_id),
+                        ))
+                    } else {
+                        None
+                    },
                 })
                 .collect();
 
+            let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+                Some(enum_adt_def.did())
+            } else {
+                None
+            };
             smallvec![build_enum_variant_part_di_node(
                 cx,
                 enum_type_and_layout,
                 enum_type_di_node,
+                enum_adt_def_id,
                 &variant_member_infos[..],
             )]
         },
@@ -134,6 +155,12 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
 
     let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false);
 
+    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+        Some(file_metadata_from_def_id(cx, Some(coroutine_def_id)))
+    } else {
+        None
+    };
+
     type_map::build_type_with_children(
         cx,
         type_map::stub(
@@ -141,6 +168,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
             Stub::Struct,
             unique_type_id,
             &coroutine_type_name,
+            def_location,
             size_and_align_of(coroutine_type_and_layout),
             Some(containing_scope),
             DIFlags::FlagZero,
@@ -197,10 +225,16 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
                 })
                 .collect();
 
+            let coroutine_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
+                Some(coroutine_def_id)
+            } else {
+                None
+            };
             smallvec![build_enum_variant_part_di_node(
                 cx,
                 coroutine_type_and_layout,
                 coroutine_type_di_node,
+                coroutine_def_id,
                 &variant_struct_type_di_nodes[..],
             )]
         },
@@ -228,6 +262,7 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     enum_type_and_layout: TyAndLayout<'tcx>,
     enum_type_di_node: &'ll DIType,
+    enum_type_def_id: Option<rustc_span::def_id::DefId>,
     variant_member_infos: &[VariantMemberInfo<'_, 'll>],
 ) -> &'ll DIType {
     let tag_member_di_node =
@@ -236,6 +271,13 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>(
     let variant_part_unique_type_id =
         UniqueTypeId::for_enum_variant_part(cx.tcx, enum_type_and_layout.ty);
 
+    let (file_metadata, line_number) = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers
+    {
+        file_metadata_from_def_id(cx, enum_type_def_id)
+    } else {
+        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
+    };
+
     let stub = StubInfo::new(
         cx,
         variant_part_unique_type_id,
@@ -246,8 +288,8 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>(
                 enum_type_di_node,
                 variant_part_name.as_c_char_ptr(),
                 variant_part_name.len(),
-                unknown_file_metadata(cx),
-                UNKNOWN_LINE_NUMBER,
+                file_metadata,
+                line_number,
                 enum_type_and_layout.size.bits(),
                 enum_type_and_layout.align.abi.bits() as u32,
                 DIFlags::FlagZero,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
index 4e461476040..a37e719d43f 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
@@ -8,7 +8,7 @@ use rustc_macros::HashStable;
 use rustc_middle::bug;
 use rustc_middle::ty::{self, PolyExistentialTraitRef, Ty, TyCtxt};
 
-use super::{SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata};
+use super::{DefinitionLocation, SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata};
 use crate::common::{AsCCharPtr, CodegenCx};
 use crate::debuginfo::utils::{DIB, create_DIArray, debug_context};
 use crate::llvm::debuginfo::{DIFlags, DIScope, DIType};
@@ -186,6 +186,7 @@ pub(super) fn stub<'ll, 'tcx>(
     kind: Stub<'ll>,
     unique_type_id: UniqueTypeId<'tcx>,
     name: &str,
+    def_location: Option<DefinitionLocation<'ll>>,
     (size, align): (Size, Align),
     containing_scope: Option<&'ll DIScope>,
     flags: DIFlags,
@@ -193,6 +194,12 @@ pub(super) fn stub<'ll, 'tcx>(
     let empty_array = create_DIArray(DIB(cx), &[]);
     let unique_type_id_str = unique_type_id.generate_unique_id_string(cx.tcx);
 
+    let (file_metadata, line_number) = if let Some(def_location) = def_location {
+        (def_location.0, def_location.1)
+    } else {
+        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
+    };
+
     let metadata = match kind {
         Stub::Struct | Stub::VTableTy { .. } => {
             let vtable_holder = match kind {
@@ -205,8 +212,8 @@ pub(super) fn stub<'ll, 'tcx>(
                     containing_scope,
                     name.as_c_char_ptr(),
                     name.len(),
-                    unknown_file_metadata(cx),
-                    UNKNOWN_LINE_NUMBER,
+                    file_metadata,
+                    line_number,
                     size.bits(),
                     align.bits() as u32,
                     flags,
@@ -225,8 +232,8 @@ pub(super) fn stub<'ll, 'tcx>(
                 containing_scope,
                 name.as_c_char_ptr(),
                 name.len(),
-                unknown_file_metadata(cx),
-                UNKNOWN_LINE_NUMBER,
+                file_metadata,
+                line_number,
                 size.bits(),
                 align.bits() as u32,
                 flags,
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index da7f94e8cf7..d8b055137b3 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -1534,6 +1534,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             sym::simd_flog => ("log", bx.type_func(&[vec_ty], vec_ty)),
             sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)),
             sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)),
+            sym::simd_relaxed_fma => ("fmuladd", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)),
             sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)),
             sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)),
             sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)),
@@ -1572,6 +1573,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             | sym::simd_fpowi
             | sym::simd_fsin
             | sym::simd_fsqrt
+            | sym::simd_relaxed_fma
             | sym::simd_round
             | sym::simd_trunc
     ) {
diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs
index 93d90cd16b2..d9c5c3e5af9 100644
--- a/compiler/rustc_codegen_ssa/src/back/apple.rs
+++ b/compiler/rustc_codegen_ssa/src/back/apple.rs
@@ -97,7 +97,7 @@ fn minimum_deployment_target(target: &Target) -> OSVersion {
 }
 
 /// Name of the environment variable used to fetch the deployment target on the given OS.
-fn deployment_target_env_var(os: &str) -> &'static str {
+pub fn deployment_target_env_var(os: &str) -> &'static str {
     match os {
         "macos" => "MACOSX_DEPLOYMENT_TARGET",
         "ios" => "IPHONEOS_DEPLOYMENT_TARGET",
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index f93f4d36e45..c31c94495d0 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -110,7 +110,7 @@ const_eval_extern_type_field = `extern type` field does not have a known offset
 const_eval_fn_ptr_call =
     function pointers need an RFC before allowed to be called in {const_eval_const_context}s
 const_eval_for_loop_into_iter_non_const =
-    cannot convert `{$ty}` into an iterator in {const_eval_const_context}s
+    cannot use `for` loop on `{$ty}` in {const_eval_const_context}s
 
 const_eval_frame_note = {$times ->
     [0] {const_eval_frame_note_inner}
@@ -324,11 +324,11 @@ const_eval_ptr_as_bytes_1 =
     this code performed an operation that depends on the underlying bytes representing a pointer
 const_eval_ptr_as_bytes_2 =
     the absolute address of a pointer is not known at compile-time, so such operations are not supported
-const_eval_question_branch_non_const =
-    `?` cannot determine the branch of `{$ty}` in {const_eval_const_context}s
 
+const_eval_question_branch_non_const =
+    `?` is not allowed on `{$ty}` in {const_eval_const_context}s
 const_eval_question_from_residual_non_const =
-    `?` cannot convert from residual of `{$ty}` in {const_eval_const_context}s
+    `?` is not allowed on `{$ty}` in {const_eval_const_context}s
 
 const_eval_range = in the range {$lo}..={$hi}
 const_eval_range_lower = greater or equal to {$lo}
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index ab81e60a33f..489bb54a6f9 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -180,8 +180,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                     };
                 }
 
-                let mut err = match kind {
-                    CallDesugaringKind::ForLoopIntoIter => {
+                // Don't point at the trait if this is a desugaring...
+                // FIXME(const_trait_impl): we could perhaps do this for `Iterator`.
+                match kind {
+                    CallDesugaringKind::ForLoopIntoIter | CallDesugaringKind::ForLoopNext => {
                         error!(NonConstForLoopIntoIter)
                     }
                     CallDesugaringKind::QuestionBranch => {
@@ -196,10 +198,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                     CallDesugaringKind::Await => {
                         error!(NonConstAwait)
                     }
-                };
-
-                diag_trait(&mut err, self_ty, kind.trait_def_id(tcx));
-                err
+                }
             }
             CallKind::FnCall { fn_trait_id, self_ty } => {
                 let note = match self_ty.kind() {
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 1271d9d2d0d..3cb77d1dcb5 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -139,12 +139,14 @@ where
     match error {
         // Don't emit a new diagnostic for these errors, they are already reported elsewhere or
         // should remain silent.
+        err_inval!(AlreadyReported(info)) => ErrorHandled::Reported(info, span),
         err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
             ErrorHandled::TooGeneric(span)
         }
-        err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span),
         err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
-            ErrorHandled::Reported(ReportedErrorInfo::tainted_by_errors(guar), span)
+            // This can occur in infallible promoteds e.g. when a non-existent type or field is
+            // encountered.
+            ErrorHandled::Reported(ReportedErrorInfo::allowed_in_infallible(guar), span)
         }
         // Report remaining errors.
         _ => {
@@ -152,7 +154,12 @@ where
             let span = span.substitute_dummy(our_span);
             let err = mk(span, frames);
             let mut err = tcx.dcx().create_err(err);
-            let can_be_spurious = matches!(error, InterpErrorKind::ResourceExhaustion(_));
+            // We allow invalid programs in infallible promoteds since invalid layouts can occur
+            // anyway (e.g. due to size overflow). And we allow OOM as that can happen any time.
+            let allowed_in_infallible = matches!(
+                error,
+                InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_)
+            );
 
             let msg = error.diagnostic_message();
             error.add_args(&mut err);
@@ -160,8 +167,8 @@ where
             // Use *our* span to label the interp error
             err.span_label(our_span, msg);
             let g = err.emit();
-            let reported = if can_be_spurious {
-                ReportedErrorInfo::spurious(g)
+            let reported = if allowed_in_infallible {
+                ReportedErrorInfo::allowed_in_infallible(g)
             } else {
                 ReportedErrorInfo::from(g)
             };
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index 8cbdcd68e13..34f795bda75 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -2,6 +2,7 @@
 
 use rustc_abi::VariantIdx;
 use rustc_middle::query::{Key, TyCtxtAt};
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{bug, mir};
 use tracing::instrument;
@@ -85,5 +86,6 @@ pub fn tag_for_variant_provider<'tcx>(
         crate::const_eval::DummyMachine,
     );
 
-    ecx.tag_for_variant(ty, variant_index).unwrap().map(|(tag, _tag_field)| tag)
+    let layout = ecx.layout_of(ty).unwrap();
+    ecx.tag_for_variant(layout, variant_index).unwrap().map(|(tag, _tag_field)| tag)
 }
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index f94d0cbb42b..6faac1582ab 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -1,7 +1,7 @@
 //! Functions for reading and writing discriminants of multi-variant layouts (enums and coroutines).
 
 use rustc_abi::{self as abi, TagEncoding, VariantIdx, Variants};
-use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt};
+use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
 use rustc_middle::ty::{self, CoroutineArgsExt, ScalarInt, Ty};
 use rustc_middle::{mir, span_bug};
 use tracing::{instrument, trace};
@@ -21,17 +21,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         variant_index: VariantIdx,
         dest: &impl Writeable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
-        // Layout computation excludes uninhabited variants from consideration
-        // therefore there's no way to represent those variants in the given layout.
-        // Essentially, uninhabited variants do not have a tag that corresponds to their
-        // discriminant, so we cannot do anything here.
-        // When evaluating we will always error before even getting here, but ConstProp 'executes'
-        // dead code, so we cannot ICE here.
-        if dest.layout().for_variant(self, variant_index).is_uninhabited() {
-            throw_ub!(UninhabitedEnumVariantWritten(variant_index))
-        }
-
-        match self.tag_for_variant(dest.layout().ty, variant_index)? {
+        match self.tag_for_variant(dest.layout(), variant_index)? {
             Some((tag, tag_field)) => {
                 // No need to validate that the discriminant here because the
                 // `TyAndLayout::for_variant()` call earlier already checks the
@@ -80,7 +70,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 if ty.is_enum() {
                     // Hilariously, `Single` is used even for 0-variant enums.
                     // (See https://github.com/rust-lang/rust/issues/89765).
-                    if matches!(ty.kind(), ty::Adt(def, ..) if def.variants().is_empty()) {
+                    if ty.ty_adt_def().unwrap().variants().is_empty() {
                         throw_ub!(UninhabitedEnumVariantRead(index))
                     }
                     // For consistency with `write_discriminant`, and to make sure that
@@ -188,6 +178,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                             let variants =
                                 ty.ty_adt_def().expect("tagged layout for non adt").variants();
                             assert!(variant_index < variants.next_index());
+                            if variant_index == untagged_variant {
+                                // The untagged variant can be in the niche range, but even then it
+                                // is not a valid encoding.
+                                throw_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size)))
+                            }
                             variant_index
                         } else {
                             untagged_variant
@@ -236,10 +231,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     ///   given field index.
     pub(crate) fn tag_for_variant(
         &self,
-        ty: Ty<'tcx>,
+        layout: TyAndLayout<'tcx>,
         variant_index: VariantIdx,
     ) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> {
-        match self.layout_of(ty)?.variants {
+        // Layout computation excludes uninhabited variants from consideration.
+        // Therefore, there's no way to represent those variants in the given layout.
+        // Essentially, uninhabited variants do not have a tag that corresponds to their
+        // discriminant, so we have to bail out here.
+        if layout.for_variant(self, variant_index).is_uninhabited() {
+            throw_ub!(UninhabitedEnumVariantWritten(variant_index))
+        }
+
+        match layout.variants {
             abi::Variants::Single { .. } => {
                 // The tag of a `Single` enum is like the tag of the niched
                 // variant: there's no tag as the discriminant is encoded
@@ -260,7 +263,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 // raw discriminants for enums are isize or bigger during
                 // their computation, but the in-memory tag is the smallest possible
                 // representation
-                let discr = self.discriminant_for_variant(ty, variant_index)?;
+                let discr = self.discriminant_for_variant(layout.ty, variant_index)?;
                 let discr_size = discr.layout.size;
                 let discr_val = discr.to_scalar().to_bits(discr_size)?;
                 let tag_size = tag_layout.size(self);
@@ -286,11 +289,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 ..
             } => {
                 assert!(variant_index != untagged_variant);
+                // We checked that this variant is inhabited, so it must be in the niche range.
+                assert!(
+                    niche_variants.contains(&variant_index),
+                    "invalid variant index for this enum"
+                );
                 let variants_start = niche_variants.start().as_u32();
-                let variant_index_relative = variant_index
-                    .as_u32()
-                    .checked_sub(variants_start)
-                    .expect("overflow computing relative variant idx");
+                let variant_index_relative = variant_index.as_u32().strict_sub(variants_start);
                 // We need to use machine arithmetic when taking into account `niche_start`:
                 // tag_val = variant_index_relative + niche_start_val
                 let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?;
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index fe93a48c2f2..241be5e175c 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -268,7 +268,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         };
         // do not continue if typeck errors occurred (can only occur in local crate)
         if let Some(err) = body.tainted_by_errors {
-            throw_inval!(AlreadyReported(ReportedErrorInfo::tainted_by_errors(err)));
+            throw_inval!(AlreadyReported(ReportedErrorInfo::from(err)));
         }
         interp_ok(body)
     }
@@ -585,13 +585,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     match err {
                         ErrorHandled::TooGeneric(..) => {},
                         ErrorHandled::Reported(reported, span) => {
-                            if reported.is_tainted_by_errors() {
-                                // const-eval will return "tainted" errors if e.g. the layout cannot
-                                // be computed as the type references non-existing names.
-                                // See <https://github.com/rust-lang/rust/issues/124348>.
-                            } else if reported.can_be_spurious() {
+                            if reported.is_allowed_in_infallible() {
                                 // These errors can just sometimes happen, even when the expression
-                                // is nominally "infallible", e.g. when running out of memory.
+                                // is nominally "infallible", e.g. when running out of memory
+                                // or when some layout could not be computed.
                             } else {
                                 // Looks like the const is not captured by `required_consts`, that's bad.
                                 span_bug!(span, "interpret const eval failure of {val:?} which is not in required_consts");
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 2a7408f1c70..b5adf06b300 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -10,6 +10,7 @@
 #![feature(never_type)]
 #![feature(rustdoc_internals)]
 #![feature(slice_ptr_get)]
+#![feature(strict_overflow_ops)]
 #![feature(trait_alias)]
 #![feature(try_blocks)]
 #![feature(unqualified_local_imports)]
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
index 34a2464972a..78d69a66edc 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
@@ -415,6 +415,10 @@ impl<O: ForestObligation> ObligationForest<O> {
             .collect()
     }
 
+    pub fn has_pending_obligations(&self) -> bool {
+        self.nodes.iter().any(|node| node.state.get() == NodeState::Pending)
+    }
+
     fn insert_into_error_cache(&mut self, index: usize) {
         let node = &self.nodes[index];
         self.error_cache
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 85eaae8a104..b7d64f75bf3 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -418,9 +418,7 @@ fn run_compiler(
                 return early_exit();
             }
 
-            if sess.opts.unstable_opts.parse_crate_root_only
-                || sess.opts.unstable_opts.show_span.is_some()
-            {
+            if sess.opts.unstable_opts.parse_crate_root_only {
                 return early_exit();
             }
 
@@ -867,8 +865,9 @@ fn print_crate_info(
             DeploymentTarget => {
                 if sess.target.is_like_osx {
                     println_info!(
-                        "deployment_target={}",
-                        apple::pretty_version(apple::deployment_target(sess))
+                        "{}={}",
+                        apple::deployment_target_env_var(&sess.target.os),
+                        apple::pretty_version(apple::deployment_target(sess)),
                     )
                 } else {
                     #[allow(rustc::diagnostic_outside_of_impl)]
diff --git a/compiler/rustc_error_codes/src/error_codes/E0060.md b/compiler/rustc_error_codes/src/error_codes/E0060.md
index 54b10c886cc..a6831c881e3 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0060.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0060.md
@@ -15,7 +15,7 @@ unsafe { printf(); } // error!
 Using this declaration, it must be called with at least one argument, so
 simply calling `printf()` is invalid. But the following uses are allowed:
 
-```
+```rust,edition2021
 # use std::os::raw::{c_char, c_int};
 # #[cfg_attr(all(windows, target_env = "msvc"),
 #            link(name = "legacy_stdio_definitions",
@@ -23,16 +23,11 @@ simply calling `printf()` is invalid. But the following uses are allowed:
 # extern "C" { fn printf(_: *const c_char, ...) -> c_int; }
 # fn main() {
 unsafe {
-    use std::ffi::CString;
-
-    let fmt = CString::new("test\n").unwrap();
-    printf(fmt.as_ptr());
+    printf(c"test\n".as_ptr());
 
-    let fmt = CString::new("number = %d\n").unwrap();
-    printf(fmt.as_ptr(), 3);
+    printf(c"number = %d\n".as_ptr(), 3);
 
-    let fmt = CString::new("%d, %d\n").unwrap();
-    printf(fmt.as_ptr(), 10, 5);
+    printf(c"%d, %d\n".as_ptr(), 10, 5);
 }
 # }
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0622.md b/compiler/rustc_error_codes/src/error_codes/E0622.md
index 5d71ee9949d..4cb605b636d 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0622.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0622.md
@@ -7,10 +7,11 @@ Erroneous code example:
 #![allow(internal_features)]
 
 extern "rust-intrinsic" {
-    pub static breakpoint: fn(); // error: intrinsic must be a function
+    pub static atomic_singlethreadfence_seqcst: fn();
+    // error: intrinsic must be a function
 }
 
-fn main() { unsafe { breakpoint(); } }
+fn main() { unsafe { atomic_singlethreadfence_seqcst(); } }
 ```
 
 An intrinsic is a function available for use in a given programming language
@@ -22,8 +23,8 @@ error, just declare a function. Example:
 #![allow(internal_features)]
 
 extern "rust-intrinsic" {
-    pub fn breakpoint(); // ok!
+    pub fn atomic_singlethreadfence_seqcst(); // ok!
 }
 
-fn main() { unsafe { breakpoint(); } }
+fn main() { unsafe { atomic_singlethreadfence_seqcst(); } }
 ```
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 798668b8bc1..b4510371323 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -6,6 +6,7 @@ use std::path::{Path, PathBuf};
 use std::process::ExitStatus;
 
 use rustc_abi::TargetDataLayoutErrors;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_ast_pretty::pprust;
 use rustc_macros::Subdiagnostic;
 use rustc_span::Span;
@@ -298,6 +299,12 @@ impl IntoDiagArg for hir::def::Namespace {
     }
 }
 
+impl IntoDiagArg for ExprPrecedence {
+    fn into_diag_arg(self) -> DiagArgValue {
+        DiagArgValue::Number(self as i32)
+    }
+}
+
 #[derive(Clone)]
 pub struct DiagSymbolList<S = Symbol>(Vec<S>);
 
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 19c2d466f7c..e5500c8bba1 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -732,7 +732,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         _ => item.to_tokens(),
                     };
                     let attr_item = attr.unwrap_normal_item();
-                    if let AttrArgs::Eq(..) = attr_item.args {
+                    if let AttrArgs::Eq { .. } = attr_item.args {
                         self.cx.dcx().emit_err(UnsupportedKeyValue { span });
                     }
                     let inner_tokens = attr_item.args.inner_tokens();
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 69a14bd9f12..8b4f441dafe 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -119,6 +119,13 @@ declare_features! (
     (removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")),
     /// Allows defining generators.
     (removed, generators, "1.21.0", Some(43122), Some("renamed to `coroutines`")),
+    /// An extension to the `generic_associated_types` feature, allowing incomplete features.
+    (removed, generic_associated_types_extended, "CURRENT_RUSTC_VERSION", Some(95451),
+        Some(
+            "feature needs overhaul and reimplementation pending \
+            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")),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index ec908762da7..abc7200699c 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -394,6 +394,8 @@ declare_features! (
     (unstable, async_fn_track_caller, "1.73.0", Some(110011)),
     /// Allows `for await` loops.
     (unstable, async_for_loop, "1.77.0", Some(118898)),
+    /// Allows `async` trait bound modifier.
+    (unstable, async_trait_bounds, "CURRENT_RUSTC_VERSION", Some(62290)),
     /// Allows using C-variadics.
     (unstable, c_variadic, "1.34.0", Some(44930)),
     /// Allows the use of `#[cfg(<true/false>)]`.
@@ -497,8 +499,6 @@ declare_features! (
     (unstable, gen_blocks, "1.75.0", Some(117078)),
     /// Infer generic args for both consts and types.
     (unstable, generic_arg_infer, "1.55.0", Some(85077)),
-    /// An extension to the `generic_associated_types` feature, allowing incomplete features.
-    (incomplete, generic_associated_types_extended, "1.61.0", Some(95451)),
     /// Allows non-trivial generic constants which have to have wfness manually propagated to callers
     (incomplete, generic_const_exprs, "1.56.0", Some(76560)),
     /// Allows generic parameters and where-clauses on free & associated const items.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 97aa88c1de8..a9696627f11 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1,7 +1,7 @@
 use std::fmt;
 
 use rustc_abi::ExternAbi;
-use rustc_ast::util::parser::{AssocOp, PREC_CLOSURE, PREC_JUMP, PREC_PREFIX, PREC_UNAMBIGUOUS};
+use rustc_ast::util::parser::{AssocOp, ExprPrecedence};
 use rustc_ast::{
     self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label,
     LitKind, TraitObjectSyntax, UintTy,
@@ -1695,22 +1695,22 @@ pub struct Expr<'hir> {
 }
 
 impl Expr<'_> {
-    pub fn precedence(&self) -> i8 {
+    pub fn precedence(&self) -> ExprPrecedence {
         match self.kind {
-            ExprKind::Closure { .. } => PREC_CLOSURE,
+            ExprKind::Closure { .. } => ExprPrecedence::Closure,
 
             ExprKind::Break(..)
             | ExprKind::Continue(..)
             | ExprKind::Ret(..)
             | ExprKind::Yield(..)
-            | ExprKind::Become(..) => PREC_JUMP,
+            | ExprKind::Become(..) => ExprPrecedence::Jump,
 
             // Binop-like expr kinds, handled by `AssocOp`.
-            ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence() as i8,
-            ExprKind::Cast(..) => AssocOp::As.precedence() as i8,
+            ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
+            ExprKind::Cast(..) => ExprPrecedence::Cast,
 
             ExprKind::Assign(..) |
-            ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8,
+            ExprKind::AssignOp(..) => ExprPrecedence::Assign,
 
             // Unary, prefix
             ExprKind::AddrOf(..)
@@ -1719,7 +1719,7 @@ impl Expr<'_> {
             // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`
             // but we need to print `(let _ = a) < b` as-is with parens.
             | ExprKind::Let(..)
-            | ExprKind::Unary(..) => PREC_PREFIX,
+            | ExprKind::Unary(..) => ExprPrecedence::Prefix,
 
             // Never need parens
             ExprKind::Array(_)
@@ -1740,7 +1740,7 @@ impl Expr<'_> {
             | ExprKind::Struct(..)
             | ExprKind::Tup(_)
             | ExprKind::Type(..)
-            | ExprKind::Err(_) => PREC_UNAMBIGUOUS,
+            | ExprKind::Err(_) => ExprPrecedence::Unambiguous,
 
             ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
         }
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index cb658111392..070d63b48b7 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -113,8 +113,6 @@ hir_analysis_const_param_ty_impl_on_unsized =
     the trait `ConstParamTy` may not be implemented for this type
     .label = type is not `Sized`
 
-hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
-
 hir_analysis_copy_impl_on_non_adt =
     the trait `Copy` cannot be implemented for this type
     .label = type is not a structure or enumeration
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index e1f4ccca97e..022a6d457ec 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -103,7 +103,7 @@ fn allowed_union_or_unsafe_field<'tcx>(
             // Fallback case: allow `ManuallyDrop` and things that are `Copy`,
             // also no need to report an error if the type is unresolved.
             ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop())
-                || ty.is_copy_modulo_regions(tcx, typing_env)
+                || tcx.type_is_copy_modulo_regions(typing_env, ty)
                 || ty.references_error()
         }
     };
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 3e33120901f..2e6b511412b 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -87,6 +87,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
         | sym::assert_inhabited
         | sym::assert_zero_valid
         | sym::assert_mem_uninitialized_valid
+        | sym::breakpoint
         | sym::size_of
         | sym::min_align_of
         | sym::needs_drop
@@ -641,7 +642,9 @@ pub fn check_intrinsic_type(
             | sym::simd_round
             | sym::simd_trunc => (1, 0, vec![param(0)], param(0)),
             sym::simd_fpowi => (1, 0, vec![param(0), tcx.types.i32], param(0)),
-            sym::simd_fma => (1, 0, vec![param(0), param(0), param(0)], param(0)),
+            sym::simd_fma | sym::simd_relaxed_fma => {
+                (1, 0, vec![param(0), param(0), param(0)], param(0))
+            }
             sym::simd_gather => (3, 0, vec![param(0), param(1), param(2)], param(0)),
             sym::simd_masked_load => (3, 0, vec![param(0), param(1), param(2)], param(2)),
             sym::simd_masked_store => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit),
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index b96469f503c..df4da03f0f5 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -178,7 +178,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
 
         // Check that the type implements Copy. The only case where this can
         // possibly fail is for SIMD types which don't #[derive(Copy)].
-        if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) {
+        if !self.tcx.type_is_copy_modulo_regions(self.typing_env, ty) {
             let msg = "arguments for inline assembly must be copyable";
             self.tcx
                 .dcx()
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 8fa797db246..2b33da3c49a 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -13,6 +13,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
 use rustc_macros::LintDiagnostic;
+use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
@@ -116,13 +117,12 @@ where
     }
     f(&mut wfcx)?;
 
-    let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;
-
     let errors = wfcx.select_all_or_error();
     if !errors.is_empty() {
         return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
     }
 
+    let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;
     debug!(?assumed_wf_types);
 
     let infcx_compat = infcx.fork();
@@ -1170,19 +1170,13 @@ fn check_type_defn<'tcx>(
 
             // Explicit `enum` discriminant values must const-evaluate successfully.
             if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr {
-                let cause = traits::ObligationCause::new(
-                    tcx.def_span(discr_def_id),
-                    wfcx.body_def_id,
-                    ObligationCauseCode::Misc,
-                );
-                wfcx.register_obligation(Obligation::new(
-                    tcx,
-                    cause,
-                    wfcx.param_env,
-                    ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(
-                        ty::Const::from_anon_const(tcx, discr_def_id.expect_local()),
-                    ))),
-                ));
+                match tcx.const_eval_poly(discr_def_id) {
+                    Ok(_) => {}
+                    Err(ErrorHandled::Reported(..)) => {}
+                    Err(ErrorHandled::TooGeneric(sp)) => {
+                        span_bug!(sp, "enum variant discr was too generic to eval")
+                    }
+                }
             }
         }
 
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 8d5824130d8..a4636da3f62 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -309,10 +309,10 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
                     self.tcx.ensure().type_of(param.def_id);
                     if let Some(default) = default {
                         // need to store default and type of default
+                        self.tcx.ensure().const_param_default(param.def_id);
                         if let hir::ConstArgKind::Anon(ac) = default.kind {
                             self.tcx.ensure().type_of(ac.def_id);
                         }
-                        self.tcx.ensure().const_param_default(param.def_id);
                     }
                 }
             }
@@ -1817,7 +1817,6 @@ fn const_param_default<'tcx>(
         ),
     };
     let icx = ItemCtxt::new(tcx, def_id);
-    // FIXME(const_generics): investigate which places do and don't need const ty feeding
-    let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::No);
+    let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id()));
     ty::EarlyBinder::bind(ct)
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs
index 8648a7d1e32..f1022d95753 100644
--- a/compiler/rustc_hir_analysis/src/collect/dump.rs
+++ b/compiler/rustc_hir_analysis/src/collect/dump.rs
@@ -1,6 +1,6 @@
 use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
 use rustc_hir::intravisit;
-use rustc_middle::hir::nested_filter::OnlyBodies;
+use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::sym;
 
@@ -42,7 +42,8 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) {
 }
 
 pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
-    for did in tcx.hir().body_owners() {
+    for iid in tcx.hir().items() {
+        let did = iid.owner_id.def_id;
         if tcx.has_attr(did, sym::rustc_dump_def_parents) {
             struct AnonConstFinder<'tcx> {
                 tcx: TyCtxt<'tcx>,
@@ -50,7 +51,7 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
             }
 
             impl<'tcx> intravisit::Visitor<'tcx> for AnonConstFinder<'tcx> {
-                type NestedFilter = OnlyBodies;
+                type NestedFilter = nested_filter::All;
 
                 fn nested_visit_map(&mut self) -> Self::Map {
                     self.tcx.hir()
@@ -62,11 +63,11 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
                 }
             }
 
-            // Look for any anon consts inside of this body owner as there is no way to apply
+            // Look for any anon consts inside of this item as there is no way to apply
             // the `rustc_dump_def_parents` attribute to the anon const so it would not be possible
             // to see what its def parent is.
             let mut anon_ct_finder = AnonConstFinder { tcx, anon_consts: vec![] };
-            intravisit::walk_expr(&mut anon_ct_finder, tcx.hir().body_owned_by(did).value);
+            intravisit::walk_item(&mut anon_ct_finder, tcx.hir().item(iid));
 
             for did in [did].into_iter().chain(anon_ct_finder.anon_consts) {
                 let span = tcx.def_span(did);
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 077696ac1f2..1d9114b0ef3 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -419,7 +419,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
     if let Node::ConstBlock(_) = node {
         own_params.push(ty::GenericParamDef {
             index: next_index(),
-            name: Symbol::intern("<const_ty>"),
+            name: rustc_span::sym::const_ty_placeholder,
             def_id: def_id.to_def_id(),
             pure_wrt_drop: false,
             kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index bfee5d33598..ca2597e79fd 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -1,12 +1,13 @@
 use std::assert_matches::assert_matches;
 
-use hir::{HirId, Node};
+use hir::Node;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_middle::ty::{self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, Upcast};
+use rustc_middle::ty::{
+    self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast,
+};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Ident;
 use rustc_span::{DUMMY_SP, Span};
@@ -305,7 +306,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     }
 
     if tcx.features().generic_const_exprs() {
-        predicates.extend(const_evaluatable_predicates_of(tcx, def_id));
+        predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates));
     }
 
     let mut predicates: Vec<_> = predicates.into_iter().collect();
@@ -369,32 +370,48 @@ fn compute_bidirectional_outlives_predicates<'tcx>(
     }
 }
 
-fn const_evaluatable_predicates_of(
-    tcx: TyCtxt<'_>,
+#[instrument(level = "debug", skip(tcx, predicates), ret)]
+fn const_evaluatable_predicates_of<'tcx>(
+    tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
-) -> FxIndexSet<(ty::Clause<'_>, Span)> {
+    predicates: &FxIndexSet<(ty::Clause<'tcx>, Span)>,
+) -> FxIndexSet<(ty::Clause<'tcx>, Span)> {
     struct ConstCollector<'tcx> {
         tcx: TyCtxt<'tcx>,
         preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
     }
 
-    impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> {
-        fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
-            let ct = ty::Const::from_anon_const(self.tcx, c.def_id);
-            if let ty::ConstKind::Unevaluated(_) = ct.kind() {
-                let span = self.tcx.def_span(c.def_id);
-                self.preds.insert((ty::ClauseKind::ConstEvaluatable(ct).upcast(self.tcx), span));
-            }
-        }
+    fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool {
+        let hir_id = tcx.local_def_id_to_hir_id(def);
+        let (_, parent_node) = tcx
+            .hir()
+            .parent_iter(hir_id)
+            .skip_while(|(_, n)| matches!(n, Node::ConstArg(..)))
+            .next()
+            .unwrap();
+        matches!(
+            parent_node,
+            Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { .. }, .. })
+        )
+    }
 
-        fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::ConstArg<'tcx>) {
-            // Do not look into const param defaults,
-            // these get checked when they are actually instantiated.
-            //
-            // We do not want the following to error:
-            //
-            //     struct Foo<const N: usize, const M: usize = { N + 1 }>;
-            //     struct Bar<const N: usize>(Foo<N, 3>);
+    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> {
+        fn visit_const(&mut self, c: ty::Const<'tcx>) {
+            if let ty::ConstKind::Unevaluated(uv) = c.kind() {
+                if is_const_param_default(self.tcx, uv.def.expect_local()) {
+                    // Do not look into const param defaults,
+                    // these get checked when they are actually instantiated.
+                    //
+                    // We do not want the following to error:
+                    //
+                    //     struct Foo<const N: usize, const M: usize = { N + 1 }>;
+                    //     struct Bar<const N: usize>(Foo<N, 3>);
+                    return;
+                }
+
+                let span = self.tcx.def_span(uv.def);
+                self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span));
+            }
         }
     }
 
@@ -402,28 +419,31 @@ fn const_evaluatable_predicates_of(
     let node = tcx.hir_node(hir_id);
 
     let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
+
+    for (clause, _sp) in predicates {
+        clause.visit_with(&mut collector);
+    }
+
     if let hir::Node::Item(item) = node
-        && let hir::ItemKind::Impl(impl_) = item.kind
+        && let hir::ItemKind::Impl(_) = item.kind
     {
-        if let Some(of_trait) = &impl_.of_trait {
-            debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id);
-            collector.visit_trait_ref(of_trait);
+        if let Some(of_trait) = tcx.impl_trait_ref(def_id) {
+            debug!("visit impl trait_ref");
+            of_trait.instantiate_identity().visit_with(&mut collector);
         }
 
-        debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id);
-        collector.visit_ty(impl_.self_ty);
-    }
-
-    if let Some(generics) = node.generics() {
-        debug!("const_evaluatable_predicates_of({:?}): visit_generics", def_id);
-        collector.visit_generics(generics);
+        debug!("visit self_ty");
+        let self_ty = tcx.type_of(def_id);
+        self_ty.instantiate_identity().visit_with(&mut collector);
     }
 
-    if let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id) {
-        debug!("const_evaluatable_predicates_of({:?}): visit_fn_decl", def_id);
-        collector.visit_fn_decl(fn_sig.decl);
+    if let Some(_) = tcx.hir().fn_sig_by_hir_id(hir_id) {
+        debug!("visit fn sig");
+        let fn_sig = tcx.fn_sig(def_id);
+        let fn_sig = fn_sig.instantiate_identity();
+        debug!(?fn_sig);
+        fn_sig.visit_with(&mut collector);
     }
-    debug!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.preds);
 
     collector.preds
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 7cf99bebd36..72d5b3ac4f5 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -12,7 +12,6 @@ use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableEx
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Ident;
 use rustc_span::{DUMMY_SP, Span};
-use tracing::debug;
 
 use super::{ItemCtxt, bad_placeholder};
 use crate::errors::TypeofReservedKeywordUsed;
@@ -138,252 +137,26 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span
     use hir::*;
     use rustc_middle::ty::Ty;
 
-    let parent_node_id = tcx.parent_hir_id(arg_hir_id);
-    let parent_node = tcx.hir_node(parent_node_id);
-
-    let (generics, arg_idx) = match parent_node {
-        // Easy case: arrays repeat expressions.
+    match tcx.parent_hir_node(arg_hir_id) {
+        // Array length const arguments do not have `type_of` fed as there is never a corresponding
+        // generic parameter definition.
         Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
         | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
             if constant.hir_id == arg_hir_id =>
         {
             return tcx.types.usize;
         }
-        Node::GenericParam(&GenericParam {
-            def_id: param_def_id,
-            kind: GenericParamKind::Const { default: Some(ct), .. },
-            ..
-        }) if ct.hir_id == arg_hir_id => {
-            return tcx
-                .type_of(param_def_id)
-                .no_bound_vars()
-                .expect("const parameter types cannot be generic");
-        }
-
-        // This match arm is for when the def_id appears in a GAT whose
-        // path can't be resolved without typechecking e.g.
-        //
-        // trait Foo {
-        //   type Assoc<const N: usize>;
-        //   fn foo() -> Self::Assoc<3>;
-        // }
-        //
-        // In the above code we would call this query with the def_id of 3 and
-        // the parent_node we match on would be the hir node for Self::Assoc<3>
-        //
-        // `Self::Assoc<3>` cant be resolved without typechecking here as we
-        // didnt write <Self as Foo>::Assoc<3>. If we did then another match
-        // arm would handle this.
-        //
-        // I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
-        Node::Ty(hir_ty @ hir::Ty { kind: TyKind::Path(QPath::TypeRelative(ty, segment)), .. }) => {
-            // Find the Item containing the associated type so we can create an ItemCtxt.
-            // Using the ItemCtxt lower the HIR for the unresolved assoc type into a
-            // ty which is a fully resolved projection.
-            // For the code example above, this would mean lowering `Self::Assoc<3>`
-            // to a ty::Alias(ty::Projection, `<Self as Foo>::Assoc<3>`).
-            let item_def_id = tcx.hir().get_parent_item(ty.hir_id).def_id;
-            let ty = ItemCtxt::new(tcx, item_def_id).lower_ty(hir_ty);
-
-            // Iterate through the generics of the projection to find the one that corresponds to
-            // the def_id that this query was called with. We filter to only type and const args here
-            // as a precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
-            // but it can't hurt to be safe ^^
-            if let ty::Alias(ty::Projection | ty::Inherent, projection) = ty.kind() {
-                let generics = tcx.generics_of(projection.def_id);
-
-                let arg_index = segment
-                    .args
-                    .and_then(|args| {
-                        args.args
-                            .iter()
-                            .filter(|arg| arg.is_ty_or_const())
-                            .position(|arg| arg.hir_id() == arg_hir_id)
-                    })
-                    .unwrap_or_else(|| {
-                        bug!("no arg matching AnonConst in segment");
-                    });
-
-                (generics, arg_index)
-            } else {
-                // I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
-                return Ty::new_error_with_message(
-                    tcx,
-                    span,
-                    "unexpected non-GAT usage of an anon const",
-                );
-            }
-        }
-        Node::Expr(&Expr {
-            kind:
-                ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
-            ..
-        }) => {
-            let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
-            let tables = tcx.typeck(body_owner);
-            // This may fail in case the method/path does not actually exist.
-            // As there is no relevant param for `def_id`, we simply return
-            // `None` here.
-            let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
-                return Ty::new_error_with_message(
-                    tcx,
-                    span,
-                    format!("unable to find type-dependent def for {parent_node_id:?}"),
-                );
-            };
-            let idx = segment
-                .args
-                .and_then(|args| {
-                    args.args
-                        .iter()
-                        .filter(|arg| arg.is_ty_or_const())
-                        .position(|arg| arg.hir_id() == arg_hir_id)
-                })
-                .unwrap_or_else(|| {
-                    bug!("no arg matching ConstArg in segment");
-                });
-
-            (tcx.generics_of(type_dependent_def), idx)
-        }
-
-        Node::Ty(&hir::Ty { kind: TyKind::Path(_), .. })
-        | Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
-        | Node::TraitRef(..)
-        | Node::Pat(_) => {
-            let path = match parent_node {
-                Node::Ty(&hir::Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
-                | Node::TraitRef(&TraitRef { path, .. }) => &*path,
-                Node::Expr(&Expr {
-                    kind:
-                        ExprKind::Path(QPath::Resolved(_, path))
-                        | ExprKind::Struct(&QPath::Resolved(_, path), ..),
-                    ..
-                }) => {
-                    let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
-                    let _tables = tcx.typeck(body_owner);
-                    &*path
-                }
-                Node::Pat(pat) => {
-                    if let Some(path) = get_path_containing_arg_in_pat(pat, arg_hir_id) {
-                        path
-                    } else {
-                        return Ty::new_error_with_message(
-                            tcx,
-                            span,
-                            format!("unable to find const parent for {arg_hir_id} in pat {pat:?}"),
-                        );
-                    }
-                }
-                _ => {
-                    return Ty::new_error_with_message(
-                        tcx,
-                        span,
-                        format!("unexpected const parent path {parent_node:?}"),
-                    );
-                }
-            };
-
-            // We've encountered an `AnonConst` in some path, so we need to
-            // figure out which generic parameter it corresponds to and return
-            // the relevant type.
-            let Some((arg_index, segment)) = path.segments.iter().find_map(|seg| {
-                let args = seg.args?;
-                args.args
-                    .iter()
-                    .filter(|arg| arg.is_ty_or_const())
-                    .position(|arg| arg.hir_id() == arg_hir_id)
-                    .map(|index| (index, seg))
-                    .or_else(|| {
-                        args.constraints
-                            .iter()
-                            .copied()
-                            .filter_map(AssocItemConstraint::ct)
-                            .position(|ct| ct.hir_id == arg_hir_id)
-                            .map(|idx| (idx, seg))
-                    })
-            }) else {
-                return Ty::new_error_with_message(tcx, span, "no arg matching AnonConst in path");
-            };
-
-            let generics = match tcx.res_generics_def_id(segment.res) {
-                Some(def_id) => tcx.generics_of(def_id),
-                None => {
-                    return Ty::new_error_with_message(
-                        tcx,
-                        span,
-                        format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
-                    );
-                }
-            };
-
-            (generics, arg_index)
-        }
 
-        _ => {
-            return Ty::new_error_with_message(
-                tcx,
-                span,
-                format!("unexpected const arg parent in type_of(): {parent_node:?}"),
-            );
-        }
-    };
-
-    debug!(?parent_node);
-    debug!(?generics, ?arg_idx);
-    if let Some(param_def_id) = generics
-        .own_params
-        .iter()
-        .filter(|param| param.kind.is_ty_or_const())
-        .nth(match generics.has_self && generics.parent.is_none() {
-            true => arg_idx + 1,
-            false => arg_idx,
-        })
-        .and_then(|param| match param.kind {
-            ty::GenericParamDefKind::Const { .. } => {
-                debug!(?param);
-                Some(param.def_id)
-            }
-            _ => None,
-        })
-    {
-        tcx.type_of(param_def_id).no_bound_vars().expect("const parameter types cannot be generic")
-    } else {
-        return Ty::new_error_with_message(
+        // This is not a `bug!` as const arguments in path segments that did not resolve to anything
+        // will result in `type_of` never being fed.
+        _ => Ty::new_error_with_message(
             tcx,
             span,
-            format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
-        );
+            "`type_of` called on const argument's anon const before the const argument was lowered",
+        ),
     }
 }
 
-fn get_path_containing_arg_in_pat<'hir>(
-    pat: &'hir hir::Pat<'hir>,
-    arg_id: HirId,
-) -> Option<&'hir hir::Path<'hir>> {
-    use hir::*;
-
-    let is_arg_in_path = |p: &hir::Path<'_>| {
-        p.segments
-            .iter()
-            .filter_map(|seg| seg.args)
-            .flat_map(|args| args.args)
-            .any(|arg| arg.hir_id() == arg_id)
-    };
-    let mut arg_path = None;
-    pat.walk(|pat| match pat.kind {
-        PatKind::Struct(QPath::Resolved(_, path), _, _)
-        | PatKind::TupleStruct(QPath::Resolved(_, path), _, _)
-        | PatKind::Path(QPath::Resolved(_, path))
-            if is_arg_in_path(path) =>
-        {
-            arg_path = Some(path);
-            false
-        }
-        _ => true,
-    });
-    arg_path
-}
-
 pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, Ty<'_>> {
     use rustc_hir::*;
     use rustc_middle::ty::Ty;
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index fcea0052546..66255829dcf 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -226,13 +226,18 @@ impl TaitConstraintLocator<'_> {
             constrained = true;
 
             if !opaque_types_defined_by.contains(&self.def_id) {
-                self.tcx.dcx().emit_err(TaitForwardCompat {
+                let guar = self.tcx.dcx().emit_err(TaitForwardCompat {
                     span: hidden_type.span,
                     item_span: self
                         .tcx
                         .def_ident_span(item_def_id)
                         .unwrap_or_else(|| self.tcx.def_span(item_def_id)),
                 });
+                // Avoid "opaque type not constrained" errors on the opaque itself.
+                self.found = Some(ty::OpaqueHiddenType {
+                    span: DUMMY_SP,
+                    ty: Ty::new_error(self.tcx, guar),
+                });
             }
             let concrete_type =
                 self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
@@ -248,7 +253,7 @@ impl TaitConstraintLocator<'_> {
         if !constrained {
             debug!("no constraints in typeck results");
             if opaque_types_defined_by.contains(&self.def_id) {
-                self.tcx.dcx().emit_err(TaitForwardCompat2 {
+                let guar = self.tcx.dcx().emit_err(TaitForwardCompat2 {
                     span: self
                         .tcx
                         .def_ident_span(item_def_id)
@@ -256,6 +261,11 @@ impl TaitConstraintLocator<'_> {
                     opaque_type_span: self.tcx.def_span(self.def_id),
                     opaque_type: self.tcx.def_path_str(self.def_id),
                 });
+                // Avoid "opaque type not constrained" errors on the opaque itself.
+                self.found = Some(ty::OpaqueHiddenType {
+                    span: DUMMY_SP,
+                    ty: Ty::new_error(self.tcx, guar),
+                });
             }
             return;
         };
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 51115b11e86..4142dcff226 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1080,13 +1080,6 @@ pub(crate) struct EmptySpecialization {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_const_specialize)]
-pub(crate) struct ConstSpecialize {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(hir_analysis_static_specialize)]
 pub(crate) struct StaticSpecialize {
     #[primary_span]
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index 9d60759ae48..0404e38a293 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -703,7 +703,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 ///
 /// It might actually be possible that we can already support early-bound generic params
 /// in such types if we just lifted some more checks in other places, too, for example
-/// inside [`ty::Const::from_anon_const`]. However, even if that were the case, we should
+/// inside `HirTyLowerer::lower_anon_const`. However, even if that were the case, we should
 /// probably gate this behind another feature flag.
 ///
 /// [^1]: <https://github.com/rust-lang/project-const-generics/issues/28>.
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 7b8e95f3434..cb4209116ac 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -2089,7 +2089,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 qpath.span(),
                 format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
             ),
-            hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id),
+            hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon.def_id),
             hir::ConstArgKind::Infer(span) => self.ct_infer(None, span),
         }
     }
@@ -2177,6 +2177,92 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
     }
 
+    /// Literals and const generic parameters are eagerly converted to a constant, everything else
+    /// becomes `Unevaluated`.
+    #[instrument(skip(self), level = "debug")]
+    fn lower_anon_const(&self, def: LocalDefId) -> Const<'tcx> {
+        let tcx = self.tcx();
+
+        let body_id = match tcx.hir_node_by_def_id(def) {
+            hir::Node::AnonConst(ac) => ac.body,
+            node => span_bug!(
+                tcx.def_span(def.to_def_id()),
+                "from_anon_const can only process anonymous constants, not {node:?}"
+            ),
+        };
+
+        let expr = &tcx.hir().body(body_id).value;
+        debug!(?expr);
+
+        let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
+
+        match self.try_lower_anon_const_lit(ty, expr) {
+            Some(v) => v,
+            None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
+                def: def.to_def_id(),
+                args: ty::GenericArgs::identity_for_item(tcx, def.to_def_id()),
+            }),
+        }
+    }
+
+    #[instrument(skip(self), level = "debug")]
+    fn try_lower_anon_const_lit(
+        &self,
+        ty: Ty<'tcx>,
+        expr: &'tcx hir::Expr<'tcx>,
+    ) -> Option<Const<'tcx>> {
+        let tcx = self.tcx();
+
+        // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
+        // currently have to be wrapped in curly brackets, so it's necessary to special-case.
+        let expr = match &expr.kind {
+            hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
+                block.expr.as_ref().unwrap()
+            }
+            _ => expr,
+        };
+
+        if let hir::ExprKind::Path(hir::QPath::Resolved(
+            _,
+            &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
+        )) = expr.kind
+        {
+            span_bug!(
+                expr.span,
+                "try_lower_anon_const_lit: received const param which shouldn't be possible"
+            );
+        };
+
+        let lit_input = match expr.kind {
+            hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
+            hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
+                hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }),
+                _ => None,
+            },
+            _ => None,
+        };
+
+        if let Some(lit_input) = lit_input {
+            // If an error occurred, ignore that it's a literal and leave reporting the error up to
+            // mir.
+            match tcx.at(expr.span).lit_to_const(lit_input) {
+                Ok(c) => return Some(c),
+                Err(_) if lit_input.ty.has_aliases() => {
+                    // allow the `ty` to be an alias type, though we cannot handle it here
+                    return None;
+                }
+                Err(e) => {
+                    tcx.dcx().span_delayed_bug(
+                        expr.span,
+                        format!("try_lower_anon_const_lit: couldn't lit_to_const {e:?}"),
+                    );
+                }
+            }
+        }
+
+        None
+    }
+
     fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
         let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
         match idx {
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index 246643d8074..ee55e1bc21a 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -66,7 +66,6 @@
 //! on traits with methods can.
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
@@ -134,7 +133,6 @@ fn check_always_applicable(
         unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args)
     };
 
-    res = res.and(check_constness(tcx, impl1_def_id, impl2_node, span));
     res = res.and(check_static_lifetimes(tcx, &parent_args, span));
     res = res.and(check_duplicate_params(tcx, impl1_args, parent_args, span));
     res = res.and(check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span));
@@ -157,30 +155,6 @@ fn check_has_items(
     Ok(())
 }
 
-/// Check that the specializing impl `impl1` is at least as const as the base
-/// impl `impl2`
-fn check_constness(
-    tcx: TyCtxt<'_>,
-    impl1_def_id: LocalDefId,
-    impl2_node: Node,
-    span: Span,
-) -> Result<(), ErrorGuaranteed> {
-    if impl2_node.is_from_trait() {
-        // This isn't a specialization
-        return Ok(());
-    }
-
-    let impl1_constness = tcx.constness(impl1_def_id.to_def_id());
-    let impl2_constness = tcx.constness(impl2_node.def_id());
-
-    if let hir::Constness::Const = impl2_constness {
-        if let hir::Constness::NotConst = impl1_constness {
-            return Err(tcx.dcx().emit_err(errors::ConstSpecialize { span }));
-        }
-    }
-    Ok(())
-}
-
 /// Given a specializing impl `impl1`, and the base impl `impl2`, returns two
 /// generic parameters `(S1, S2)` that equate their trait references.
 /// The returned types are expressed in terms of the generics of `impl1`.
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 11864b61a94..0f3dcebc092 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -10,7 +10,7 @@ use std::cell::Cell;
 use std::vec;
 
 use rustc_abi::ExternAbi;
-use rustc_ast::util::parser::{self, AssocOp, Fixity};
+use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity};
 use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
 use rustc_ast_pretty::pp::{self, Breaks};
 use rustc_ast_pretty::pprust::{Comments, PrintState};
@@ -1125,12 +1125,12 @@ impl<'a> State<'a> {
     }
 
     fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
-        let prec = match func.kind {
-            hir::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
-            _ => parser::PREC_UNAMBIGUOUS,
+        let needs_paren = match func.kind {
+            hir::ExprKind::Field(..) => true,
+            _ => func.precedence() < ExprPrecedence::Unambiguous,
         };
 
-        self.print_expr_cond_paren(func, func.precedence() < prec);
+        self.print_expr_cond_paren(func, needs_paren);
         self.print_call_post(args)
     }
 
@@ -1141,7 +1141,7 @@ impl<'a> State<'a> {
         args: &[hir::Expr<'_>],
     ) {
         let base_args = args;
-        self.print_expr_cond_paren(receiver, receiver.precedence() < parser::PREC_UNAMBIGUOUS);
+        self.print_expr_cond_paren(receiver, receiver.precedence() < ExprPrecedence::Unambiguous);
         self.word(".");
         self.print_ident(segment.ident);
 
@@ -1155,37 +1155,38 @@ impl<'a> State<'a> {
 
     fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) {
         let assoc_op = AssocOp::from_ast_binop(op.node);
-        let prec = assoc_op.precedence() as i8;
-        let fixity = assoc_op.fixity();
-
-        let (left_prec, right_prec) = match fixity {
-            Fixity::Left => (prec, prec + 1),
-            Fixity::Right => (prec + 1, prec),
-            Fixity::None => (prec + 1, prec + 1),
+        let binop_prec = assoc_op.precedence();
+        let left_prec = lhs.precedence();
+        let right_prec = rhs.precedence();
+
+        let (mut left_needs_paren, right_needs_paren) = match assoc_op.fixity() {
+            Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
+            Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
+            Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),
         };
 
-        let left_prec = match (&lhs.kind, op.node) {
+        match (&lhs.kind, op.node) {
             // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
             // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
             // of `(x as i32) < ...`. We need to convince it _not_ to do that.
             (&hir::ExprKind::Cast { .. }, hir::BinOpKind::Lt | hir::BinOpKind::Shl) => {
-                parser::PREC_FORCE_PAREN
+                left_needs_paren = true;
             }
-            (&hir::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(prec) => {
-                parser::PREC_FORCE_PAREN
+            (&hir::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(binop_prec) => {
+                left_needs_paren = true;
             }
-            _ => left_prec,
-        };
+            _ => {}
+        }
 
-        self.print_expr_cond_paren(lhs, lhs.precedence() < left_prec);
+        self.print_expr_cond_paren(lhs, left_needs_paren);
         self.space();
         self.word_space(op.node.as_str());
-        self.print_expr_cond_paren(rhs, rhs.precedence() < right_prec)
+        self.print_expr_cond_paren(rhs, right_needs_paren);
     }
 
     fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) {
         self.word(op.as_str());
-        self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_PREFIX)
+        self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix);
     }
 
     fn print_expr_addr_of(
@@ -1202,7 +1203,7 @@ impl<'a> State<'a> {
                 self.print_mutability(mutability, true);
             }
         }
-        self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_PREFIX)
+        self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix);
     }
 
     fn print_literal(&mut self, lit: &hir::Lit) {
@@ -1340,8 +1341,7 @@ impl<'a> State<'a> {
                 self.print_literal(lit);
             }
             hir::ExprKind::Cast(expr, ty) => {
-                let prec = AssocOp::As.precedence() as i8;
-                self.print_expr_cond_paren(expr, expr.precedence() < prec);
+                self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Cast);
                 self.space();
                 self.word_space("as");
                 self.print_type(ty);
@@ -1442,27 +1442,25 @@ impl<'a> State<'a> {
                 self.print_block(blk);
             }
             hir::ExprKind::Assign(lhs, rhs, _) => {
-                let prec = AssocOp::Assign.precedence() as i8;
-                self.print_expr_cond_paren(lhs, lhs.precedence() <= prec);
+                self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
                 self.space();
                 self.word_space("=");
-                self.print_expr_cond_paren(rhs, rhs.precedence() < prec);
+                self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign);
             }
             hir::ExprKind::AssignOp(op, lhs, rhs) => {
-                let prec = AssocOp::Assign.precedence() as i8;
-                self.print_expr_cond_paren(lhs, lhs.precedence() <= prec);
+                self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
                 self.space();
                 self.word(op.node.as_str());
                 self.word_space("=");
-                self.print_expr_cond_paren(rhs, rhs.precedence() < prec);
+                self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign);
             }
             hir::ExprKind::Field(expr, ident) => {
-                self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_UNAMBIGUOUS);
+                self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous);
                 self.word(".");
                 self.print_ident(ident);
             }
             hir::ExprKind::Index(expr, index, _) => {
-                self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_UNAMBIGUOUS);
+                self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous);
                 self.word("[");
                 self.print_expr(index);
                 self.word("]");
@@ -1476,7 +1474,7 @@ impl<'a> State<'a> {
                 }
                 if let Some(expr) = opt_expr {
                     self.space();
-                    self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP);
+                    self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
                 }
             }
             hir::ExprKind::Continue(destination) => {
@@ -1490,13 +1488,13 @@ impl<'a> State<'a> {
                 self.word("return");
                 if let Some(expr) = result {
                     self.word(" ");
-                    self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP);
+                    self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
                 }
             }
             hir::ExprKind::Become(result) => {
                 self.word("become");
                 self.word(" ");
-                self.print_expr_cond_paren(result, result.precedence() < parser::PREC_JUMP);
+                self.print_expr_cond_paren(result, result.precedence() < ExprPrecedence::Jump);
             }
             hir::ExprKind::InlineAsm(asm) => {
                 self.word("asm!");
@@ -1521,7 +1519,7 @@ impl<'a> State<'a> {
             }
             hir::ExprKind::Yield(expr, _) => {
                 self.word_space("yield");
-                self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP);
+                self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
             }
             hir::ExprKind::Err(_) => {
                 self.popen();
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index b0afbab8e01..b430f48965a 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -1,6 +1,6 @@
 use std::iter;
 
-use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
 use rustc_hir::def::{self, CtorKind, Namespace, Res};
 use rustc_hir::def_id::DefId;
@@ -606,7 +606,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             };
 
             if let Ok(rest_snippet) = rest_snippet {
-                let sugg = if callee_expr.precedence() >= PREC_UNAMBIGUOUS {
+                let sugg = if callee_expr.precedence() >= ExprPrecedence::Unambiguous {
                     vec![
                         (up_to_rcvr_span, "".to_string()),
                         (rest_span, format!(".{}({rest_snippet}", segment.ident)),
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 0c3f21d540d..80b91c21598 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -28,6 +28,7 @@
 //! expression, `e as U2` is not necessarily so (in fact it will only be valid if
 //! `U1` coerces to `U2`).
 
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::codes::*;
 use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
@@ -1108,7 +1109,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
     fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) {
         let expr_prec = self.expr.precedence();
-        let needs_parens = expr_prec < rustc_ast::util::parser::PREC_UNAMBIGUOUS;
+        let needs_parens = expr_prec < ExprPrecedence::Unambiguous;
 
         let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize));
         let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 2a00530c434..774d00edea0 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -228,7 +228,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
     }
 
     fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
-        ty.is_copy_modulo_regions(self.0.tcx, self.0.typing_env())
+        self.0.type_is_copy_modulo_regions(ty)
     }
 
     fn body_owner_def_id(&self) -> LocalDefId {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 3940d138deb..aacdcf027b6 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -307,7 +307,11 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
             ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _)
                 if !ty.has_escaping_bound_vars() =>
             {
-                self.normalize(span, ty).ty_adt_def()
+                if self.next_trait_solver() {
+                    self.try_structurally_resolve_type(span, ty).ty_adt_def()
+                } else {
+                    self.normalize(span, ty).ty_adt_def()
+                }
             }
             _ => None,
         }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index b493a61b9f4..61260dbd16c 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -2,7 +2,7 @@ use core::cmp::min;
 use core::iter;
 
 use hir::def_id::LocalDefId;
-use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::{Applicability, Diag, MultiSpan};
 use rustc_hir as hir;
@@ -398,7 +398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // so we remove the user's `clone` call.
                     {
                         vec![(receiver_method.ident.span, conversion_method.name.to_string())]
-                    } else if expr.precedence() < PREC_UNAMBIGUOUS {
+                    } else if expr.precedence() < ExprPrecedence::Unambiguous {
                         vec![
                             (expr.span.shrink_to_lo(), "(".to_string()),
                             (expr.span.shrink_to_hi(), format!(").{}()", conversion_method.name)),
@@ -1376,7 +1376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             let span = expr.span.find_oldest_ancestor_in_same_ctxt();
 
-            let mut sugg = if expr.precedence() >= PREC_UNAMBIGUOUS {
+            let mut sugg = if expr.precedence() >= ExprPrecedence::Unambiguous {
                 vec![(span.shrink_to_hi(), ".into()".to_owned())]
             } else {
                 vec![
@@ -3000,7 +3000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             "change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`",
         );
 
-        let close_paren = if expr.precedence() < PREC_UNAMBIGUOUS {
+        let close_paren = if expr.precedence() < ExprPrecedence::Unambiguous {
             sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
             ")"
         } else {
@@ -3025,7 +3025,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let len = src.trim_end_matches(&checked_ty.to_string()).len();
                 expr.span.with_lo(expr.span.lo() + BytePos(len as u32))
             },
-            if expr.precedence() < PREC_UNAMBIGUOUS {
+            if expr.precedence() < ExprPrecedence::Unambiguous {
                 // Readd `)`
                 format!("{expected_ty})")
             } else {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index cff2aa68993..6b1a288510a 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -664,7 +664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| {
             tcx.is_diagnostic_item(sym::write_macro, def_id)
                 || tcx.is_diagnostic_item(sym::writeln_macro, def_id)
-        }) && item_name.name == Symbol::intern("write_fmt");
+        }) && item_name.name == sym::write_fmt;
         let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source {
             self.suggest_missing_writer(rcvr_ty, rcvr_expr)
         } else {
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs
index ba1516655b0..51282b900ed 100644
--- a/compiler/rustc_infer/src/traits/engine.rs
+++ b/compiler/rustc_infer/src/traits/engine.rs
@@ -84,6 +84,8 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
         self.collect_remaining_errors(infcx)
     }
 
+    fn has_pending_obligations(&self) -> bool;
+
     fn pending_obligations(&self) -> PredicateObligations<'tcx>;
 
     /// Among all pending obligations, collect those are stalled on a inference variable which has
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 2905fe688b5..d42915f4110 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -54,10 +54,6 @@ pub(crate) fn parse<'a>(sess: &'a Session) -> Result<ast::Crate> {
         })
         .map_err(|parse_error| parse_error.emit())?;
 
-    if let Some(ref s) = sess.opts.unstable_opts.show_span {
-        rustc_ast_passes::show_span::run(sess.dcx(), s, &krate);
-    }
-
     if sess.opts.unstable_opts.input_stats {
         input_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1");
     }
@@ -830,7 +826,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
                     tcx.ensure().check_mod_attrs(module);
                     tcx.ensure().check_mod_naked_functions(module);
                     tcx.ensure().check_mod_unstable_api_usage(module);
-                    tcx.ensure().check_mod_const_bodies(module);
                 });
             },
             {
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index c1b2d856252..3c4d9c2e928 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -771,6 +771,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(crate_attr, vec!["abc".to_string()]);
     tracked!(cross_crate_inline_threshold, InliningThreshold::Always);
     tracked!(debug_info_for_profiling, true);
+    tracked!(debug_info_type_line_numbers, true);
     tracked!(default_visibility, Some(rustc_target::spec::SymbolVisibility::Hidden));
     tracked!(dep_info_omit_d_target, true);
     tracked!(direct_access_external_data, Some(true));
@@ -843,7 +844,6 @@ fn test_unstable_options_tracking_hash() {
     tracked!(sanitizer_recover, SanitizerSet::ADDRESS);
     tracked!(saturating_float_casts, Some(true));
     tracked!(share_generics, Some(true));
-    tracked!(show_span, Some(String::from("abc")));
     tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc")));
     tracked!(small_data_threshold, Some(16));
     tracked!(split_lto_unit, Some(true));
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 4aeaf616816..49e6b763590 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -775,6 +775,9 @@ lint_suspicious_double_ref_clone =
 lint_suspicious_double_ref_deref =
     using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type
 
+lint_symbol_intern_string_literal = using `Symbol::intern` on a string literal
+    .help = consider adding the symbol to `compiler/rustc_span/src/symbol.rs`
+
 lint_trailing_semi_macro = trailing semicolon in macro used in expression position
     .note1 = macro invocations at the end of a block are treated as expressions
     .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}`
@@ -882,6 +885,12 @@ lint_unnameable_test_items = cannot test inner items
 lint_unnecessary_qualification = unnecessary qualification
     .suggestion = remove the unnecessary path segments
 
+lint_unpredictable_fn_pointer_comparisons = function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+    .note_duplicated_fn = the address of the same function can vary between different codegen units
+    .note_deduplicated_fn = furthermore, different functions could have the same address after being merged together
+    .note_visit_fn_addr_eq = for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+    .fn_addr_eq_suggestion = refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
+
 lint_unqualified_local_imports = `use` of a local item without leading `self::`, `super::`, or `crate::`
 
 lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index e130cfc1d73..ec085198922 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -586,7 +586,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
                 return;
             }
         }
-        if ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) {
+        if cx.type_is_copy_modulo_regions(ty) {
             return;
         }
         if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.typing_env()) {
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 7248b192763..44c7888a530 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -710,6 +710,10 @@ impl<'tcx> LateContext<'tcx> {
         TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env }
     }
 
+    pub fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
+        self.tcx.type_is_copy_modulo_regions(self.typing_env(), ty)
+    }
+
     /// Gets the type-checking results for the current body,
     /// or `None` if outside a body.
     pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> {
diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs
index 8fe86738658..ce23892508b 100644
--- a/compiler/rustc_lint/src/drop_forget_useless.rs
+++ b/compiler/rustc_lint/src/drop_forget_useless.rs
@@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
             && let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id)
         {
             let arg_ty = cx.typeck_results().expr_ty(arg);
-            let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env());
+            let is_copy = cx.type_is_copy_modulo_regions(arg_ty);
             let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
             let let_underscore_ignore_sugg = || {
                 if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0)
diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs
index 0e874669043..2db229ed133 100644
--- a/compiler/rustc_lint/src/if_let_rescope.rs
+++ b/compiler/rustc_lint/src/if_let_rescope.rs
@@ -103,8 +103,11 @@ fn expr_parent_is_else(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
 }
 
 fn expr_parent_is_stmt(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
-    let Some((_, hir::Node::Stmt(stmt))) = tcx.hir().parent_iter(hir_id).next() else {
-        return false;
+    let mut parents = tcx.hir().parent_iter(hir_id);
+    let stmt = match parents.next() {
+        Some((_, hir::Node::Stmt(stmt))) => stmt,
+        Some((_, hir::Node::Block(_) | hir::Node::Arm(_))) => return true,
+        _ => return false,
     };
     let (hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr)) = stmt.kind else { return false };
     expr.hir_id == hir_id
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 38c38b59bc5..482650e04e8 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -17,8 +17,9 @@ use tracing::debug;
 
 use crate::lints::{
     BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
-    NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, TyQualified,
-    TykindDiag, TykindKind, TypeIrInherentUsage, UntranslatableDiag,
+    NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
+    SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage,
+    UntranslatableDiag,
 };
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 
@@ -242,17 +243,10 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> {
         }
         // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait.
         Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
-            if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_identity().kind() {
-                if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(adt.did())
-                {
-                    // NOTE: This path is currently unreachable as `Ty<'tcx>` is
-                    // defined as a type alias meaning that `impl<'tcx> Ty<'tcx>`
-                    // is not actually allowed.
-                    //
-                    // I(@lcnr) still kept this branch in so we don't miss this
-                    // if we ever change it in the future.
-                    return Some(format!("{}<{}>", name, args[0]));
-                }
+            if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_identity().kind()
+                && let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(adt.did())
+            {
+                return Some(format!("{}<{}>", name, args[0]));
             }
         }
         _ => (),
@@ -657,3 +651,33 @@ fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         _ => false,
     }
 }
+
+declare_tool_lint! {
+    /// The `symbol_intern_string_literal` detects `Symbol::intern` being called on a string literal
+    pub rustc::SYMBOL_INTERN_STRING_LITERAL,
+    // rustc_driver crates out of the compiler can't/shouldn't add preinterned symbols;
+    // bootstrap will deny this manually
+    Allow,
+    "Forbid uses of string literals in `Symbol::intern`, suggesting preinterning instead",
+    report_in_external_macro: true
+}
+
+declare_lint_pass!(SymbolInternStringLiteral => [SYMBOL_INTERN_STRING_LITERAL]);
+
+impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
+        if let ExprKind::Call(path, [arg]) = expr.kind
+            && let ExprKind::Path(ref qpath) = path.kind
+            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+            && cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id)
+            && let ExprKind::Lit(kind) = arg.kind
+            && let rustc_ast::LitKind::Str(_, _) = kind.node
+        {
+            cx.emit_span_lint(
+                SYMBOL_INTERN_STRING_LITERAL,
+                kind.span,
+                SymbolInternStringLiteralDiag,
+            );
+        }
+    }
+}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 4cf5c7b4ff9..a99c94592b3 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -614,6 +614,8 @@ fn register_internals(store: &mut LintStore) {
     store.register_late_mod_pass(|_| Box::new(PassByValue));
     store.register_lints(&SpanUseEqCtxt::lint_vec());
     store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt));
+    store.register_lints(&SymbolInternStringLiteral::lint_vec());
+    store.register_late_mod_pass(|_| Box::new(SymbolInternStringLiteral));
     // FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and
     // `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and
     // these lints will trigger all of the time - change this once migration to diagnostic structs
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 3a854796f67..20822f23bf1 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -908,6 +908,11 @@ pub(crate) struct QueryUntracked {
 pub(crate) struct SpanUseEqCtxtDiag;
 
 #[derive(LintDiagnostic)]
+#[diag(lint_symbol_intern_string_literal)]
+#[help]
+pub(crate) struct SymbolInternStringLiteralDiag;
+
+#[derive(LintDiagnostic)]
 #[diag(lint_tykind_kind)]
 pub(crate) struct TykindKind {
     #[suggestion(code = "ty", applicability = "maybe-incorrect")]
@@ -1810,6 +1815,42 @@ pub(crate) enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
     },
 }
 
+#[derive(LintDiagnostic)]
+pub(crate) enum UnpredictableFunctionPointerComparisons<'a> {
+    #[diag(lint_unpredictable_fn_pointer_comparisons)]
+    #[note(lint_note_duplicated_fn)]
+    #[note(lint_note_deduplicated_fn)]
+    #[note(lint_note_visit_fn_addr_eq)]
+    Suggestion {
+        #[subdiagnostic]
+        sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a>,
+    },
+    #[diag(lint_unpredictable_fn_pointer_comparisons)]
+    #[note(lint_note_duplicated_fn)]
+    #[note(lint_note_deduplicated_fn)]
+    #[note(lint_note_visit_fn_addr_eq)]
+    Warn,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    lint_fn_addr_eq_suggestion,
+    style = "verbose",
+    applicability = "maybe-incorrect"
+)]
+pub(crate) struct UnpredictableFunctionPointerComparisonsSuggestion<'a> {
+    pub ne: &'a str,
+    pub cast_right: String,
+    pub deref_left: &'a str,
+    pub deref_right: &'a str,
+    #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")]
+    pub left: Span,
+    #[suggestion_part(code = ", {deref_right}")]
+    pub middle: Span,
+    #[suggestion_part(code = "{cast_right})")]
+    pub right: Span,
+}
+
 pub(crate) struct ImproperCTypes<'a> {
     pub ty: Ty<'a>,
     pub desc: &'a str,
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index b1d7d4ab689..33650be056d 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -23,7 +23,9 @@ use crate::lints::{
     AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion,
     AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
     AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons,
-    InvalidNanComparisonsSuggestion, UnusedComparisons, VariantSizeDifferencesDiag,
+    InvalidNanComparisonsSuggestion, UnpredictableFunctionPointerComparisons,
+    UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons,
+    VariantSizeDifferencesDiag,
 };
 use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent};
 
@@ -166,6 +168,35 @@ declare_lint! {
     "detects ambiguous wide pointer comparisons"
 }
 
+declare_lint! {
+    /// The `unpredictable_function_pointer_comparisons` lint checks comparison
+    /// of function pointer as the operands.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// fn a() {}
+    /// fn b() {}
+    ///
+    /// let f: fn() = a;
+    /// let g: fn() = b;
+    ///
+    /// let _ = f == g;
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Function pointers comparisons do not produce meaningful result since
+    /// they are never guaranteed to be unique and could vary between different
+    /// code generation units. Furthermore, different functions could have the
+    /// same address after being merged together.
+    UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
+    Warn,
+    "detects unpredictable function pointer comparisons"
+}
+
 #[derive(Copy, Clone, Default)]
 pub(crate) struct TypeLimits {
     /// Id of the last visited negated expression
@@ -178,7 +209,8 @@ impl_lint_pass!(TypeLimits => [
     UNUSED_COMPARISONS,
     OVERFLOWING_LITERALS,
     INVALID_NAN_COMPARISONS,
-    AMBIGUOUS_WIDE_POINTER_COMPARISONS
+    AMBIGUOUS_WIDE_POINTER_COMPARISONS,
+    UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS
 ]);
 
 impl TypeLimits {
@@ -255,7 +287,7 @@ fn lint_nan<'tcx>(
     cx.emit_span_lint(INVALID_NAN_COMPARISONS, e.span, lint);
 }
 
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Copy, Clone)]
 enum ComparisonOp {
     BinOp(hir::BinOpKind),
     Other,
@@ -383,6 +415,100 @@ fn lint_wide_pointer<'tcx>(
     );
 }
 
+fn lint_fn_pointer<'tcx>(
+    cx: &LateContext<'tcx>,
+    e: &'tcx hir::Expr<'tcx>,
+    cmpop: ComparisonOp,
+    l: &'tcx hir::Expr<'tcx>,
+    r: &'tcx hir::Expr<'tcx>,
+) {
+    let peel_refs = |mut ty: Ty<'tcx>| -> (Ty<'tcx>, usize) {
+        let mut refs = 0;
+
+        while let ty::Ref(_, inner_ty, _) = ty.kind() {
+            ty = *inner_ty;
+            refs += 1;
+        }
+
+        (ty, refs)
+    };
+
+    // Left and right operands can have borrows, remove them
+    let l = l.peel_borrows();
+    let r = r.peel_borrows();
+
+    let Some(l_ty) = cx.typeck_results().expr_ty_opt(l) else { return };
+    let Some(r_ty) = cx.typeck_results().expr_ty_opt(r) else { return };
+
+    // Remove any references as `==` will deref through them (and count the
+    // number of references removed, for latter).
+    let (l_ty, l_ty_refs) = peel_refs(l_ty);
+    let (r_ty, r_ty_refs) = peel_refs(r_ty);
+
+    if !l_ty.is_fn() || !r_ty.is_fn() {
+        return;
+    }
+
+    // Let's try to suggest `ptr::fn_addr_eq` if/when possible.
+
+    let is_eq_ne = matches!(cmpop, ComparisonOp::BinOp(hir::BinOpKind::Eq | hir::BinOpKind::Ne));
+
+    if !is_eq_ne {
+        // Neither `==` nor `!=`, we can't suggest `ptr::fn_addr_eq`, just show the warning.
+        return cx.emit_span_lint(
+            UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
+            e.span,
+            UnpredictableFunctionPointerComparisons::Warn,
+        );
+    }
+
+    let (Some(l_span), Some(r_span)) =
+        (l.span.find_ancestor_inside(e.span), r.span.find_ancestor_inside(e.span))
+    else {
+        // No appropriate spans for the left and right operands, just show the warning.
+        return cx.emit_span_lint(
+            UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
+            e.span,
+            UnpredictableFunctionPointerComparisons::Warn,
+        );
+    };
+
+    let ne = if cmpop == ComparisonOp::BinOp(hir::BinOpKind::Ne) { "!" } else { "" };
+
+    // `ptr::fn_addr_eq` only works with raw pointer, deref any references.
+    let deref_left = &*"*".repeat(l_ty_refs);
+    let deref_right = &*"*".repeat(r_ty_refs);
+
+    let left = e.span.shrink_to_lo().until(l_span.shrink_to_lo());
+    let middle = l_span.shrink_to_hi().until(r_span.shrink_to_lo());
+    let right = r_span.shrink_to_hi().until(e.span.shrink_to_hi());
+
+    // We only check for a right cast as `FnDef` == `FnPtr` is not possible,
+    // only `FnPtr == FnDef` is possible.
+    let cast_right = if !r_ty.is_fn_ptr() {
+        let fn_sig = r_ty.fn_sig(cx.tcx);
+        format!(" as {fn_sig}")
+    } else {
+        String::new()
+    };
+
+    cx.emit_span_lint(
+        UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
+        e.span,
+        UnpredictableFunctionPointerComparisons::Suggestion {
+            sugg: UnpredictableFunctionPointerComparisonsSuggestion {
+                ne,
+                deref_left,
+                deref_right,
+                left,
+                middle,
+                right,
+                cast_right,
+            },
+        },
+    );
+}
+
 impl<'tcx> LateLintPass<'tcx> for TypeLimits {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
         match e.kind {
@@ -399,7 +525,9 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
                         cx.emit_span_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons);
                     } else {
                         lint_nan(cx, e, binop, l, r);
-                        lint_wide_pointer(cx, e, ComparisonOp::BinOp(binop.node), l, r);
+                        let cmpop = ComparisonOp::BinOp(binop.node);
+                        lint_wide_pointer(cx, e, cmpop, l, r);
+                        lint_fn_pointer(cx, e, cmpop, l, r);
                     }
                 }
             }
@@ -411,6 +539,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
                     && let Some(cmpop) = diag_item_cmpop(diag_item) =>
             {
                 lint_wide_pointer(cx, e, cmpop, l, r);
+                lint_fn_pointer(cx, e, cmpop, l, r);
             }
             hir::ExprKind::MethodCall(_, l, [r], _)
                 if let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
@@ -418,6 +547,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
                     && let Some(cmpop) = diag_item_cmpop(diag_item) =>
             {
                 lint_wide_pointer(cx, e, cmpop, l, r);
+                lint_fn_pointer(cx, e, cmpop, l, r);
             }
             _ => {}
         };
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index e1a0e1ec579..b775cd37409 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1563,7 +1563,7 @@ impl UnusedImportBraces {
                     }
                     rename.unwrap_or(orig_ident).name
                 }
-                ast::UseTreeKind::Glob => Symbol::intern("*"),
+                ast::UseTreeKind::Glob => sym::asterisk,
                 ast::UseTreeKind::Nested { .. } => return,
             };
 
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 3b406c7e161..d2b7ae620e2 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -179,7 +179,7 @@ declare_lint! {
     Warn,
     "applying forbid to lint-groups",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
         reference: "issue #81670 <https://github.com/rust-lang/rust/issues/81670>",
     };
 }
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index a18c6baec00..29dba2bca61 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -861,8 +861,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
         // First up we check for global allocators. Look at the crate graph here
         // and see what's a global allocator, including if we ourselves are a
         // global allocator.
-        let mut global_allocator =
-            self.cstore.has_global_allocator.then(|| Symbol::intern("this crate"));
+        #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
+        let this_crate = Symbol::intern("this crate");
+
+        let mut global_allocator = self.cstore.has_global_allocator.then_some(this_crate);
         for (_, data) in self.cstore.iter_crate_data() {
             if data.has_global_allocator() {
                 match global_allocator {
@@ -876,8 +878,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
                 }
             }
         }
-        let mut alloc_error_handler =
-            self.cstore.has_alloc_error_handler.then(|| Symbol::intern("this crate"));
+        let mut alloc_error_handler = self.cstore.has_alloc_error_handler.then_some(this_crate);
         for (_, data) in self.cstore.iter_crate_data() {
             if data.has_alloc_error_handler() {
                 match alloc_error_handler {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 56beff5aa64..f3f5af49412 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -872,6 +872,7 @@ impl MetadataBlob {
 
                         let def_kind = root.tables.def_kind.get(blob, item).unwrap();
                         let def_key = root.tables.def_keys.get(blob, item).unwrap().decode(blob);
+                        #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
                         let def_name = if item == CRATE_DEF_INDEX {
                             rustc_span::symbol::kw::Crate
                         } else {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 068a5d31a8e..a34ea18f716 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1389,10 +1389,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             // `ConstArgKind::Path`. We never actually access this `DefId`
             // anywhere so we don't need to encode it for other crates.
             if def_kind == DefKind::AnonConst
-                && matches!(
-                    tcx.hir_node_by_def_id(local_id),
-                    hir::Node::ConstArg(hir::ConstArg { kind: hir::ConstArgKind::Path(..), .. })
-                )
+                && match tcx.hir_node_by_def_id(local_id) {
+                    hir::Node::ConstArg(hir::ConstArg { kind, .. }) => match kind {
+                        // Skip encoding defs for these as they should not have had a `DefId` created
+                        hir::ConstArgKind::Path(..) | hir::ConstArgKind::Infer(..) => true,
+                        hir::ConstArgKind::Anon(..) => false,
+                    },
+                    _ => false,
+                }
             {
                 continue;
             }
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 9438350ca09..28f406fbc96 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -1,6 +1,5 @@
 use rustc_hir::def::CtorOf;
 use rustc_index::Idx;
-use tracing::trace;
 
 use crate::rmeta::*;
 
@@ -530,8 +529,6 @@ where
 {
     /// Given the metadata, extract out the value at a particular index (if any).
     pub(super) fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>(&self, metadata: M, i: I) -> T::Value<'tcx> {
-        trace!("LazyTable::lookup: index={:?} len={:?}", i, self.len);
-
         // Access past the end of the table returns a Default
         if i.index() >= self.len {
             return Default::default();
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 08afa33c6b4..ad5d678178d 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -46,7 +46,7 @@ impl ErrorHandled {
     pub fn emit_note(&self, tcx: TyCtxt<'_>) {
         match self {
             &ErrorHandled::Reported(err, span) => {
-                if !err.is_tainted_by_errors && !span.is_dummy() {
+                if !err.allowed_in_infallible && !span.is_dummy() {
                     tcx.dcx().emit_note(error::ErroneousConstant { span });
                 }
             }
@@ -58,34 +58,26 @@ impl ErrorHandled {
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
 pub struct ReportedErrorInfo {
     error: ErrorGuaranteed,
-    is_tainted_by_errors: bool,
-    /// Whether this is the kind of error that can sometimes occur, and sometimes not.
-    /// Used for resource exhaustion errors.
-    can_be_spurious: bool,
+    /// Whether this error is allowed to show up even in otherwise "infallible" promoteds.
+    /// This is for things like overflows during size computation or resource exhaustion.
+    allowed_in_infallible: bool,
 }
 
 impl ReportedErrorInfo {
     #[inline]
-    pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo {
-        ReportedErrorInfo { is_tainted_by_errors: true, can_be_spurious: false, error }
-    }
-    #[inline]
-    pub fn spurious(error: ErrorGuaranteed) -> ReportedErrorInfo {
-        ReportedErrorInfo { can_be_spurious: true, is_tainted_by_errors: false, error }
+    pub fn allowed_in_infallible(error: ErrorGuaranteed) -> ReportedErrorInfo {
+        ReportedErrorInfo { allowed_in_infallible: true, error }
     }
 
-    pub fn is_tainted_by_errors(&self) -> bool {
-        self.is_tainted_by_errors
-    }
-    pub fn can_be_spurious(&self) -> bool {
-        self.can_be_spurious
+    pub fn is_allowed_in_infallible(&self) -> bool {
+        self.allowed_in_infallible
     }
 }
 
 impl From<ErrorGuaranteed> for ReportedErrorInfo {
     #[inline]
     fn from(error: ErrorGuaranteed) -> ReportedErrorInfo {
-        ReportedErrorInfo { is_tainted_by_errors: false, can_be_spurious: false, error }
+        ReportedErrorInfo { allowed_in_infallible: false, error }
     }
 }
 
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index a17aa9ecc04..df110fdc20a 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -958,11 +958,6 @@ rustc_queries! {
         desc { |tcx| "checking for unstable API usage in {}", describe_as_module(key, tcx) }
     }
 
-    /// Checks the const bodies in the module for illegal operations (e.g. `if` or `loop`).
-    query check_mod_const_bodies(key: LocalModDefId) {
-        desc { |tcx| "checking consts in {}", describe_as_module(key, tcx) }
-    }
-
     /// Checks the loops in the module.
     query check_mod_loops(key: LocalModDefId) {
         desc { |tcx| "checking loops in {}", describe_as_module(key, tcx) }
@@ -1086,6 +1081,8 @@ rustc_queries! {
     }
 
     /// Computes the tag (if any) for a given type and variant.
+    /// `None` means that the variant doesn't need a tag (because it is niched).
+    /// Will panic for uninhabited variants.
     query tag_for_variant(
         key: (Ty<'tcx>, abi::VariantIdx)
     ) -> Option<ty::ScalarInt> {
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index d27205e26ab..31055276422 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -2,15 +2,11 @@ use std::borrow::Cow;
 
 use rustc_data_structures::intern::Interned;
 use rustc_error_messages::MultiSpan;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::LocalDefId;
-use rustc_hir::{self as hir};
 use rustc_macros::HashStable;
 use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
-use tracing::{debug, instrument};
 
-use crate::mir::interpret::{LitToConstInput, Scalar};
-use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt};
+use crate::mir::interpret::Scalar;
+use crate::ty::{self, Ty, TyCtxt};
 
 mod int;
 mod kind;
@@ -181,82 +177,6 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
 }
 
 impl<'tcx> Const<'tcx> {
-    // FIXME: move this and try_from_lit to hir_ty_lowering like lower_const_arg/from_const_arg
-    /// Literals and const generic parameters are eagerly converted to a constant, everything else
-    /// becomes `Unevaluated`.
-    #[instrument(skip(tcx), level = "debug")]
-    pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
-        let body_id = match tcx.hir_node_by_def_id(def) {
-            hir::Node::AnonConst(ac) => ac.body,
-            node => span_bug!(
-                tcx.def_span(def.to_def_id()),
-                "from_anon_const can only process anonymous constants, not {node:?}"
-            ),
-        };
-
-        let expr = &tcx.hir().body(body_id).value;
-        debug!(?expr);
-
-        let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
-
-        match Self::try_from_lit(tcx, ty, expr) {
-            Some(v) => v,
-            None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
-                def: def.to_def_id(),
-                args: GenericArgs::identity_for_item(tcx, def.to_def_id()),
-            }),
-        }
-    }
-
-    #[instrument(skip(tcx), level = "debug")]
-    fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
-        // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
-        // currently have to be wrapped in curly brackets, so it's necessary to special-case.
-        let expr = match &expr.kind {
-            hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
-                block.expr.as_ref().unwrap()
-            }
-            _ => expr,
-        };
-
-        if let hir::ExprKind::Path(hir::QPath::Resolved(
-            _,
-            &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
-        )) = expr.kind
-        {
-            span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible");
-        };
-
-        let lit_input = match expr.kind {
-            hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
-            hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
-                hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }),
-                _ => None,
-            },
-            _ => None,
-        };
-
-        if let Some(lit_input) = lit_input {
-            // If an error occurred, ignore that it's a literal and leave reporting the error up to
-            // mir.
-            match tcx.at(expr.span).lit_to_const(lit_input) {
-                Ok(c) => return Some(c),
-                Err(_) if lit_input.ty.has_aliases() => {
-                    // allow the `ty` to be an alias type, though we cannot handle it here
-                    return None;
-                }
-                Err(e) => {
-                    tcx.dcx().span_delayed_bug(
-                        expr.span,
-                        format!("Const::try_from_lit: couldn't lit_to_const {e:?}"),
-                    );
-                }
-            }
-        }
-
-        None
-    }
-
     /// Creates a constant with the given integer value and interns it.
     #[inline]
     pub fn from_bits(
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 797ac9685b1..57054bd1a0b 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -172,6 +172,24 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
+    /// Checks whether `ty: Copy` holds while ignoring region constraints.
+    ///
+    /// This impacts whether values of `ty` are *moved* or *copied*
+    /// when referenced. This means that we may generate MIR which
+    /// does copies even when the type actually doesn't satisfy the
+    /// full requirements for the `Copy` trait (cc #29149) -- this
+    /// winds up being reported as an error during NLL borrow check.
+    ///
+    /// This function should not be used if there is an `InferCtxt` available.
+    /// Use `InferCtxt::type_is_copy_modulo_regions` instead.
+    pub fn type_is_copy_modulo_regions(
+        self,
+        typing_env: ty::TypingEnv<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> bool {
+        ty.is_trivially_pure_clone_copy() || self.is_copy_raw(typing_env.as_query_input(ty))
+    }
+
     /// Returns the deeply last field of nested structures, or the same type if
     /// not a structure at all. Corresponds to the only possible unsized field,
     /// and its type can be used to determine unsizing strategy.
@@ -1174,21 +1192,6 @@ impl<'tcx> Ty<'tcx> {
             .map(|(min, _)| ty::Const::from_bits(tcx, min, typing_env, self))
     }
 
-    /// Checks whether values of this type `T` are *moved* or *copied*
-    /// when referenced -- this amounts to a check for whether `T:
-    /// Copy`, but note that we **don't** consider lifetimes when
-    /// doing this check. This means that we may generate MIR which
-    /// does copies even when the type actually doesn't satisfy the
-    /// full requirements for the `Copy` trait (cc #29149) -- this
-    /// winds up being reported as an error during NLL borrow check.
-    pub fn is_copy_modulo_regions(
-        self,
-        tcx: TyCtxt<'tcx>,
-        typing_env: ty::TypingEnv<'tcx>,
-    ) -> bool {
-        self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(typing_env.as_query_input(self))
-    }
-
     /// Checks whether values of this type `T` have a size known at
     /// compile time (i.e., whether `T: Sized`). Lifetimes are ignored
     /// for the purposes of this check, so it can be an
diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs
index acfb78b3f6e..df5b73ac1bd 100644
--- a/compiler/rustc_middle/src/util/call_kind.rs
+++ b/compiler/rustc_middle/src/util/call_kind.rs
@@ -14,6 +14,8 @@ use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, Ty, TyCtxt, Typing
 pub enum CallDesugaringKind {
     /// for _ in x {} calls x.into_iter()
     ForLoopIntoIter,
+    /// for _ in x {} calls iter.next()
+    ForLoopNext,
     /// x? calls x.branch()
     QuestionBranch,
     /// x? calls type_of(x)::from_residual()
@@ -28,6 +30,7 @@ impl CallDesugaringKind {
     pub fn trait_def_id(self, tcx: TyCtxt<'_>) -> DefId {
         match self {
             Self::ForLoopIntoIter => tcx.get_diagnostic_item(sym::IntoIterator).unwrap(),
+            Self::ForLoopNext => tcx.require_lang_item(LangItem::Iterator, None),
             Self::QuestionBranch | Self::TryBlockFromOutput => {
                 tcx.require_lang_item(LangItem::Try, None)
             }
@@ -121,6 +124,10 @@ pub fn call_kind<'tcx>(
             && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop)
         {
             Some((CallDesugaringKind::ForLoopIntoIter, method_args.type_at(0)))
+        } else if tcx.is_lang_item(method_did, LangItem::IteratorNext)
+            && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop)
+        {
+            Some((CallDesugaringKind::ForLoopNext, method_args.type_at(0)))
         } else if fn_call_span.desugaring_kind() == Some(DesugaringKind::QuestionMark) {
             if tcx.is_lang_item(method_did, LangItem::TryTraitBranch) {
                 Some((CallDesugaringKind::QuestionBranch, method_args.type_at(0)))
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index f28cf84fa69..f647486f62a 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -84,12 +84,17 @@ mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
 
 mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable
 
-mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns
+mir_build_const_defined_here = constant defined here
 
-mir_build_const_pattern_depends_on_generic_parameter =
-    constant pattern depends on a generic parameter
+mir_build_const_param_in_pattern = constant parameters cannot be referenced in patterns
+    .label = can't be used in patterns
+mir_build_const_param_in_pattern_def = constant defined here
+
+mir_build_const_pattern_depends_on_generic_parameter = constant pattern cannot depend on generic parameters
+    .label = `const` depends on a generic parameter
 
 mir_build_could_not_eval_const_pattern = could not evaluate constant pattern
+    .label = could not evaluate constant
 
 mir_build_deref_raw_pointer_requires_unsafe =
     dereference of raw pointer is unsafe and requires unsafe block
@@ -147,7 +152,8 @@ mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
 
 mir_build_interpreted_as_const = introduce a variable instead
 
-mir_build_invalid_pattern = `{$non_sm_ty}` cannot be used in patterns
+mir_build_invalid_pattern = {$prefix} `{$non_sm_ty}` cannot be used in patterns
+    .label = {$prefix} can't be used in patterns
 
 mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count ->
         [one] pattern
@@ -244,10 +250,12 @@ mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsa
     .label = mutation of layout constrained field
 
 mir_build_nan_pattern = cannot use NaN in patterns
+    .label = evaluates to `NaN`, which is not allowed in patterns
     .note = NaNs compare inequal to everything, even themselves, so this pattern would never match
     .help = try using the `is_nan` method instead
 
 mir_build_non_const_path = runtime values cannot be referenced in patterns
+    .label = references a runtime value
 
 mir_build_non_empty_never_pattern =
     mismatched types
@@ -265,13 +273,15 @@ mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type
     .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
     .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
-mir_build_non_partial_eq_match =
-    to use a constant of type `{$non_peq_ty}` in a pattern, the type must implement `PartialEq`
+mir_build_non_partial_eq_match = constant of non-structural type `{$ty}` in a pattern
+    .label = constant of non-structural type
 
 mir_build_pattern_not_covered = refutable pattern in {$origin}
     .pattern_ty = the matched value is of type `{$pattern_ty}`
 
-mir_build_pointer_pattern = function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+mir_build_pointer_pattern = function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
+    .label = can't be used in patterns
+    .note = see https://github.com/rust-lang/rust/issues/70861 for details
 
 mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
 
@@ -283,6 +293,8 @@ mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly
     .missing_box = `#[rustc_box]` requires the `owned_box` lang item
 
 mir_build_static_in_pattern = statics cannot be referenced in patterns
+    .label = can't be used in patterns
+mir_build_static_in_pattern_def = `static` defined here
 
 mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
 
@@ -310,12 +322,12 @@ mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
         *[other] them
     } into the body
 
-mir_build_type_not_structural =
-     to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]`
-
+mir_build_type_not_structural = constant of non-structural type `{$ty}` in a pattern
+    .label = constant of non-structural type
+mir_build_type_not_structural_def = `{$ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
 mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-
-mir_build_type_not_structural_tip = the traits must be derived, manual `impl`s are not sufficient
+mir_build_type_not_structural_tip =
+    the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
 mir_build_unconditional_recursion = function cannot return without recursing
     .label = cannot return without recursing
@@ -334,6 +346,7 @@ mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
     .label = access to union field
 
 mir_build_union_pattern = cannot use unions in constant patterns
+    .label = can't use a `union` here
 
 mir_build_unreachable_making_this_unreachable = collectively making this unreachable
 
diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
index 0cab853196b..777ff9e68f0 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -176,7 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             let ty = expr.ty;
             if !ty.is_sized(tcx, this.typing_env()) {
                 // !sized means !copy, so this is an unsized move
-                assert!(!ty.is_copy_modulo_regions(tcx, this.typing_env()));
+                assert!(!tcx.type_is_copy_modulo_regions(this.typing_env(), ty));
 
                 // As described above, detect the case where we are passing a value of unsized
                 // type, and that value is coming from the deref of a box.
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 58487a48184..3632da943e1 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -631,20 +631,27 @@ pub(crate) struct NonExhaustiveMatchAllArmsGuarded;
 #[diag(mir_build_static_in_pattern, code = E0158)]
 pub(crate) struct StaticInPattern {
     #[primary_span]
+    #[label]
     pub(crate) span: Span,
+    #[label(mir_build_static_in_pattern_def)]
+    pub(crate) static_span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_const_param_in_pattern, code = E0158)]
 pub(crate) struct ConstParamInPattern {
     #[primary_span]
+    #[label]
     pub(crate) span: Span,
+    #[label(mir_build_const_param_in_pattern_def)]
+    pub(crate) const_span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_non_const_path, code = E0080)]
 pub(crate) struct NonConstPath {
     #[primary_span]
+    #[label]
     pub(crate) span: Span,
 }
 
@@ -695,6 +702,7 @@ pub(crate) struct WantedConstant {
 #[diag(mir_build_const_pattern_depends_on_generic_parameter, code = E0158)]
 pub(crate) struct ConstPatternDependsOnGenericParameter {
     #[primary_span]
+    #[label]
     pub(crate) span: Span,
 }
 
@@ -702,6 +710,7 @@ pub(crate) struct ConstPatternDependsOnGenericParameter {
 #[diag(mir_build_could_not_eval_const_pattern)]
 pub(crate) struct CouldNotEvalConstPattern {
     #[primary_span]
+    #[label]
     pub(crate) span: Span,
 }
 
@@ -867,33 +876,43 @@ pub(crate) enum Conflict {
 #[diag(mir_build_union_pattern)]
 pub(crate) struct UnionPattern {
     #[primary_span]
+    #[label]
     pub(crate) span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_type_not_structural)]
-#[note(mir_build_type_not_structural_tip)]
-#[note(mir_build_type_not_structural_more_info)]
 pub(crate) struct TypeNotStructural<'tcx> {
     #[primary_span]
+    #[label]
     pub(crate) span: Span,
-    pub(crate) non_sm_ty: Ty<'tcx>,
+    #[label(mir_build_type_not_structural_def)]
+    pub(crate) ty_def_span: Span,
+    pub(crate) ty: Ty<'tcx>,
+    #[note(mir_build_type_not_structural_tip)]
+    pub(crate) manual_partialeq_impl_span: Option<Span>,
+    #[note(mir_build_type_not_structural_more_info)]
+    pub(crate) manual_partialeq_impl_note: bool,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_non_partial_eq_match)]
+#[note(mir_build_type_not_structural_more_info)]
 pub(crate) struct TypeNotPartialEq<'tcx> {
     #[primary_span]
+    #[label]
     pub(crate) span: Span,
-    pub(crate) non_peq_ty: Ty<'tcx>,
+    pub(crate) ty: Ty<'tcx>,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_invalid_pattern)]
 pub(crate) struct InvalidPattern<'tcx> {
     #[primary_span]
+    #[label]
     pub(crate) span: Span,
     pub(crate) non_sm_ty: Ty<'tcx>,
+    pub(crate) prefix: String,
 }
 
 #[derive(Diagnostic)]
@@ -910,13 +929,16 @@ pub(crate) struct UnsizedPattern<'tcx> {
 #[help]
 pub(crate) struct NaNPattern {
     #[primary_span]
+    #[label]
     pub(crate) span: Span,
 }
 
 #[derive(Diagnostic)]
 #[diag(mir_build_pointer_pattern)]
+#[note]
 pub(crate) struct PointerPattern {
     #[primary_span]
+    #[label]
     pub(crate) span: Span,
 }
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index e55cd35e243..a13b00e1921 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -780,7 +780,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
         return;
     };
 
-    let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env);
+    let is_binding_by_move = |ty: Ty<'tcx>| !cx.tcx.type_is_copy_modulo_regions(cx.typing_env, ty);
 
     let sess = cx.tcx.sess;
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 5db08f01fdb..aed00aecefc 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -1,14 +1,17 @@
 use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_apfloat::Float;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::Diag;
 use rustc_hir as hir;
 use rustc_index::Idx;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::Obligation;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::thir::{FieldPat, Pat, PatKind};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, ValTree};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeVisitor, ValTree};
 use rustc_middle::{mir, span_bug};
-use rustc_span::Span;
+use rustc_span::def_id::DefId;
+use rustc_span::{Span, sym};
 use rustc_trait_selection::traits::ObligationCause;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use tracing::{debug, instrument, trace};
@@ -35,7 +38,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         id: hir::HirId,
         span: Span,
     ) -> Box<Pat<'tcx>> {
-        let mut convert = ConstToPat::new(self, id, span);
+        let mut convert = ConstToPat::new(self, id, span, c);
 
         match c.kind() {
             ty::ConstKind::Unevaluated(uv) => convert.unevaluated_to_pat(uv, ty),
@@ -49,21 +52,26 @@ struct ConstToPat<'tcx> {
     tcx: TyCtxt<'tcx>,
     typing_env: ty::TypingEnv<'tcx>,
     span: Span,
+    id: hir::HirId,
 
     treat_byte_string_as_slice: bool,
+
+    c: ty::Const<'tcx>,
 }
 
 impl<'tcx> ConstToPat<'tcx> {
-    fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span) -> Self {
+    fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self {
         trace!(?pat_ctxt.typeck_results.hir_owner);
         ConstToPat {
             tcx: pat_ctxt.tcx,
             typing_env: pat_ctxt.typing_env,
             span,
+            id,
             treat_byte_string_as_slice: pat_ctxt
                 .typeck_results
                 .treat_byte_string_as_slice
                 .contains(&id.local_id),
+            c,
         }
     }
 
@@ -71,13 +79,32 @@ impl<'tcx> ConstToPat<'tcx> {
         ty.is_structural_eq_shallow(self.tcx)
     }
 
+    /// We errored. Signal that in the pattern, so that follow up errors can be silenced.
+    fn mk_err(&self, mut err: Diag<'_>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
+        if let ty::ConstKind::Unevaluated(uv) = self.c.kind() {
+            let def_kind = self.tcx.def_kind(uv.def);
+            if let hir::def::DefKind::AssocConst = def_kind
+                && let Some(def_id) = uv.def.as_local()
+            {
+                // Include the container item in the output.
+                err.span_label(self.tcx.def_span(self.tcx.local_parent(def_id)), "");
+            }
+            if let hir::def::DefKind::Const | hir::def::DefKind::AssocConst = def_kind {
+                err.span_label(
+                    self.tcx.def_span(uv.def),
+                    crate::fluent_generated::mir_build_const_defined_here,
+                );
+            }
+        }
+        Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()) })
+    }
+
     fn unevaluated_to_pat(
         &mut self,
         uv: ty::UnevaluatedConst<'tcx>,
         ty: Ty<'tcx>,
     ) -> Box<Pat<'tcx>> {
         trace!(self.treat_byte_string_as_slice);
-        let pat_from_kind = |kind| Box::new(Pat { span: self.span, ty, kind });
 
         // It's not *technically* correct to be revealing opaque types here as borrowcheck has
         // not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even
@@ -96,32 +123,60 @@ impl<'tcx> ConstToPat<'tcx> {
             Ok(Ok(c)) => c,
             Err(ErrorHandled::Reported(_, _)) => {
                 // Let's tell the use where this failing const occurs.
-                let e = self.tcx.dcx().emit_err(CouldNotEvalConstPattern { span: self.span });
-                return pat_from_kind(PatKind::Error(e));
+                let mut err =
+                    self.tcx.dcx().create_err(CouldNotEvalConstPattern { span: self.span });
+                // We've emitted an error on the original const, it would be redundant to complain
+                // on its use as well.
+                if let ty::ConstKind::Unevaluated(uv) = self.c.kind()
+                    && let hir::def::DefKind::Const | hir::def::DefKind::AssocConst =
+                        self.tcx.def_kind(uv.def)
+                {
+                    err.downgrade_to_delayed_bug();
+                }
+                return self.mk_err(err, ty);
             }
             Err(ErrorHandled::TooGeneric(_)) => {
-                let e = self
+                let mut e = self
                     .tcx
                     .dcx()
-                    .emit_err(ConstPatternDependsOnGenericParameter { span: self.span });
-                return pat_from_kind(PatKind::Error(e));
+                    .create_err(ConstPatternDependsOnGenericParameter { span: self.span });
+                for arg in uv.args {
+                    if let ty::GenericArgKind::Type(ty) = arg.unpack()
+                        && let ty::Param(param_ty) = ty.kind()
+                    {
+                        let def_id = self.tcx.hir().enclosing_body_owner(self.id);
+                        let generics = self.tcx.generics_of(def_id);
+                        let param = generics.type_param(*param_ty, self.tcx);
+                        let span = self.tcx.def_span(param.def_id);
+                        e.span_label(span, "constant depends on this generic parameter");
+                        if let Some(ident) = self.tcx.def_ident_span(def_id)
+                            && self.tcx.sess.source_map().is_multiline(ident.between(span))
+                        {
+                            // Display the `fn` name as well in the diagnostic, as the generic isn't
+                            // in the same line and it could be confusing otherwise.
+                            e.span_label(ident, "");
+                        }
+                    }
+                }
+                return self.mk_err(e, ty);
             }
             Ok(Err(bad_ty)) => {
                 // The pattern cannot be turned into a valtree.
                 let e = match bad_ty.kind() {
                     ty::Adt(def, ..) => {
                         assert!(def.is_union());
-                        self.tcx.dcx().emit_err(UnionPattern { span: self.span })
+                        self.tcx.dcx().create_err(UnionPattern { span: self.span })
                     }
                     ty::FnPtr(..) | ty::RawPtr(..) => {
-                        self.tcx.dcx().emit_err(PointerPattern { span: self.span })
+                        self.tcx.dcx().create_err(PointerPattern { span: self.span })
                     }
-                    _ => self
-                        .tcx
-                        .dcx()
-                        .emit_err(InvalidPattern { span: self.span, non_sm_ty: bad_ty }),
+                    _ => self.tcx.dcx().create_err(InvalidPattern {
+                        span: self.span,
+                        non_sm_ty: bad_ty,
+                        prefix: bad_ty.prefix_string(self.tcx).to_string(),
+                    }),
                 };
-                return pat_from_kind(PatKind::Error(e));
+                return self.mk_err(e, ty);
             }
         };
 
@@ -130,42 +185,16 @@ impl<'tcx> ConstToPat<'tcx> {
 
         if !inlined_const_as_pat.references_error() {
             // Always check for `PartialEq` if we had no other errors yet.
-            if !self.type_has_partial_eq_impl(ty) {
-                let err = TypeNotPartialEq { span: self.span, non_peq_ty: ty };
-                let e = self.tcx.dcx().emit_err(err);
-                return pat_from_kind(PatKind::Error(e));
+            if !type_has_partial_eq_impl(self.tcx, typing_env, ty).0 {
+                let mut err = self.tcx.dcx().create_err(TypeNotPartialEq { span: self.span, ty });
+                extend_type_not_partial_eq(self.tcx, typing_env, ty, &mut err);
+                return self.mk_err(err, ty);
             }
         }
 
         inlined_const_as_pat
     }
 
-    #[instrument(level = "trace", skip(self), ret)]
-    fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
-        let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
-        // double-check there even *is* a semantic `PartialEq` to dispatch to.
-        //
-        // (If there isn't, then we can safely issue a hard
-        // error, because that's never worked, due to compiler
-        // using `PartialEq::eq` in this scenario in the past.)
-        let partial_eq_trait_id =
-            self.tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span));
-        let partial_eq_obligation = Obligation::new(
-            self.tcx,
-            ObligationCause::dummy(),
-            param_env,
-            ty::TraitRef::new(self.tcx, partial_eq_trait_id, [ty, ty]),
-        );
-
-        // This *could* accept a type that isn't actually `PartialEq`, because region bounds get
-        // ignored. However that should be pretty much impossible since consts that do not depend on
-        // generics can only mention the `'static` lifetime, and how would one have a type that's
-        // `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem
-        // we'll need to leave some sort of trace of this requirement in the MIR so that borrowck
-        // can ensure that the type really implements `PartialEq`.
-        infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation)
-    }
-
     fn field_pats(
         &self,
         vals: impl Iterator<Item = (ValTree<'tcx>, Ty<'tcx>)>,
@@ -190,10 +219,25 @@ impl<'tcx> ConstToPat<'tcx> {
                 // Extremely important check for all ADTs! Make sure they opted-in to be used in
                 // patterns.
                 debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty);
-                let err = TypeNotStructural { span, non_sm_ty: ty };
-                let e = tcx.dcx().emit_err(err);
-                // We errored. Signal that in the pattern, so that follow up errors can be silenced.
-                PatKind::Error(e)
+                let (_impls_partial_eq, derived, structural, impl_def_id) =
+                    type_has_partial_eq_impl(self.tcx, self.typing_env, ty);
+                let (manual_partialeq_impl_span, manual_partialeq_impl_note) =
+                    match (structural, impl_def_id) {
+                        (true, _) => (None, false),
+                        (_, Some(def_id)) if def_id.is_local() && !derived => {
+                            (Some(tcx.def_span(def_id)), false)
+                        }
+                        _ => (None, true),
+                    };
+                let ty_def_span = tcx.def_span(adt_def.did());
+                let err = TypeNotStructural {
+                    span,
+                    ty,
+                    ty_def_span,
+                    manual_partialeq_impl_span,
+                    manual_partialeq_impl_note,
+                };
+                return self.mk_err(tcx.dcx().create_err(err), ty);
             }
             ty::Adt(adt_def, args) if adt_def.is_enum() => {
                 let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap();
@@ -207,7 +251,7 @@ impl<'tcx> ConstToPat<'tcx> {
                             adt_def.variants()[variant_index]
                                 .fields
                                 .iter()
-                                .map(|field| field.ty(self.tcx, args)),
+                                .map(|field| field.ty(tcx, args)),
                         ),
                     ),
                 }
@@ -216,7 +260,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 assert!(!def.is_union()); // Valtree construction would never succeed for unions.
                 PatKind::Leaf {
                     subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip(
-                        def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx, args)),
+                        def.non_enum_variant().fields.iter().map(|field| field.ty(tcx, args)),
                     )),
                 }
             }
@@ -252,10 +296,10 @@ impl<'tcx> ConstToPat<'tcx> {
                 // deref pattern.
                 _ => {
                     if !pointee_ty.is_sized(tcx, self.typing_env) && !pointee_ty.is_slice() {
-                        let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
-                        let e = tcx.dcx().emit_err(err);
-                        // We errored. Signal that in the pattern, so that follow up errors can be silenced.
-                        PatKind::Error(e)
+                        return self.mk_err(
+                            tcx.dcx().create_err(UnsizedPattern { span, non_sm_ty: *pointee_ty }),
+                            ty,
+                        );
                     } else {
                         // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
                         // matching against references, you can only use byte string literals.
@@ -286,8 +330,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 if is_nan {
                     // NaNs are not ever equal to anything so they make no sense as patterns.
                     // Also see <https://github.com/rust-lang/rfcs/pull/3535>.
-                    let e = tcx.dcx().emit_err(NaNPattern { span });
-                    PatKind::Error(e)
+                    return self.mk_err(tcx.dcx().create_err(NaNPattern { span }), ty);
                 } else {
                     PatKind::Constant {
                         value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
@@ -305,13 +348,153 @@ impl<'tcx> ConstToPat<'tcx> {
                 )
             }
             _ => {
-                let err = InvalidPattern { span, non_sm_ty: ty };
-                let e = tcx.dcx().emit_err(err);
-                // We errored. Signal that in the pattern, so that follow up errors can be silenced.
-                PatKind::Error(e)
+                let err = InvalidPattern {
+                    span,
+                    non_sm_ty: ty,
+                    prefix: ty.prefix_string(tcx).to_string(),
+                };
+                return self.mk_err(tcx.dcx().create_err(err), ty);
             }
         };
 
         Box::new(Pat { span, ty, kind })
     }
 }
+
+/// Given a type with type parameters, visit every ADT looking for types that need to
+/// `#[derive(PartialEq)]` for it to be a structural type.
+fn extend_type_not_partial_eq<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
+    ty: Ty<'tcx>,
+    err: &mut Diag<'_>,
+) {
+    /// Collect all types that need to be `StructuralPartialEq`.
+    struct UsedParamsNeedInstantiationVisitor<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        typing_env: ty::TypingEnv<'tcx>,
+        /// The user has written `impl PartialEq for Ty` which means it's non-structual.
+        adts_with_manual_partialeq: FxHashSet<Span>,
+        /// The type has no `PartialEq` implementation, neither manual or derived.
+        adts_without_partialeq: FxHashSet<Span>,
+        /// The user has written `impl PartialEq for Ty` which means it's non-structual,
+        /// but we don't have a span to point at, so we'll just add them as a `note`.
+        manual: Vec<Ty<'tcx>>,
+        /// The type has no `PartialEq` implementation, neither manual or derived, but
+        /// we don't have a span to point at, so we'll just add them as a `note`.
+        without: Vec<Ty<'tcx>>,
+    }
+
+    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor<'tcx> {
+        fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
+            if let ty::Adt(def, _args) = ty.kind() {
+                let ty_def_id = def.did();
+                let ty_def_span = self.tcx.def_span(ty_def_id);
+                let (impls_partial_eq, derived, structural, impl_def_id) =
+                    type_has_partial_eq_impl(self.tcx, self.typing_env, ty);
+                match (impls_partial_eq, derived, structural, impl_def_id) {
+                    (_, _, true, _) => {}
+                    (true, false, _, Some(def_id)) if def_id.is_local() => {
+                        self.adts_with_manual_partialeq.insert(self.tcx.def_span(def_id));
+                    }
+                    (true, false, _, _) if ty_def_id.is_local() => {
+                        self.adts_with_manual_partialeq.insert(ty_def_span);
+                    }
+                    (false, _, _, _) if ty_def_id.is_local() => {
+                        self.adts_without_partialeq.insert(ty_def_span);
+                    }
+                    (true, false, _, _) => {
+                        self.manual.push(ty);
+                    }
+                    (false, _, _, _) => {
+                        self.without.push(ty);
+                    }
+                    _ => {}
+                };
+            }
+            use rustc_middle::ty::TypeSuperVisitable;
+            ty.super_visit_with(self)
+        }
+    }
+    let mut v = UsedParamsNeedInstantiationVisitor {
+        tcx,
+        typing_env,
+        adts_with_manual_partialeq: FxHashSet::default(),
+        adts_without_partialeq: FxHashSet::default(),
+        manual: vec![],
+        without: vec![],
+    };
+    v.visit_ty(ty);
+    #[allow(rustc::potential_query_instability)] // Span labels will be sorted by the rendering
+    for span in v.adts_with_manual_partialeq {
+        err.span_note(span, "the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details");
+    }
+    #[allow(rustc::potential_query_instability)] // Span labels will be sorted by the rendering
+    for span in v.adts_without_partialeq {
+        err.span_label(
+            span,
+            "must be annotated with `#[derive(PartialEq)]` to be usable in patterns",
+        );
+    }
+    for ty in v.manual {
+        err.note(format!(
+            "`{ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details"
+        ));
+    }
+    for ty in v.without {
+        err.note(format!(
+            "`{ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns"
+        ));
+    }
+}
+
+#[instrument(level = "trace", skip(tcx), ret)]
+fn type_has_partial_eq_impl<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    typing_env: ty::TypingEnv<'tcx>,
+    ty: Ty<'tcx>,
+) -> (
+    /* has impl */ bool,
+    /* is derived */ bool,
+    /* structural partial eq */ bool,
+    /* non-blanket impl */ Option<DefId>,
+) {
+    let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
+    // double-check there even *is* a semantic `PartialEq` to dispatch to.
+    //
+    // (If there isn't, then we can safely issue a hard
+    // error, because that's never worked, due to compiler
+    // using `PartialEq::eq` in this scenario in the past.)
+    let partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::PartialEq, None);
+    let structural_partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::StructuralPeq, None);
+
+    let partial_eq_obligation = Obligation::new(
+        tcx,
+        ObligationCause::dummy(),
+        param_env,
+        ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]),
+    );
+
+    let mut automatically_derived = false;
+    let mut structural_peq = false;
+    let mut impl_def_id = None;
+    for def_id in tcx.non_blanket_impls_for_ty(partial_eq_trait_id, ty) {
+        automatically_derived = tcx.has_attr(def_id, sym::automatically_derived);
+        impl_def_id = Some(def_id);
+    }
+    for _ in tcx.non_blanket_impls_for_ty(structural_partial_eq_trait_id, ty) {
+        structural_peq = true;
+    }
+    // This *could* accept a type that isn't actually `PartialEq`, because region bounds get
+    // ignored. However that should be pretty much impossible since consts that do not depend on
+    // generics can only mention the `'static` lifetime, and how would one have a type that's
+    // `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem
+    // we'll need to leave some sort of trace of this requirement in the MIR so that borrowck
+    // can ensure that the type really implements `PartialEq`.
+    (
+        infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation),
+        automatically_derived,
+        structural_peq,
+        impl_def_id,
+    )
+}
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 08c6b4abd3b..3ac53fa6272 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -528,11 +528,17 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
             _ => {
                 let e = match res {
-                    Res::Def(DefKind::ConstParam, _) => {
-                        self.tcx.dcx().emit_err(ConstParamInPattern { span })
+                    Res::Def(DefKind::ConstParam, def_id) => {
+                        self.tcx.dcx().emit_err(ConstParamInPattern {
+                            span,
+                            const_span: self.tcx().def_span(def_id),
+                        })
                     }
-                    Res::Def(DefKind::Static { .. }, _) => {
-                        self.tcx.dcx().emit_err(StaticInPattern { span })
+                    Res::Def(DefKind::Static { .. }, def_id) => {
+                        self.tcx.dcx().emit_err(StaticInPattern {
+                            span,
+                            static_span: self.tcx().def_span(def_id),
+                        })
                     }
                     _ => self.tcx.dcx().emit_err(NonConstPath { span }),
                 };
diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
index 11cf8c3e898..4a9bcdaddb3 100644
--- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
@@ -15,7 +15,6 @@ pub enum ResultsHandle<'a, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
-    Borrowed(&'a Results<'tcx, A>),
     BorrowedMut(&'a mut Results<'tcx, A>),
     Owned(Results<'tcx, A>),
 }
@@ -28,7 +27,6 @@ where
 
     fn deref(&self) -> &Results<'tcx, A> {
         match self {
-            ResultsHandle::Borrowed(borrowed) => borrowed,
             ResultsHandle::BorrowedMut(borrowed) => borrowed,
             ResultsHandle::Owned(owned) => owned,
         }
@@ -41,9 +39,6 @@ where
 {
     fn deref_mut(&mut self) -> &mut Results<'tcx, A> {
         match self {
-            ResultsHandle::Borrowed(_borrowed) => {
-                panic!("tried to deref_mut a `ResultsHandle::Borrowed")
-            }
             ResultsHandle::BorrowedMut(borrowed) => borrowed,
             ResultsHandle::Owned(owned) => owned,
         }
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index 6e4994af8b4..561229cf725 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -47,7 +47,7 @@ where
 {
     pub(crate) fn new(
         body: &'mir Body<'tcx>,
-        results: &'mir Results<'tcx, A>,
+        results: &'mir mut Results<'tcx, A>,
         style: OutputStyle,
     ) -> Self {
         let reachable = mir::traversal::reachable_as_bitset(body);
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index f1ea94e1689..b9407882ec5 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -281,10 +281,10 @@ pub trait Analysis<'tcx> {
             );
         }
 
-        let results = Results { analysis: self, entry_sets };
+        let mut results = Results { analysis: self, entry_sets };
 
         if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
-            let res = write_graphviz_results(tcx, body, &results, pass_name);
+            let res = write_graphviz_results(tcx, body, &mut results, pass_name);
             if let Err(e) = res {
                 error!("Failed to write graphviz dataflow results: {}", e);
             }
diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs
index 8493a7aa44b..c4321c454e6 100644
--- a/compiler/rustc_mir_dataflow/src/framework/results.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/results.rs
@@ -37,18 +37,9 @@ impl<'tcx, A> Results<'tcx, A>
 where
     A: Analysis<'tcx>,
 {
-    /// Creates a `ResultsCursor` that can inspect these `Results`. Immutably borrows the `Results`,
-    /// which is appropriate when the `Results` is used outside the cursor.
+    /// Creates a `ResultsCursor` that mutably borrows the `Results`, which is appropriate when the
+    /// `Results` is also used outside the cursor.
     pub fn as_results_cursor<'mir>(
-        &'mir self,
-        body: &'mir mir::Body<'tcx>,
-    ) -> ResultsCursor<'mir, 'tcx, A> {
-        ResultsCursor::new(body, ResultsHandle::Borrowed(self))
-    }
-
-    /// Creates a `ResultsCursor` that can mutate these `Results`. Mutably borrows the `Results`,
-    /// which is appropriate when the `Results` is used outside the cursor.
-    pub fn as_results_cursor_mut<'mir>(
         &'mir mut self,
         body: &'mir mir::Body<'tcx>,
     ) -> ResultsCursor<'mir, 'tcx, A> {
@@ -95,7 +86,7 @@ where
 pub(super) fn write_graphviz_results<'tcx, A>(
     tcx: TyCtxt<'tcx>,
     body: &mir::Body<'tcx>,
-    results: &Results<'tcx, A>,
+    results: &mut Results<'tcx, A>,
     pass_name: Option<&'static str>,
 ) -> std::io::Result<()>
 where
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 9b9aeccf890..858752a3f01 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -680,7 +680,7 @@ fn locals_live_across_suspend_points<'tcx>(
     let mut requires_storage_results =
         MaybeRequiresStorage::new(borrowed_locals_results.into_results_cursor(body))
             .iterate_to_fixpoint(tcx, body, None);
-    let mut requires_storage_cursor = requires_storage_results.as_results_cursor_mut(body);
+    let mut requires_storage_cursor = requires_storage_results.as_results_cursor(body);
 
     // Calculate the liveness of MIR locals ignoring borrows.
     let mut liveness =
diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs
index cf9f6981c5a..46efdd16ee8 100644
--- a/compiler/rustc_mir_transform/src/coverage/counters.rs
+++ b/compiler/rustc_mir_transform/src/coverage/counters.rs
@@ -1,3 +1,4 @@
+use std::cmp::Ordering;
 use std::fmt::{self, Debug};
 
 use rustc_data_structures::captures::Captures;
@@ -10,9 +11,12 @@ use tracing::{debug, debug_span, instrument};
 
 use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, TraverseCoverageGraphWithLoops};
 
+#[cfg(test)]
+mod tests;
+
 /// The coverage counter or counter expression associated with a particular
 /// BCB node or BCB edge.
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
 enum BcbCounter {
     Counter { id: CounterId },
     Expression { id: ExpressionId },
@@ -43,8 +47,9 @@ struct BcbExpression {
     rhs: BcbCounter,
 }
 
-#[derive(Debug)]
-pub(super) enum CounterIncrementSite {
+/// Enum representing either a node or an edge in the coverage graph.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub(super) enum Site {
     Node { bcb: BasicCoverageBlock },
     Edge { from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock },
 }
@@ -54,16 +59,10 @@ pub(super) enum CounterIncrementSite {
 pub(super) struct CoverageCounters {
     /// List of places where a counter-increment statement should be injected
     /// into MIR, each with its corresponding counter ID.
-    counter_increment_sites: IndexVec<CounterId, CounterIncrementSite>,
+    counter_increment_sites: IndexVec<CounterId, Site>,
 
     /// Coverage counters/expressions that are associated with individual BCBs.
     node_counters: IndexVec<BasicCoverageBlock, Option<BcbCounter>>,
-    /// Coverage counters/expressions that are associated with the control-flow
-    /// edge between two BCBs.
-    ///
-    /// We currently don't iterate over this map, but if we do in the future,
-    /// switch it back to `FxIndexMap` to avoid query stability hazards.
-    edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>,
 
     /// Table of expression data, associating each expression ID with its
     /// corresponding operator (+ or -) and its LHS/RHS operands.
@@ -83,93 +82,30 @@ impl CoverageCounters {
         let mut builder = CountersBuilder::new(graph, bcb_needs_counter);
         builder.make_bcb_counters();
 
-        builder.counters
+        builder.into_coverage_counters()
     }
 
     fn with_num_bcbs(num_bcbs: usize) -> Self {
         Self {
             counter_increment_sites: IndexVec::new(),
             node_counters: IndexVec::from_elem_n(None, num_bcbs),
-            edge_counters: FxHashMap::default(),
             expressions: IndexVec::new(),
             expressions_memo: FxHashMap::default(),
         }
     }
 
-    /// Shared helper used by [`Self::make_phys_node_counter`] and
-    /// [`Self::make_phys_edge_counter`]. Don't call this directly.
-    fn make_counter_inner(&mut self, site: CounterIncrementSite) -> BcbCounter {
+    /// Creates a new physical counter for a BCB node or edge.
+    fn make_phys_counter(&mut self, site: Site) -> BcbCounter {
         let id = self.counter_increment_sites.push(site);
         BcbCounter::Counter { id }
     }
 
-    /// Creates a new physical counter for a BCB node.
-    fn make_phys_node_counter(&mut self, bcb: BasicCoverageBlock) -> BcbCounter {
-        self.make_counter_inner(CounterIncrementSite::Node { bcb })
-    }
-
-    /// Creates a new physical counter for a BCB edge.
-    fn make_phys_edge_counter(
-        &mut self,
-        from_bcb: BasicCoverageBlock,
-        to_bcb: BasicCoverageBlock,
-    ) -> BcbCounter {
-        self.make_counter_inner(CounterIncrementSite::Edge { from_bcb, to_bcb })
-    }
-
     fn make_expression(&mut self, lhs: BcbCounter, op: Op, rhs: BcbCounter) -> BcbCounter {
         let new_expr = BcbExpression { lhs, op, rhs };
-        *self
-            .expressions_memo
-            .entry(new_expr)
-            .or_insert_with(|| Self::make_expression_inner(&mut self.expressions, new_expr))
-    }
-
-    /// This is an associated function so that we can call it while borrowing
-    /// `&mut self.expressions_memo`.
-    fn make_expression_inner(
-        expressions: &mut IndexVec<ExpressionId, BcbExpression>,
-        new_expr: BcbExpression,
-    ) -> BcbCounter {
-        // Simplify expressions using basic algebra.
-        //
-        // Some of these cases might not actually occur in practice, depending
-        // on the details of how the instrumentor builds expressions.
-        let BcbExpression { lhs, op, rhs } = new_expr;
-
-        if let BcbCounter::Expression { id } = lhs {
-            let lhs_expr = &expressions[id];
-
-            // Simplify `(a - b) + b` to `a`.
-            if lhs_expr.op == Op::Subtract && op == Op::Add && lhs_expr.rhs == rhs {
-                return lhs_expr.lhs;
-            }
-            // Simplify `(a + b) - b` to `a`.
-            if lhs_expr.op == Op::Add && op == Op::Subtract && lhs_expr.rhs == rhs {
-                return lhs_expr.lhs;
-            }
-            // Simplify `(a + b) - a` to `b`.
-            if lhs_expr.op == Op::Add && op == Op::Subtract && lhs_expr.lhs == rhs {
-                return lhs_expr.rhs;
-            }
-        }
-
-        if let BcbCounter::Expression { id } = rhs {
-            let rhs_expr = &expressions[id];
-
-            // Simplify `a + (b - a)` to `b`.
-            if op == Op::Add && rhs_expr.op == Op::Subtract && lhs == rhs_expr.rhs {
-                return rhs_expr.lhs;
-            }
-            // Simplify `a - (a - b)` to `b`.
-            if op == Op::Subtract && rhs_expr.op == Op::Subtract && lhs == rhs_expr.lhs {
-                return rhs_expr.rhs;
-            }
-        }
-
-        // Simplification failed, so actually create the new expression.
-        let id = expressions.push(new_expr);
-        BcbCounter::Expression { id }
+        *self.expressions_memo.entry(new_expr).or_insert_with(|| {
+            let id = self.expressions.push(new_expr);
+            BcbCounter::Expression { id }
+        })
     }
 
     /// Creates a counter that is the sum of the given counters.
@@ -182,6 +118,12 @@ impl CoverageCounters {
             .reduce(|accum, counter| self.make_expression(accum, Op::Add, counter))
     }
 
+    /// Creates a counter whose value is `lhs - SUM(rhs)`.
+    fn make_subtracted_sum(&mut self, lhs: BcbCounter, rhs: &[BcbCounter]) -> BcbCounter {
+        let Some(rhs_sum) = self.make_sum(rhs) else { return lhs };
+        self.make_expression(lhs, Op::Subtract, rhs_sum)
+    }
+
     pub(super) fn num_counters(&self) -> usize {
         self.counter_increment_sites.len()
     }
@@ -195,20 +137,6 @@ impl CoverageCounters {
         counter
     }
 
-    fn set_edge_counter(
-        &mut self,
-        from_bcb: BasicCoverageBlock,
-        to_bcb: BasicCoverageBlock,
-        counter: BcbCounter,
-    ) -> BcbCounter {
-        let existing = self.edge_counters.insert((from_bcb, to_bcb), counter);
-        assert!(
-            existing.is_none(),
-            "edge ({from_bcb:?} -> {to_bcb:?}) already has a counter: {existing:?} => {counter:?}"
-        );
-        counter
-    }
-
     pub(super) fn term_for_bcb(&self, bcb: BasicCoverageBlock) -> Option<CovTerm> {
         self.node_counters[bcb].map(|counter| counter.as_term())
     }
@@ -218,8 +146,8 @@ impl CoverageCounters {
     /// each site's corresponding counter ID.
     pub(super) fn counter_increment_sites(
         &self,
-    ) -> impl Iterator<Item = (CounterId, &CounterIncrementSite)> {
-        self.counter_increment_sites.iter_enumerated()
+    ) -> impl Iterator<Item = (CounterId, Site)> + Captures<'_> {
+        self.counter_increment_sites.iter_enumerated().map(|(id, &site)| (id, site))
     }
 
     /// Returns an iterator over the subset of BCB nodes that have been associated
@@ -254,22 +182,53 @@ impl CoverageCounters {
     }
 }
 
+/// Symbolic representation of the coverage counter to be used for a particular
+/// node or edge in the coverage graph. The same site counter can be used for
+/// multiple sites, if they have been determined to have the same count.
+#[derive(Clone, Copy, Debug)]
+enum SiteCounter {
+    /// A physical counter at some node/edge.
+    Phys { site: Site },
+    /// A counter expression for a node that takes the sum of all its in-edge
+    /// counters.
+    NodeSumExpr { bcb: BasicCoverageBlock },
+    /// A counter expression for an edge that takes the counter of its source
+    /// node, and subtracts the counters of all its sibling out-edges.
+    EdgeDiffExpr { from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock },
+}
+
+/// Yields the graph successors of `from_bcb` that aren't `to_bcb`. This is
+/// used when creating a counter expression for [`SiteCounter::EdgeDiffExpr`].
+///
+/// For example, in this diagram the sibling out-edge targets of edge `AC` are
+/// the nodes `B` and `D`.
+///
+/// ```text
+///    A
+///  / | \
+/// B  C  D
+/// ```
+fn sibling_out_edge_targets(
+    graph: &CoverageGraph,
+    from_bcb: BasicCoverageBlock,
+    to_bcb: BasicCoverageBlock,
+) -> impl Iterator<Item = BasicCoverageBlock> + Captures<'_> {
+    graph.successors[from_bcb].iter().copied().filter(move |&t| t != to_bcb)
+}
+
 /// Helper struct that allows counter creation to inspect the BCB graph, and
 /// the set of nodes that need counters.
 struct CountersBuilder<'a> {
-    counters: CoverageCounters,
     graph: &'a CoverageGraph,
     bcb_needs_counter: &'a BitSet<BasicCoverageBlock>,
+
+    site_counters: FxHashMap<Site, SiteCounter>,
 }
 
 impl<'a> CountersBuilder<'a> {
     fn new(graph: &'a CoverageGraph, bcb_needs_counter: &'a BitSet<BasicCoverageBlock>) -> Self {
         assert_eq!(graph.num_nodes(), bcb_needs_counter.domain_size());
-        Self {
-            counters: CoverageCounters::with_num_bcbs(graph.num_nodes()),
-            graph,
-            bcb_needs_counter,
-        }
+        Self { graph, bcb_needs_counter, site_counters: FxHashMap::default() }
     }
 
     fn make_bcb_counters(&mut self) {
@@ -302,9 +261,7 @@ impl<'a> CountersBuilder<'a> {
     fn make_node_counter_and_out_edge_counters(&mut self, from_bcb: BasicCoverageBlock) {
         // First, ensure that this node has a counter of some kind.
         // We might also use that counter to compute one of the out-edge counters.
-        let node_counter = self.get_or_make_node_counter(from_bcb);
-
-        let successors = self.graph.successors[from_bcb].as_slice();
+        self.get_or_make_node_counter(from_bcb);
 
         // If this node's out-edges won't sum to the node's counter,
         // then there's no reason to create edge counters here.
@@ -315,11 +272,11 @@ impl<'a> CountersBuilder<'a> {
         // When choosing which out-edge should be given a counter expression, ignore edges that
         // already have counters, or could use the existing counter of their target node.
         let out_edge_has_counter = |to_bcb| {
-            if self.counters.edge_counters.contains_key(&(from_bcb, to_bcb)) {
+            if self.site_counters.contains_key(&Site::Edge { from_bcb, to_bcb }) {
                 return true;
             }
             self.graph.sole_predecessor(to_bcb) == Some(from_bcb)
-                && self.counters.node_counters[to_bcb].is_some()
+                && self.site_counters.contains_key(&Site::Node { bcb: to_bcb })
         };
 
         // Determine the set of out-edges that could benefit from being given an expression.
@@ -332,51 +289,41 @@ impl<'a> CountersBuilder<'a> {
 
         // If there are out-edges without counters, choose one to be given an expression
         // (computed from this node and the other out-edges) instead of a physical counter.
-        let Some(target_bcb) = self.choose_out_edge_for_expression(from_bcb, &candidate_successors)
+        let Some(to_bcb) = self.choose_out_edge_for_expression(from_bcb, &candidate_successors)
         else {
             return;
         };
 
         // For each out-edge other than the one that was chosen to get an expression,
-        // ensure that it has a counter (existing counter/expression or a new counter),
-        // and accumulate the corresponding counters into a single sum expression.
-        let other_out_edge_counters = successors
-            .iter()
-            .copied()
-            // Skip the chosen edge, since we'll calculate its count from this sum.
-            .filter(|&edge_target_bcb| edge_target_bcb != target_bcb)
-            .map(|to_bcb| self.get_or_make_edge_counter(from_bcb, to_bcb))
-            .collect::<Vec<_>>();
-        let Some(sum_of_all_other_out_edges) = self.counters.make_sum(&other_out_edge_counters)
-        else {
-            return;
-        };
+        // ensure that it has a counter (existing counter/expression or a new counter).
+        for target in sibling_out_edge_targets(self.graph, from_bcb, to_bcb) {
+            self.get_or_make_edge_counter(from_bcb, target);
+        }
 
         // Now create an expression for the chosen edge, by taking the counter
         // for its source node and subtracting the sum of its sibling out-edges.
-        let expression =
-            self.counters.make_expression(node_counter, Op::Subtract, sum_of_all_other_out_edges);
-
-        debug!("{target_bcb:?} gets an expression: {expression:?}");
-        self.counters.set_edge_counter(from_bcb, target_bcb, expression);
+        let counter = SiteCounter::EdgeDiffExpr { from_bcb, to_bcb };
+        self.site_counters.insert(Site::Edge { from_bcb, to_bcb }, counter);
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn get_or_make_node_counter(&mut self, bcb: BasicCoverageBlock) -> BcbCounter {
+    fn get_or_make_node_counter(&mut self, bcb: BasicCoverageBlock) -> SiteCounter {
         // If the BCB already has a counter, return it.
-        if let Some(counter) = self.counters.node_counters[bcb] {
+        if let Some(&counter) = self.site_counters.get(&Site::Node { bcb }) {
             debug!("{bcb:?} already has a counter: {counter:?}");
             return counter;
         }
 
         let counter = self.make_node_counter_inner(bcb);
-        self.counters.set_node_counter(bcb, counter)
+        self.site_counters.insert(Site::Node { bcb }, counter);
+        counter
     }
 
-    fn make_node_counter_inner(&mut self, bcb: BasicCoverageBlock) -> BcbCounter {
+    fn make_node_counter_inner(&mut self, bcb: BasicCoverageBlock) -> SiteCounter {
         // If the node's sole in-edge already has a counter, use that.
         if let Some(sole_pred) = self.graph.sole_predecessor(bcb)
-            && let Some(&edge_counter) = self.counters.edge_counters.get(&(sole_pred, bcb))
+            && let Some(&edge_counter) =
+                self.site_counters.get(&Site::Edge { from_bcb: sole_pred, to_bcb: bcb })
         {
             return edge_counter;
         }
@@ -390,20 +337,17 @@ impl<'a> CountersBuilder<'a> {
         //   leading to infinite recursion.
         if predecessors.len() <= 1 || predecessors.contains(&bcb) {
             debug!(?bcb, ?predecessors, "node has <=1 predecessors or is its own predecessor");
-            let counter = self.counters.make_phys_node_counter(bcb);
+            let counter = SiteCounter::Phys { site: Site::Node { bcb } };
             debug!(?bcb, ?counter, "node gets a physical counter");
             return counter;
         }
 
         // A BCB with multiple incoming edges can compute its count by ensuring that counters
         // exist for each of those edges, and then adding them up to get a total count.
-        let in_edge_counters = predecessors
-            .iter()
-            .copied()
-            .map(|from_bcb| self.get_or_make_edge_counter(from_bcb, bcb))
-            .collect::<Vec<_>>();
-        let sum_of_in_edges: BcbCounter =
-            self.counters.make_sum(&in_edge_counters).expect("there must be at least one in-edge");
+        for &from_bcb in predecessors {
+            self.get_or_make_edge_counter(from_bcb, bcb);
+        }
+        let sum_of_in_edges = SiteCounter::NodeSumExpr { bcb };
 
         debug!("{bcb:?} gets a new counter (sum of predecessor counters): {sum_of_in_edges:?}");
         sum_of_in_edges
@@ -414,22 +358,23 @@ impl<'a> CountersBuilder<'a> {
         &mut self,
         from_bcb: BasicCoverageBlock,
         to_bcb: BasicCoverageBlock,
-    ) -> BcbCounter {
+    ) -> SiteCounter {
         // If the edge already has a counter, return it.
-        if let Some(&counter) = self.counters.edge_counters.get(&(from_bcb, to_bcb)) {
+        if let Some(&counter) = self.site_counters.get(&Site::Edge { from_bcb, to_bcb }) {
             debug!("Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter:?}");
             return counter;
         }
 
         let counter = self.make_edge_counter_inner(from_bcb, to_bcb);
-        self.counters.set_edge_counter(from_bcb, to_bcb, counter)
+        self.site_counters.insert(Site::Edge { from_bcb, to_bcb }, counter);
+        counter
     }
 
     fn make_edge_counter_inner(
         &mut self,
         from_bcb: BasicCoverageBlock,
         to_bcb: BasicCoverageBlock,
-    ) -> BcbCounter {
+    ) -> SiteCounter {
         // If the target node has exactly one in-edge (i.e. this one), then just
         // use the node's counter, since it will have the same value.
         if let Some(sole_pred) = self.graph.sole_predecessor(to_bcb) {
@@ -447,7 +392,7 @@ impl<'a> CountersBuilder<'a> {
         }
 
         // Make a new counter to count this edge.
-        let counter = self.counters.make_phys_edge_counter(from_bcb, to_bcb);
+        let counter = SiteCounter::Phys { site: Site::Edge { from_bcb, to_bcb } };
         debug!(?from_bcb, ?to_bcb, ?counter, "edge gets a physical counter");
         counter
     }
@@ -510,4 +455,145 @@ impl<'a> CountersBuilder<'a> {
 
         None
     }
+
+    fn into_coverage_counters(self) -> CoverageCounters {
+        Transcriber::new(&self).transcribe_counters()
+    }
+}
+
+/// Helper struct for converting `CountersBuilder` into a final `CoverageCounters`.
+struct Transcriber<'a> {
+    old: &'a CountersBuilder<'a>,
+    new: CoverageCounters,
+    phys_counter_for_site: FxHashMap<Site, BcbCounter>,
+}
+
+impl<'a> Transcriber<'a> {
+    fn new(old: &'a CountersBuilder<'a>) -> Self {
+        Self {
+            old,
+            new: CoverageCounters::with_num_bcbs(old.graph.num_nodes()),
+            phys_counter_for_site: FxHashMap::default(),
+        }
+    }
+
+    fn transcribe_counters(mut self) -> CoverageCounters {
+        for bcb in self.old.bcb_needs_counter.iter() {
+            let site = Site::Node { bcb };
+            let site_counter = self.site_counter(site);
+
+            // Resolve the site counter into flat lists of nodes/edges whose
+            // physical counts contribute to the counter for this node.
+            // Distinguish between counts that will be added vs subtracted.
+            let mut pos = vec![];
+            let mut neg = vec![];
+            self.push_resolved_sites(site_counter, &mut pos, &mut neg);
+
+            // Simplify by cancelling out sites that appear on both sides.
+            let (mut pos, mut neg) = sort_and_cancel(pos, neg);
+
+            if pos.is_empty() {
+                // If we somehow end up with no positive terms after cancellation,
+                // fall back to creating a physical counter. There's no known way
+                // for this to happen, but it's hard to confidently rule it out.
+                debug_assert!(false, "{site:?} has no positive counter terms");
+                pos = vec![Some(site)];
+                neg = vec![];
+            }
+
+            let mut new_counters_for_sites = |sites: Vec<Option<Site>>| {
+                sites
+                    .into_iter()
+                    .filter_map(|id| try { self.ensure_phys_counter(id?) })
+                    .collect::<Vec<_>>()
+            };
+            let mut pos = new_counters_for_sites(pos);
+            let mut neg = new_counters_for_sites(neg);
+
+            pos.sort();
+            neg.sort();
+
+            let pos_counter = self.new.make_sum(&pos).expect("`pos` should not be empty");
+            let new_counter = self.new.make_subtracted_sum(pos_counter, &neg);
+            self.new.set_node_counter(bcb, new_counter);
+        }
+
+        self.new
+    }
+
+    fn site_counter(&self, site: Site) -> SiteCounter {
+        self.old.site_counters.get(&site).copied().unwrap_or_else(|| {
+            // We should have already created all necessary site counters.
+            // But if we somehow didn't, avoid crashing in release builds,
+            // and just use an extra physical counter instead.
+            debug_assert!(false, "{site:?} should have a counter");
+            SiteCounter::Phys { site }
+        })
+    }
+
+    fn ensure_phys_counter(&mut self, site: Site) -> BcbCounter {
+        *self.phys_counter_for_site.entry(site).or_insert_with(|| self.new.make_phys_counter(site))
+    }
+
+    /// Resolves the given counter into flat lists of nodes/edges, whose counters
+    /// will then be added and subtracted to form a counter expression.
+    fn push_resolved_sites(&self, counter: SiteCounter, pos: &mut Vec<Site>, neg: &mut Vec<Site>) {
+        match counter {
+            SiteCounter::Phys { site } => pos.push(site),
+            SiteCounter::NodeSumExpr { bcb } => {
+                for &from_bcb in &self.old.graph.predecessors[bcb] {
+                    let edge_counter = self.site_counter(Site::Edge { from_bcb, to_bcb: bcb });
+                    self.push_resolved_sites(edge_counter, pos, neg);
+                }
+            }
+            SiteCounter::EdgeDiffExpr { from_bcb, to_bcb } => {
+                // First, add the count for `from_bcb`.
+                let node_counter = self.site_counter(Site::Node { bcb: from_bcb });
+                self.push_resolved_sites(node_counter, pos, neg);
+
+                // Then subtract the counts for the other out-edges.
+                for target in sibling_out_edge_targets(self.old.graph, from_bcb, to_bcb) {
+                    let edge_counter = self.site_counter(Site::Edge { from_bcb, to_bcb: target });
+                    // Swap `neg` and `pos` so that the counter is subtracted.
+                    self.push_resolved_sites(edge_counter, neg, pos);
+                }
+            }
+        }
+    }
+}
+
+/// Given two lists:
+/// - Sorts each list.
+/// - Converts each list to `Vec<Option<T>>`.
+/// - Scans for values that appear in both lists, and cancels them out by
+///   replacing matching pairs of values with `None`.
+fn sort_and_cancel<T: Ord>(mut pos: Vec<T>, mut neg: Vec<T>) -> (Vec<Option<T>>, Vec<Option<T>>) {
+    pos.sort();
+    neg.sort();
+
+    // Convert to `Vec<Option<T>>`. If `T` has a niche, this should be zero-cost.
+    let mut pos = pos.into_iter().map(Some).collect::<Vec<_>>();
+    let mut neg = neg.into_iter().map(Some).collect::<Vec<_>>();
+
+    // Scan through the lists using two cursors. When either cursor reaches the
+    // end of its list, there can be no more equal pairs, so stop.
+    let mut p = 0;
+    let mut n = 0;
+    while p < pos.len() && n < neg.len() {
+        // If the values are equal, remove them and advance both cursors.
+        // Otherwise, advance whichever cursor points to the lesser value.
+        // (Choosing which cursor to advance relies on both lists being sorted.)
+        match pos[p].cmp(&neg[n]) {
+            Ordering::Less => p += 1,
+            Ordering::Equal => {
+                pos[p] = None;
+                neg[n] = None;
+                p += 1;
+                n += 1;
+            }
+            Ordering::Greater => n += 1,
+        }
+    }
+
+    (pos, neg)
 }
diff --git a/compiler/rustc_mir_transform/src/coverage/counters/tests.rs b/compiler/rustc_mir_transform/src/coverage/counters/tests.rs
new file mode 100644
index 00000000000..794d4358f82
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/coverage/counters/tests.rs
@@ -0,0 +1,41 @@
+use std::fmt::Debug;
+
+use super::sort_and_cancel;
+
+fn flatten<T>(input: Vec<Option<T>>) -> Vec<T> {
+    input.into_iter().flatten().collect()
+}
+
+fn sort_and_cancel_and_flatten<T: Clone + Ord>(pos: Vec<T>, neg: Vec<T>) -> (Vec<T>, Vec<T>) {
+    let (pos_actual, neg_actual) = sort_and_cancel(pos, neg);
+    (flatten(pos_actual), flatten(neg_actual))
+}
+
+#[track_caller]
+fn check_test_case<T: Clone + Debug + Ord>(
+    pos: Vec<T>,
+    neg: Vec<T>,
+    pos_expected: Vec<T>,
+    neg_expected: Vec<T>,
+) {
+    eprintln!("pos = {pos:?}; neg = {neg:?}");
+    let output = sort_and_cancel_and_flatten(pos, neg);
+    assert_eq!(output, (pos_expected, neg_expected));
+}
+
+#[test]
+fn cancellation() {
+    let cases: &[(Vec<u32>, Vec<u32>, Vec<u32>, Vec<u32>)] = &[
+        (vec![], vec![], vec![], vec![]),
+        (vec![4, 2, 1, 5, 3], vec![], vec![1, 2, 3, 4, 5], vec![]),
+        (vec![5, 5, 5, 5, 5], vec![5], vec![5, 5, 5, 5], vec![]),
+        (vec![1, 1, 2, 2, 3, 3], vec![1, 2, 3], vec![1, 2, 3], vec![]),
+        (vec![1, 1, 2, 2, 3, 3], vec![2, 4, 2], vec![1, 1, 3, 3], vec![4]),
+    ];
+
+    for (pos, neg, pos_expected, neg_expected) in cases {
+        check_test_case(pos.to_vec(), neg.to_vec(), pos_expected.to_vec(), neg_expected.to_vec());
+        // Same test case, but with its inputs flipped and its outputs flipped.
+        check_test_case(neg.to_vec(), pos.to_vec(), neg_expected.to_vec(), pos_expected.to_vec());
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index e8b3d80be02..241c3c79114 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -25,7 +25,7 @@ use rustc_span::source_map::SourceMap;
 use rustc_span::{BytePos, Pos, SourceFile, Span};
 use tracing::{debug, debug_span, trace};
 
-use crate::coverage::counters::{CounterIncrementSite, CoverageCounters};
+use crate::coverage::counters::{CoverageCounters, Site};
 use crate::coverage::graph::CoverageGraph;
 use crate::coverage::mappings::ExtractedMappings;
 
@@ -265,13 +265,13 @@ fn inject_coverage_statements<'tcx>(
     coverage_counters: &CoverageCounters,
 ) {
     // Inject counter-increment statements into MIR.
-    for (id, counter_increment_site) in coverage_counters.counter_increment_sites() {
+    for (id, site) in coverage_counters.counter_increment_sites() {
         // Determine the block to inject a counter-increment statement into.
         // For BCB nodes this is just their first block, but for edges we need
         // to create a new block between the two BCBs, and inject into that.
-        let target_bb = match *counter_increment_site {
-            CounterIncrementSite::Node { bcb } => basic_coverage_blocks[bcb].leader_bb(),
-            CounterIncrementSite::Edge { from_bcb, to_bcb } => {
+        let target_bb = match site {
+            Site::Node { bcb } => basic_coverage_blocks[bcb].leader_bb(),
+            Site::Edge { from_bcb, to_bcb } => {
                 // Create a new block between the last block of `from_bcb` and
                 // the first block of `to_bcb`.
                 let from_bb = basic_coverage_blocks[from_bcb].last_bb();
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 0878fa26a92..79c38b50459 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -220,15 +220,7 @@ impl<'tcx> Inliner<'tcx> {
 
         // Normally, this shouldn't be required, but trait normalization failure can create a
         // validation ICE.
-        if !validate_types(
-            self.tcx,
-            MirPhase::Runtime(RuntimePhase::Optimized),
-            self.typing_env,
-            &callee_body,
-            &caller_body,
-        )
-        .is_empty()
-        {
+        if !validate_types(self.tcx, self.typing_env, &callee_body, &caller_body).is_empty() {
             return Err("failed to validate callee body");
         }
 
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index 779e7f22101..8a45ce0762d 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -292,7 +292,7 @@ fn run_passes_inner<'tcx>(
 }
 
 pub(super) fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) {
-    validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body);
+    validate::Validator { when }.run_pass(tcx, body);
 }
 
 fn dump_mir_for_pass<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, pass_name: &str, is_after: bool) {
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 51e5c49cea1..404fbb6b839 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -29,12 +29,6 @@ enum EdgeKind {
 pub(super) struct Validator {
     /// Describes at which point in the pipeline this validation is happening.
     pub when: String,
-    /// The phase for which we are upholding the dialect. If the given phase forbids a specific
-    /// element, this validator will now emit errors if that specific element is encountered.
-    /// Note that phases that change the dialect cause all *following* phases to check the
-    /// invariants of the new dialect. A phase that changes dialects never checks the new invariants
-    /// itself.
-    pub mir_phase: MirPhase,
 }
 
 impl<'tcx> crate::MirPass<'tcx> for Validator {
@@ -46,11 +40,9 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
         if matches!(body.source.instance, InstanceKind::Intrinsic(..) | InstanceKind::Virtual(..)) {
             return;
         }
-        debug_assert_eq!(self.mir_phase, body.phase);
         let def_id = body.source.def_id();
-        let mir_phase = body.phase;
         let typing_env = body.typing_env(tcx);
-        let can_unwind = if mir_phase <= MirPhase::Runtime(RuntimePhase::Initial) {
+        let can_unwind = if body.phase <= MirPhase::Runtime(RuntimePhase::Initial) {
             // In this case `AbortUnwindingCalls` haven't yet been executed.
             true
         } else if !tcx.def_kind(def_id).is_fn_like() {
@@ -64,9 +56,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
                 ty::Coroutine(..) => ExternAbi::Rust,
                 // No need to do MIR validation on error bodies
                 ty::Error(_) => return,
-                _ => {
-                    span_bug!(body.span, "unexpected body ty: {:?} phase {:?}", body_ty, mir_phase)
-                }
+                _ => span_bug!(body.span, "unexpected body ty: {body_ty:?}"),
             };
 
             ty::layout::fn_can_unwind(tcx, Some(def_id), body_abi)
@@ -76,7 +66,6 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
             when: &self.when,
             body,
             tcx,
-            mir_phase,
             unwind_edge_count: 0,
             reachable_blocks: traversal::reachable_as_bitset(body),
             value_cache: FxHashSet::default(),
@@ -86,7 +75,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
         cfg_checker.check_cleanup_control_flow();
 
         // Also run the TypeChecker.
-        for (location, msg) in validate_types(tcx, self.mir_phase, typing_env, body, body) {
+        for (location, msg) in validate_types(tcx, typing_env, body, body) {
             cfg_checker.fail(location, msg);
         }
 
@@ -107,7 +96,6 @@ struct CfgChecker<'a, 'tcx> {
     when: &'a str,
     body: &'a Body<'tcx>,
     tcx: TyCtxt<'tcx>,
-    mir_phase: MirPhase,
     unwind_edge_count: usize,
     reachable_blocks: BitSet<BasicBlock>,
     value_cache: FxHashSet<u128>,
@@ -294,7 +282,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
     fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
         match &statement.kind {
             StatementKind::AscribeUserType(..) => {
-                if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
+                if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(
                         location,
                         "`AscribeUserType` should have been removed after drop lowering phase",
@@ -302,7 +290,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                 }
             }
             StatementKind::FakeRead(..) => {
-                if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
+                if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(
                         location,
                         "`FakeRead` should have been removed after drop lowering phase",
@@ -310,17 +298,17 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                 }
             }
             StatementKind::SetDiscriminant { .. } => {
-                if self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) {
+                if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(location, "`SetDiscriminant`is not allowed until deaggregation");
                 }
             }
             StatementKind::Deinit(..) => {
-                if self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) {
+                if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(location, "`Deinit`is not allowed until deaggregation");
                 }
             }
             StatementKind::Retag(kind, _) => {
-                // FIXME(JakobDegen) The validator should check that `self.mir_phase <
+                // FIXME(JakobDegen) The validator should check that `self.body.phase <
                 // DropsLowered`. However, this causes ICEs with generation of drop shims, which
                 // seem to fail to set their `MirPhase` correctly.
                 if matches!(kind, RetagKind::TwoPhase) {
@@ -328,7 +316,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                 }
             }
             StatementKind::Coverage(kind) => {
-                if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup)
+                if self.body.phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup)
                     && let CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. } = kind
                 {
                     self.fail(
@@ -391,7 +379,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                     // the return edge from the call. FIXME(tmiasko): Since this is a strictly code
                     // generation concern, the code generation should be responsible for handling
                     // it.
-                    if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Optimized)
+                    if self.body.phase >= MirPhase::Runtime(RuntimePhase::Optimized)
                         && self.is_critical_call_edge(target, unwind)
                     {
                         self.fail(
@@ -440,7 +428,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                 if self.body.coroutine.is_none() {
                     self.fail(location, "`Yield` cannot appear outside coroutine bodies");
                 }
-                if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
+                if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(location, "`Yield` should have been replaced by coroutine lowering");
                 }
                 self.check_edge(location, *resume, EdgeKind::Normal);
@@ -449,7 +437,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                 }
             }
             TerminatorKind::FalseEdge { real_target, imaginary_target } => {
-                if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
+                if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(
                         location,
                         "`FalseEdge` should have been removed after drop elaboration",
@@ -459,7 +447,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                 self.check_edge(location, *imaginary_target, EdgeKind::Normal);
             }
             TerminatorKind::FalseUnwind { real_target, unwind } => {
-                if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
+                if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(
                         location,
                         "`FalseUnwind` should have been removed after drop elaboration",
@@ -478,7 +466,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                 if self.body.coroutine.is_none() {
                     self.fail(location, "`CoroutineDrop` cannot appear outside coroutine bodies");
                 }
-                if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
+                if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(
                         location,
                         "`CoroutineDrop` should have been replaced by coroutine lowering",
@@ -532,13 +520,11 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
 /// `optimized_mir` is available.
 pub(super) fn validate_types<'tcx>(
     tcx: TyCtxt<'tcx>,
-    mir_phase: MirPhase,
     typing_env: ty::TypingEnv<'tcx>,
     body: &Body<'tcx>,
     caller_body: &Body<'tcx>,
 ) -> Vec<(Location, String)> {
-    let mut type_checker =
-        TypeChecker { body, caller_body, tcx, typing_env, mir_phase, failures: Vec::new() };
+    let mut type_checker = TypeChecker { body, caller_body, tcx, typing_env, failures: Vec::new() };
     type_checker.visit_body(body);
     type_checker.failures
 }
@@ -548,7 +534,6 @@ struct TypeChecker<'a, 'tcx> {
     caller_body: &'a Body<'tcx>,
     tcx: TyCtxt<'tcx>,
     typing_env: ty::TypingEnv<'tcx>,
-    mir_phase: MirPhase,
     failures: Vec<(Location, String)>,
 }
 
@@ -577,7 +562,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
         // After borrowck subtyping should be fully explicit via
         // `Subtype` projections.
-        let variance = if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
+        let variance = if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
             Variance::Invariant
         } else {
             Variance::Covariant
@@ -618,13 +603,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
     fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
         // This check is somewhat expensive, so only run it when -Zvalidate-mir is passed.
         if self.tcx.sess.opts.unstable_opts.validate_mir
-            && self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial)
+            && self.body.phase < MirPhase::Runtime(RuntimePhase::Initial)
         {
             // `Operand::Copy` is only supposed to be used with `Copy` types.
             if let Operand::Copy(place) = operand {
                 let ty = place.ty(&self.body.local_decls, self.tcx).ty;
 
-                if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) {
+                if !self.tcx.type_is_copy_modulo_regions(self.typing_env, ty) {
                     self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}"));
                 }
             }
@@ -642,7 +627,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
     ) {
         match elem {
             ProjectionElem::OpaqueCast(ty)
-                if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) =>
+                if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) =>
             {
                 self.fail(
                     location,
@@ -656,7 +641,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 }
             }
             ProjectionElem::Deref
-                if self.mir_phase >= MirPhase::Runtime(RuntimePhase::PostCleanup) =>
+                if self.body.phase >= MirPhase::Runtime(RuntimePhase::PostCleanup) =>
             {
                 let base_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty;
 
@@ -856,7 +841,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
         // Set off any `bug!`s in the type computation code
         let _ = place.ty(&self.body.local_decls, self.tcx);
 
-        if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial)
+        if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial)
             && place.projection.len() > 1
             && cntxt != PlaceContext::NonUse(NonUseContext::VarDebugInfo)
             && place.projection[1..].contains(&ProjectionElem::Deref)
@@ -974,7 +959,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     }
                 }
                 AggregateKind::RawPtr(pointee_ty, mutability) => {
-                    if !matches!(self.mir_phase, MirPhase::Runtime(_)) {
+                    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, so
                         // earlier things just `bug!` on it.
@@ -1016,7 +1001,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 }
             },
             Rvalue::Ref(_, BorrowKind::Fake(_), _) => {
-                if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
+                if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(
                         location,
                         "`Assign` statement with a `Fake` borrow should have been removed in runtime MIR",
@@ -1130,7 +1115,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         );
                     }
                     UnOp::PtrMetadata => {
-                        if !matches!(self.mir_phase, MirPhase::Runtime(_)) {
+                        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
@@ -1206,7 +1191,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             "CastKind::{kind:?} output must be a raw const pointer, not {:?}",
                             ty::RawPtr(_, Mutability::Not)
                         );
-                        if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) {
+                        if self.body.phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) {
                             self.fail(location, format!("After borrowck, MIR disallows {kind:?}"));
                         }
                     }
@@ -1222,7 +1207,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             "CastKind::{kind:?} output must be a raw pointer, not {:?}",
                             ty::RawPtr(..)
                         );
-                        if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) {
+                        if self.body.phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) {
                             self.fail(location, format!("After borrowck, MIR disallows {kind:?}"));
                         }
                     }
@@ -1288,7 +1273,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         }
                     }
                     CastKind::Transmute => {
-                        if let MirPhase::Runtime(..) = self.mir_phase {
+                        if let MirPhase::Runtime(..) = self.body.phase {
                             // Unlike `mem::transmute`, a MIR `Transmute` is well-formed
                             // for any two `Sized` types, just potentially UB to run.
 
@@ -1317,7 +1302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                                 location,
                                 format!(
                                     "Transmute is not supported in non-runtime phase {:?}.",
-                                    self.mir_phase
+                                    self.body.phase
                                 ),
                             );
                         }
@@ -1404,7 +1389,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 }
             }
             StatementKind::AscribeUserType(..) => {
-                if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
+                if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(
                         location,
                         "`AscribeUserType` should have been removed after drop lowering phase",
@@ -1412,7 +1397,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 }
             }
             StatementKind::FakeRead(..) => {
-                if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
+                if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(
                         location,
                         "`FakeRead` should have been removed after drop lowering phase",
@@ -1463,7 +1448,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 }
             }
             StatementKind::SetDiscriminant { place, .. } => {
-                if self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) {
+                if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(location, "`SetDiscriminant`is not allowed until deaggregation");
                 }
                 let pty = place.ty(&self.body.local_decls, self.tcx).ty.kind();
@@ -1477,12 +1462,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 }
             }
             StatementKind::Deinit(..) => {
-                if self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) {
+                if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) {
                     self.fail(location, "`Deinit`is not allowed until deaggregation");
                 }
             }
             StatementKind::Retag(kind, _) => {
-                // FIXME(JakobDegen) The validator should check that `self.mir_phase <
+                // FIXME(JakobDegen) The validator should check that `self.body.phase <
                 // DropsLowered`. However, this causes ICEs with generation of drop shims, which
                 // seem to fail to set their `MirPhase` correctly.
                 if matches!(kind, RetagKind::TwoPhase) {
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index b9a325eddd8..e5cd4622dae 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -343,6 +343,9 @@ parse_incorrect_semicolon =
     .suggestion = remove this semicolon
     .help = {$name} declarations are not followed by a semicolon
 
+parse_incorrect_type_on_self = type not allowed for shorthand `self` parameter
+    .suggestion = move the modifiers on `self` to the type
+
 parse_incorrect_use_of_await = incorrect use of `await`
     .parentheses_suggestion = `await` is not a method call, remove the parentheses
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 91e8ba2e1f9..14f2dd32e92 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -3,6 +3,7 @@
 use std::borrow::Cow;
 
 use rustc_ast::token::Token;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_ast::{Path, Visibility};
 use rustc_errors::codes::*;
 use rustc_errors::{
@@ -2686,7 +2687,7 @@ pub(crate) struct UnexpectedExpressionInPattern {
     /// Was a `RangePatternBound` expected?
     pub is_bound: bool,
     /// The unexpected expr's precedence (used in match arm guard suggestions).
-    pub expr_precedence: i8,
+    pub expr_precedence: ExprPrecedence,
 }
 
 #[derive(Subdiagnostic)]
@@ -3408,3 +3409,22 @@ pub(crate) struct PolarityAndModifiers {
     pub polarity: &'static str,
     pub modifiers_concatenated: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(parse_incorrect_type_on_self)]
+pub(crate) struct IncorrectTypeOnSelf {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub move_self_modifier: MoveSelfModifier,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
+pub(crate) struct MoveSelfModifier {
+    #[suggestion_part(code = "")]
+    pub removal_span: Span,
+    #[suggestion_part(code = "{modifier}")]
+    pub insertion_span: Span,
+    pub modifier: String,
+}
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 4430d2d1431..8d16d44b0a2 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1,7 +1,7 @@
 // ignore-tidy-filelength
 
 use core::mem;
-use core::ops::ControlFlow;
+use core::ops::{Bound, ControlFlow};
 
 use ast::mut_visit::{self, MutVisitor};
 use ast::token::IdentIsRaw;
@@ -10,7 +10,7 @@ use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
 use rustc_ast::util::case::Case;
 use rustc_ast::util::classify;
-use rustc_ast::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par};
+use rustc_ast::util::parser::{AssocOp, ExprPrecedence, Fixity, prec_let_scrutinee_needs_par};
 use rustc_ast::visit::{Visitor, walk_expr};
 use rustc_ast::{
     self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy,
@@ -120,7 +120,7 @@ impl<'a> Parser<'a> {
         r: Restrictions,
         attrs: AttrWrapper,
     ) -> PResult<'a, (P<Expr>, bool)> {
-        self.with_res(r, |this| this.parse_expr_assoc_with(0, attrs))
+        self.with_res(r, |this| this.parse_expr_assoc_with(Bound::Unbounded, attrs))
     }
 
     /// Parses an associative expression with operators of at least `min_prec` precedence.
@@ -128,7 +128,7 @@ impl<'a> Parser<'a> {
     /// followed by a subexpression (e.g. `1 + 2`).
     pub(super) fn parse_expr_assoc_with(
         &mut self,
-        min_prec: usize,
+        min_prec: Bound<ExprPrecedence>,
         attrs: AttrWrapper,
     ) -> PResult<'a, (P<Expr>, bool)> {
         let lhs = if self.token.is_range_separator() {
@@ -144,7 +144,7 @@ impl<'a> Parser<'a> {
     /// was actually parsed.
     pub(super) fn parse_expr_assoc_rest_with(
         &mut self,
-        min_prec: usize,
+        min_prec: Bound<ExprPrecedence>,
         starts_stmt: bool,
         mut lhs: P<Expr>,
     ) -> PResult<'a, (P<Expr>, bool)> {
@@ -163,7 +163,11 @@ impl<'a> Parser<'a> {
                 self.restrictions
             };
             let prec = op.node.precedence();
-            if prec < min_prec {
+            if match min_prec {
+                Bound::Included(min_prec) => prec < min_prec,
+                Bound::Excluded(min_prec) => prec <= min_prec,
+                Bound::Unbounded => false,
+            } {
                 break;
             }
             // Check for deprecated `...` syntax
@@ -276,16 +280,16 @@ impl<'a> Parser<'a> {
             }
 
             let fixity = op.fixity();
-            let prec_adjustment = match fixity {
-                Fixity::Right => 0,
-                Fixity::Left => 1,
+            let min_prec = match fixity {
+                Fixity::Right => Bound::Included(prec),
+                Fixity::Left => Bound::Excluded(prec),
                 // We currently have no non-associative operators that are not handled above by
                 // the special cases. The code is here only for future convenience.
-                Fixity::None => 1,
+                Fixity::None => Bound::Excluded(prec),
             };
             let (rhs, _) = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| {
                 let attrs = this.parse_outer_attributes()?;
-                this.parse_expr_assoc_with(prec + prec_adjustment, attrs)
+                this.parse_expr_assoc_with(min_prec, attrs)
             })?;
 
             let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
@@ -451,7 +455,7 @@ impl<'a> Parser<'a> {
     /// The other two variants are handled in `parse_prefix_range_expr` below.
     fn parse_expr_range(
         &mut self,
-        prec: usize,
+        prec: ExprPrecedence,
         lhs: P<Expr>,
         op: AssocOp,
         cur_op_span: Span,
@@ -460,7 +464,7 @@ impl<'a> Parser<'a> {
             let maybe_lt = self.token.clone();
             let attrs = self.parse_outer_attributes()?;
             Some(
-                self.parse_expr_assoc_with(prec + 1, attrs)
+                self.parse_expr_assoc_with(Bound::Excluded(prec), attrs)
                     .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?
                     .0,
             )
@@ -518,7 +522,7 @@ impl<'a> Parser<'a> {
             let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
                 // RHS must be parsed with more associativity than the dots.
                 let attrs = this.parse_outer_attributes()?;
-                this.parse_expr_assoc_with(op.unwrap().precedence() + 1, attrs)
+                this.parse_expr_assoc_with(Bound::Excluded(op.unwrap().precedence()), attrs)
                     .map(|(x, _)| (lo.to(x.span), Some(x)))
                     .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))?
             } else {
@@ -2643,7 +2647,8 @@ impl<'a> Parser<'a> {
             self.expect(&token::Eq)?;
         }
         let attrs = self.parse_outer_attributes()?;
-        let (expr, _) = self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), attrs)?;
+        let (expr, _) =
+            self.parse_expr_assoc_with(Bound::Excluded(prec_let_scrutinee_needs_par()), attrs)?;
         let span = lo.to(expr.span);
         Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, recovered)))
     }
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 26e81b7676b..475cd09147f 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -2941,6 +2941,32 @@ impl<'a> Parser<'a> {
             };
             Ok((eself, eself_ident, eself_hi))
         };
+        let expect_self_ident_not_typed =
+            |this: &mut Self, modifier: &SelfKind, modifier_span: Span| {
+                let eself_ident = expect_self_ident(this);
+
+                // Recover `: Type` after a qualified self
+                if this.may_recover() && this.eat_noexpect(&token::Colon) {
+                    let snap = this.create_snapshot_for_diagnostic();
+                    match this.parse_ty() {
+                        Ok(ty) => {
+                            this.dcx().emit_err(errors::IncorrectTypeOnSelf {
+                                span: ty.span,
+                                move_self_modifier: errors::MoveSelfModifier {
+                                    removal_span: modifier_span,
+                                    insertion_span: ty.span.shrink_to_lo(),
+                                    modifier: modifier.to_ref_suggestion(),
+                                },
+                            });
+                        }
+                        Err(diag) => {
+                            diag.cancel();
+                            this.restore_snapshot(snap);
+                        }
+                    }
+                }
+                eself_ident
+            };
         // Recover for the grammar `*self`, `*const self`, and `*mut self`.
         let recover_self_ptr = |this: &mut Self| {
             this.dcx().emit_err(errors::SelfArgumentPointer { span: this.token.span });
@@ -2978,7 +3004,9 @@ impl<'a> Parser<'a> {
                     // `&not_self`
                     return Ok(None);
                 };
-                (eself, expect_self_ident(self), self.prev_token.span)
+                let hi = self.token.span;
+                let self_ident = expect_self_ident_not_typed(self, &eself, eself_lo.until(hi));
+                (eself, self_ident, hi)
             }
             // `*self`
             token::BinOp(token::Star) if is_isolated_self(self, 1) => {
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 0ed8d152d2d..37556c064d8 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1376,7 +1376,7 @@ impl<'a> Parser<'a> {
             AttrArgs::Delimited(args)
         } else if self.eat(&token::Eq) {
             let eq_span = self.prev_token.span;
-            AttrArgs::Eq(eq_span, AttrArgsEq::Ast(self.parse_expr_force_collect()?))
+            AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(self.parse_expr_force_collect()?) }
         } else {
             AttrArgs::Empty
         })
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index bb976e092bf..e08b925f008 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1,12 +1,13 @@
+use std::ops::Bound;
+
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token};
-use rustc_ast::util::parser::AssocOp;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_ast::visit::{self, Visitor};
 use rustc_ast::{
-    self as ast, Arm, AttrVec, BinOpKind, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall,
-    Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt,
-    StmtKind,
+    self as ast, Arm, AttrVec, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall, Mutability,
+    Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt, StmtKind,
 };
 use rustc_ast_pretty::pprust;
 use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey};
@@ -435,8 +436,9 @@ impl<'a> Parser<'a> {
 
         // Parse an associative expression such as `+ expr`, `% expr`, ...
         // Assignments, ranges and `|` are disabled by [`Restrictions::IS_PAT`].
-        let Ok((expr, _)) =
-            snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel())
+        let Ok((expr, _)) = snapshot
+            .parse_expr_assoc_rest_with(Bound::Unbounded, false, expr)
+            .map_err(|err| err.cancel())
         else {
             // We got a trailing method/operator, but that wasn't an expression.
             return None;
@@ -545,10 +547,7 @@ impl<'a> Parser<'a> {
                             // HACK: a neater way would be preferable.
                             let expr = match &err.args["expr_precedence"] {
                                 DiagArgValue::Number(expr_precedence) => {
-                                    if *expr_precedence
-                                        <= AssocOp::from_ast_binop(BinOpKind::Eq).precedence()
-                                            as i32
-                                    {
+                                    if *expr_precedence <= ExprPrecedence::Compare as i32 {
                                         format!("({expr})")
                                     } else {
                                         format!("{expr}")
@@ -570,9 +569,7 @@ impl<'a> Parser<'a> {
                                 }
                                 Some(guard) => {
                                     // Are parentheses required around the old guard?
-                                    let wrap_guard = guard.precedence()
-                                        <= AssocOp::from_ast_binop(BinOpKind::And).precedence()
-                                            as i8;
+                                    let wrap_guard = guard.precedence() <= ExprPrecedence::LAnd;
 
                                     err.subdiagnostic(
                                         UnexpectedExpressionInPatternSugg::UpdateGuard {
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 190cd9ed061..5fa2e01fc86 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -1,5 +1,6 @@
 use std::borrow::Cow;
 use std::mem;
+use std::ops::Bound;
 
 use ast::Label;
 use rustc_ast as ast;
@@ -207,7 +208,7 @@ impl<'a> Parser<'a> {
             // Perform this outside of the `collect_tokens` closure, since our
             // outer attributes do not apply to this part of the expression.
             let (expr, _) = self.with_res(Restrictions::STMT_EXPR, |this| {
-                this.parse_expr_assoc_rest_with(0, true, expr)
+                this.parse_expr_assoc_rest_with(Bound::Unbounded, true, expr)
             })?;
             Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr)))
         } else {
@@ -240,7 +241,7 @@ impl<'a> Parser<'a> {
             let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
             let e = self.maybe_recover_from_bad_qpath(e)?;
             let e = self.parse_expr_dot_or_call_with(attrs, e, lo)?;
-            let (e, _) = self.parse_expr_assoc_rest_with(0, false, e)?;
+            let (e, _) = self.parse_expr_assoc_rest_with(Bound::Unbounded, false, e)?;
             StmtKind::Expr(e)
         };
         Ok(self.mk_stmt(lo.to(hi), kind))
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 505586e74f1..8cff23c2e32 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -9,7 +9,7 @@ use rustc_ast::{
 };
 use rustc_errors::{Applicability, PResult};
 use rustc_span::symbol::{Ident, kw, sym};
-use rustc_span::{ErrorGuaranteed, Span, Symbol};
+use rustc_span::{ErrorGuaranteed, Span};
 use thin_vec::{ThinVec, thin_vec};
 
 use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
@@ -940,7 +940,7 @@ impl<'a> Parser<'a> {
         let asyncness = if self.token.uninterpolated_span().at_least_rust_2018()
             && self.eat_keyword(kw::Async)
         {
-            self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span);
+            self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
             BoundAsyncness::Async(self.prev_token.span)
         } else if self.may_recover()
             && self.token.uninterpolated_span().is_rust_2015()
@@ -951,7 +951,7 @@ impl<'a> Parser<'a> {
                 span: self.prev_token.span,
                 help: HelpUseLatestEdition::new(),
             });
-            self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span);
+            self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
             BoundAsyncness::Async(self.prev_token.span)
         } else {
             BoundAsyncness::Normal
@@ -1136,7 +1136,7 @@ impl<'a> Parser<'a> {
                 Some(ast::Path {
                     span: fn_token_span.to(self.prev_token.span),
                     segments: thin_vec![ast::PathSegment {
-                        ident: Ident::new(Symbol::intern("Fn"), fn_token_span),
+                        ident: Ident::new(sym::Fn, fn_token_span),
                         id: DUMMY_NODE_ID,
                         args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
                             span: args_lo.to(self.prev_token.span),
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index f3174e7dea2..aab3f10bc66 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -43,7 +43,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
             }
         }
         _ => {
-            if let AttrArgs::Eq(..) = attr_item.args {
+            if let AttrArgs::Eq { .. } = attr_item.args {
                 // All key-value attributes are restricted to meta-item syntax.
                 match parse_meta(psess, attr) {
                     Ok(_) => {}
@@ -70,7 +70,7 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met
                     parse_in(psess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?;
                 MetaItemKind::List(nmis)
             }
-            AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => {
+            AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => {
                 if let ast::ExprKind::Lit(token_lit) = expr.kind {
                     let res = ast::MetaItemLit::from_token_lit(token_lit, expr.span);
                     let res = match res {
@@ -116,7 +116,9 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met
                     return Err(err);
                 }
             }
-            AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => MetaItemKind::NameValue(lit.clone()),
+            AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => {
+                MetaItemKind::NameValue(lit.clone())
+            }
         },
     })
 }
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 0712af422ad..7a0a518bb51 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -709,8 +709,6 @@ passes_should_be_applied_to_trait =
     attribute should be applied to a trait
     .label = not a trait
 
-passes_skipping_const_checks = skipping const checks
-
 passes_stability_promotable =
     attribute cannot be applied to an expression
 
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
deleted file mode 100644
index f5ece513956..00000000000
--- a/compiler/rustc_passes/src/check_const.rs
+++ /dev/null
@@ -1,236 +0,0 @@
-//! This pass checks HIR bodies that may be evaluated at compile-time (e.g., `const`, `static`,
-//! `const fn`) for structured control flow (e.g. `if`, `while`), which is forbidden in a const
-//! context.
-//!
-//! By the time the MIR const-checker runs, these high-level constructs have been lowered to
-//! control-flow primitives (e.g., `Goto`, `SwitchInt`), making it tough to properly attribute
-//! errors. We still look for those primitives in the MIR const-checker to ensure nothing slips
-//! through, but errors for structured control flow in a `const` should be emitted here.
-
-use rustc_hir::def_id::{LocalDefId, LocalModDefId};
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_middle::hir::nested_filter;
-use rustc_middle::query::Providers;
-use rustc_middle::span_bug;
-use rustc_middle::ty::TyCtxt;
-use rustc_session::parse::feature_err;
-use rustc_span::{Span, Symbol, sym};
-use {rustc_attr as attr, rustc_hir as hir};
-
-use crate::errors::SkippingConstChecks;
-
-/// An expression that is not *always* legal in a const context.
-#[derive(Clone, Copy)]
-enum NonConstExpr {
-    Loop(hir::LoopSource),
-    Match(hir::MatchSource),
-}
-
-impl NonConstExpr {
-    fn name(self) -> String {
-        match self {
-            Self::Loop(src) => format!("`{}`", src.name()),
-            Self::Match(src) => format!("`{}`", src.name()),
-        }
-    }
-
-    fn required_feature_gates(self) -> Option<&'static [Symbol]> {
-        use hir::LoopSource::*;
-        use hir::MatchSource::*;
-
-        let gates: &[_] = match self {
-            Self::Match(AwaitDesugar) => {
-                return None;
-            }
-
-            Self::Loop(ForLoop) | Self::Match(ForLoopDesugar) => &[sym::const_for],
-
-            Self::Match(TryDesugar(_)) => &[sym::const_try],
-
-            // All other expressions are allowed.
-            Self::Loop(Loop | While) | Self::Match(Normal | Postfix | FormatArgs) => &[],
-        };
-
-        Some(gates)
-    }
-}
-
-fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
-    let mut vis = CheckConstVisitor::new(tcx);
-    tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis);
-}
-
-pub(crate) fn provide(providers: &mut Providers) {
-    *providers = Providers { check_mod_const_bodies, ..*providers };
-}
-
-#[derive(Copy, Clone)]
-struct CheckConstVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    const_kind: Option<hir::ConstContext>,
-    def_id: Option<LocalDefId>,
-}
-
-impl<'tcx> CheckConstVisitor<'tcx> {
-    fn new(tcx: TyCtxt<'tcx>) -> Self {
-        CheckConstVisitor { tcx, const_kind: None, def_id: None }
-    }
-
-    /// Emits an error when an unsupported expression is found in a const context.
-    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
-    fn const_check_violated(&self, expr: NonConstExpr, span: Span) {
-        let Self { tcx, def_id, const_kind } = *self;
-
-        let features = tcx.features();
-        let required_gates = expr.required_feature_gates();
-
-        let is_feature_allowed = |feature_gate| {
-            // All features require that the corresponding gate be enabled,
-            // even if the function has `#[rustc_allow_const_fn_unstable(the_gate)]`.
-            if !tcx.features().enabled(feature_gate) {
-                return false;
-            }
-
-            // If `def_id` is `None`, we don't need to consider stability attributes.
-            let def_id = match def_id {
-                Some(x) => x,
-                None => return true,
-            };
-
-            // If the function belongs to a trait, then it must enable the const_trait_impl
-            // feature to use that trait function (with a const default body).
-            if tcx.trait_of_item(def_id.to_def_id()).is_some() {
-                return true;
-            }
-
-            // If this crate is not using stability attributes, or this function is not claiming to be a
-            // stable `const fn`, that is all that is required.
-            if !tcx.features().staged_api() || tcx.has_attr(def_id, sym::rustc_const_unstable) {
-                return true;
-            }
-
-            // However, we cannot allow stable `const fn`s to use unstable features without an explicit
-            // opt-in via `rustc_allow_const_fn_unstable`.
-            let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(def_id));
-            attr::rustc_allow_const_fn_unstable(tcx.sess, attrs).any(|name| name == feature_gate)
-        };
-
-        match required_gates {
-            // Don't emit an error if the user has enabled the requisite feature gates.
-            Some(gates) if gates.iter().copied().all(is_feature_allowed) => return,
-
-            // `-Zunleash-the-miri-inside-of-you` only works for expressions that don't have a
-            // corresponding feature gate. This encourages nightly users to use feature gates when
-            // possible.
-            None if tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you => {
-                tcx.dcx().emit_warn(SkippingConstChecks { span });
-                return;
-            }
-
-            _ => {}
-        }
-
-        let const_kind =
-            const_kind.expect("`const_check_violated` may only be called inside a const context");
-
-        let required_gates = required_gates.unwrap_or(&[]);
-        let missing_gates: Vec<_> =
-            required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect();
-
-        match missing_gates.as_slice() {
-            [] => {
-                span_bug!(
-                    span,
-                    "we should not have reached this point, since `.await` is denied earlier"
-                );
-            }
-
-            [missing_primary, ref missing_secondary @ ..] => {
-                let msg =
-                    format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name());
-                let mut err = feature_err(&tcx.sess, *missing_primary, span, msg);
-
-                // If multiple feature gates would be required to enable this expression, include
-                // them as help messages. Don't emit a separate error for each missing feature gate.
-                //
-                // FIXME(ecstaticmorse): Maybe this could be incorporated into `feature_err`? This
-                // is a pretty narrow case, however.
-                tcx.disabled_nightly_features(
-                    &mut err,
-                    def_id.map(|id| tcx.local_def_id_to_hir_id(id)),
-                    missing_secondary.into_iter().map(|gate| (String::new(), *gate)),
-                );
-
-                err.emit();
-            }
-        }
-    }
-
-    /// Saves the parent `const_kind` before calling `f` and restores it afterwards.
-    fn recurse_into(
-        &mut self,
-        kind: Option<hir::ConstContext>,
-        def_id: Option<LocalDefId>,
-        f: impl FnOnce(&mut Self),
-    ) {
-        let parent_def_id = self.def_id;
-        let parent_kind = self.const_kind;
-        self.def_id = def_id;
-        self.const_kind = kind;
-        f(self);
-        self.def_id = parent_def_id;
-        self.const_kind = parent_kind;
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
-    type NestedFilter = nested_filter::OnlyBodies;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
-    }
-
-    fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
-        let kind = Some(hir::ConstContext::Const { inline: false });
-        self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
-    }
-
-    fn visit_inline_const(&mut self, block: &'tcx hir::ConstBlock) {
-        let kind = Some(hir::ConstContext::Const { inline: true });
-        self.recurse_into(kind, None, |this| intravisit::walk_inline_const(this, block));
-    }
-
-    fn visit_body(&mut self, body: &hir::Body<'tcx>) {
-        let owner = self.tcx.hir().body_owner_def_id(body.id());
-        let kind = self.tcx.hir().body_const_context(owner);
-        self.recurse_into(kind, Some(owner), |this| intravisit::walk_body(this, body));
-    }
-
-    fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
-        match &e.kind {
-            // Skip the following checks if we are not currently in a const context.
-            _ if self.const_kind.is_none() => {}
-
-            hir::ExprKind::Loop(_, _, source, _) => {
-                self.const_check_violated(NonConstExpr::Loop(*source), e.span);
-            }
-
-            hir::ExprKind::Match(_, _, source) => {
-                let non_const_expr = match source {
-                    // These are handled by `ExprKind::Loop` above.
-                    hir::MatchSource::ForLoopDesugar => None,
-
-                    _ => Some(NonConstExpr::Match(*source)),
-                };
-
-                if let Some(expr) = non_const_expr {
-                    self.const_check_violated(expr, e.span);
-                }
-            }
-
-            _ => {}
-        }
-
-        intravisit::walk_expr(self, e);
-    }
-}
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index fbf25cb476a..fdc7e1bba2f 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1670,13 +1670,6 @@ pub(crate) struct ProcMacroBadSig {
     pub kind: ProcMacroKind,
 }
 
-#[derive(Diagnostic)]
-#[diag(passes_skipping_const_checks)]
-pub(crate) struct SkippingConstChecks {
-    #[primary_span]
-    pub span: Span,
-}
-
 #[derive(LintDiagnostic)]
 #[diag(passes_unreachable_due_to_uninhabited)]
 pub(crate) struct UnreachableDueToUninhabited<'desc, 'tcx> {
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 8f53b71319d..1aa077ad2bb 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -19,7 +19,6 @@ use rustc_middle::query::Providers;
 
 pub mod abi_test;
 mod check_attr;
-mod check_const;
 pub mod dead;
 mod debugger_visualizer;
 mod diagnostic_items;
@@ -43,7 +42,6 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
 pub fn provide(providers: &mut Providers) {
     check_attr::provide(providers);
-    check_const::provide(providers);
     dead::provide(providers);
     debugger_visualizer::provide(providers);
     diagnostic_items::provide(providers);
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 663c3ac0045..09f3e848766 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -3113,6 +3113,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             }
         }
 
+        #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
         let existing_name = match &in_scope_lifetimes[..] {
             [] => Symbol::intern("'a"),
             [(existing, _)] => existing.name,
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 094871ad268..ca4adce37ce 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -2257,7 +2257,7 @@ fn module_to_string(module: Module<'_>) -> Option<String> {
                 collect_mod(names, parent);
             }
         } else {
-            names.push(Symbol::intern("<opaque>"));
+            names.push(sym::opaque_module_name_placeholder);
             collect_mod(names, module.parent.unwrap());
         }
     }
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 02e255d7726..65128ceb866 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -220,9 +220,9 @@ pub fn attrs_to_doc_fragments<'a>(
 
 fn span_for_value(attr: &ast::Attribute) -> Span {
     if let ast::AttrKind::Normal(normal) = &attr.kind
-        && let ast::AttrArgs::Eq(_, ast::AttrArgsEq::Hir(meta)) = &normal.item.args
+        && let ast::AttrArgs::Eq { value, .. } = &normal.item.args
     {
-        meta.span.with_ctxt(attr.span.ctxt())
+        value.span().with_ctxt(attr.span.ctxt())
     } else {
         attr.span
     }
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 25f75ae12e8..2c0302bbb2b 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1702,6 +1702,8 @@ options! {
         "threshold to allow cross crate inlining of functions"),
     debug_info_for_profiling: bool = (false, parse_bool, [TRACKED],
         "emit discriminators and other data necessary for AutoFDO"),
+    debug_info_type_line_numbers: bool = (false, parse_bool, [TRACKED],
+        "emit type and line information for additional data types (default: no)"),
     debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED],
         "compress debug info sections (none, zlib, zstd, default: none)"),
     deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED],
@@ -2036,8 +2038,6 @@ written to standard error output)"),
         "make the current crate share its generic instantiations"),
     shell_argfiles: bool = (false, parse_bool, [UNTRACKED],
         "allow argument files to be specified with POSIX \"shell-style\" argument quoting"),
-    show_span: Option<String> = (None, parse_opt_string, [TRACKED],
-        "show spans in the crate root file, for compiler debugging (expr|pat|ty)"),
     simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
         "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
         to rust's source base directory. only meant for testing purposes"),
diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs
index 357d746c184..2b2ba50d3fb 100644
--- a/compiler/rustc_session/src/output.rs
+++ b/compiler/rustc_session/src/output.rs
@@ -87,7 +87,7 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute]) -> Symbol {
         }
     }
 
-    Symbol::intern("rust_out")
+    sym::rust_out
 }
 
 pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) {
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index f585410adb9..120ae9946ea 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -1358,6 +1358,12 @@ pub struct EarlyDiagCtxt {
     dcx: DiagCtxt,
 }
 
+impl Default for EarlyDiagCtxt {
+    fn default() -> Self {
+        Self::new(ErrorOutputType::default())
+    }
+}
+
 impl EarlyDiagCtxt {
     pub fn new(output: ErrorOutputType) -> Self {
         let emitter = mk_emitter(output);
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index e94c0a5ea6e..47ceab750cf 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -298,6 +298,7 @@ symbols! {
         Return,
         Right,
         Rust,
+        RustaceansAreAwesome,
         RustcDecodable,
         RustcEncodable,
         RwLock,
@@ -316,6 +317,7 @@ symbols! {
         StructuralPartialEq,
         SubdiagMessage,
         Subdiagnostic,
+        SymbolIntern,
         Sync,
         SyncUnsafeCell,
         T,
@@ -377,6 +379,7 @@ symbols! {
         adt_const_params,
         advanced_slice_patterns,
         adx_target_feature,
+        aes,
         aggregate_raw_ptr,
         alias,
         align,
@@ -440,6 +443,7 @@ symbols! {
         associated_types,
         assume,
         assume_init,
+        asterisk: "*",
         async_await,
         async_call,
         async_call_mut,
@@ -468,6 +472,7 @@ symbols! {
         async_for_loop,
         async_iterator,
         async_iterator_poll_next,
+        async_trait_bounds,
         atomic,
         atomic_mod,
         atomics,
@@ -520,6 +525,7 @@ symbols! {
         btreeset_iter,
         builtin_syntax,
         c,
+        c_dash_variadic,
         c_str,
         c_str_literals,
         c_unwind,
@@ -650,6 +656,7 @@ symbols! {
         const_trait_bound_opt_out,
         const_trait_impl,
         const_try,
+        const_ty_placeholder: "<const_ty>",
         constant,
         constructor,
         convert_identity,
@@ -779,6 +786,7 @@ symbols! {
         drop_types_in_const,
         dropck_eyepatch,
         dropck_parametricity,
+        dummy_cgu_name,
         dylib,
         dyn_compatible_for_dispatch,
         dyn_metadata,
@@ -922,6 +930,7 @@ symbols! {
         fmuladdf32,
         fmuladdf64,
         fn_align,
+        fn_body,
         fn_delegation,
         fn_must_use,
         fn_mut,
@@ -962,6 +971,7 @@ symbols! {
         fs_create_dir,
         fsub_algebraic,
         fsub_fast,
+        fsxr,
         full,
         fundamental,
         fused_iterator,
@@ -1385,6 +1395,7 @@ symbols! {
         on,
         on_unimplemented,
         opaque,
+        opaque_module_name_placeholder: "<opaque>",
         open_options_new,
         ops,
         opt_out_copy,
@@ -1654,6 +1665,7 @@ symbols! {
         rust_eh_catch_typeinfo,
         rust_eh_personality,
         rust_logo,
+        rust_out,
         rustc,
         rustc_abi,
         rustc_allocator,
@@ -1776,6 +1788,8 @@ symbols! {
         self_in_typedefs,
         self_struct_ctor,
         semitransparent,
+        sha2,
+        sha3,
         sha512_sm_x86,
         shadow_call_stack,
         shallow,
@@ -1844,6 +1858,7 @@ symbols! {
         simd_reduce_mul_unordered,
         simd_reduce_or,
         simd_reduce_xor,
+        simd_relaxed_fma,
         simd_rem,
         simd_round,
         simd_saturating_add,
@@ -1889,6 +1904,7 @@ symbols! {
         sreg,
         sreg_low16,
         sse,
+        sse2,
         sse4a_target_feature,
         stable,
         staged_api,
@@ -2176,6 +2192,7 @@ symbols! {
         wrapping_sub,
         wreg,
         write_bytes,
+        write_fmt,
         write_macro,
         write_str,
         write_via_move,
@@ -2405,6 +2422,7 @@ impl Symbol {
     }
 
     /// Maps a string to its interned representation.
+    #[rustc_diagnostic_item = "SymbolIntern"]
     pub fn intern(string: &str) -> Self {
         with_session_globals(|session_globals| session_globals.symbol_interner.intern(string))
     }
diff --git a/compiler/rustc_target/src/spec/base/aix.rs b/compiler/rustc_target/src/spec/base/aix.rs
index 1869369b9e3..fe37d313294 100644
--- a/compiler/rustc_target/src/spec/base/aix.rs
+++ b/compiler/rustc_target/src/spec/base/aix.rs
@@ -4,7 +4,7 @@ use crate::spec::{Cc, CodeModel, LinkOutputKind, LinkerFlavor, TargetOptions, cr
 pub(crate) fn opts() -> TargetOptions {
     TargetOptions {
         abi: "vec-extabi".into(),
-        code_model: Some(CodeModel::Small),
+        code_model: Some(CodeModel::Large),
         cpu: "pwr7".into(),
         os: "aix".into(),
         vendor: "ibm".into(),
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 9b969dd3e43..90b18253629 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -794,7 +794,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     closure_def_id,
                     found_kind,
                     expected_kind,
-                    "async ",
+                    "Async",
                 );
                 self.note_obligation_cause(&mut err, &obligation);
                 self.point_at_returns_when_relevant(&mut err, &obligation);
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
index 7f42c932fcf..f10314c1c9e 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
@@ -1,7 +1,7 @@
 use std::iter;
 use std::path::PathBuf;
 
-use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, MetaItemInner};
+use rustc_ast::{AttrArgs, AttrKind, Attribute, MetaItemInner};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::codes::*;
 use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
@@ -639,8 +639,7 @@ impl<'tcx> OnUnimplementedDirective {
                 let report_span = match &item.args {
                     AttrArgs::Empty => item.path.span,
                     AttrArgs::Delimited(args) => args.dspan.entire(),
-                    AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => eq_span.to(expr.span),
-                    AttrArgs::Eq(span, AttrArgsEq::Hir(expr)) => span.to(expr.span),
+                    AttrArgs::Eq { eq_span, value } => eq_span.to(value.span()),
                 };
 
                 if let Some(item_def_id) = item_def_id.as_local() {
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index 43244eb5dcb..ee708564a80 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -35,7 +35,7 @@ impl<'tcx> InferCtxt<'tcx> {
         // FIXME(#132279): This should be removed as it causes us to incorrectly
         // handle opaques in their defining scope.
         if !(param_env, ty).has_infer() {
-            return ty.is_copy_modulo_regions(self.tcx, self.typing_env(param_env));
+            return self.tcx.type_is_copy_modulo_regions(self.typing_env(param_env), ty);
         }
 
         let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None);
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 0f90c45d032..2b2623a050e 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -199,6 +199,10 @@ where
         errors
     }
 
+    fn has_pending_obligations(&self) -> bool {
+        !self.obligations.pending.is_empty() || !self.obligations.overflowed.is_empty()
+    }
+
     fn pending_obligations(&self) -> PredicateObligations<'tcx> {
         self.obligations.clone_pending()
     }
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index e0a9ddf1876..c9297027519 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -18,7 +18,6 @@ use rustc_middle::ty::{
     TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
 };
 use rustc_span::Span;
-use rustc_span::symbol::Symbol;
 use smallvec::SmallVec;
 use tracing::{debug, instrument};
 
@@ -329,10 +328,7 @@ pub fn dyn_compatibility_violations_for_assoc_item(
             .collect(),
         // Associated types can only be dyn-compatible if they have `Self: Sized` bounds.
         ty::AssocKind::Type => {
-            if !tcx.features().generic_associated_types_extended()
-                && !tcx.generics_of(item.def_id).is_own_empty()
-                && !item.is_impl_trait_in_trait()
-            {
+            if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() {
                 vec![DynCompatibilityViolation::GAT(item.name, item.ident(tcx).span)]
             } else {
                 // We will permit associated types if they are explicitly mentioned in the trait object.
@@ -679,7 +675,7 @@ fn receiver_is_dispatchable<'tcx>(
     // FIXME(mikeyhew) this is a total hack. Once dyn_compatible_for_dispatch is stabilized, we can
     // replace this with `dyn Trait`
     let unsized_self_ty: Ty<'tcx> =
-        Ty::new_param(tcx, u32::MAX, Symbol::intern("RustaceansAreAwesome"));
+        Ty::new_param(tcx, u32::MAX, rustc_span::sym::RustaceansAreAwesome);
 
     // `Receiver[Self => U]`
     let unsized_receiver_ty =
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 03e483f555d..7529ee128f5 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -213,6 +213,10 @@ where
         }
     }
 
+    fn has_pending_obligations(&self) -> bool {
+        self.predicates.has_pending_obligations()
+    }
+
     fn pending_obligations(&self) -> PredicateObligations<'tcx> {
         self.predicates.map_pending_obligations(|o| o.obligation.clone())
     }
diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs
index e99c5eacbd8..ad62b456ad4 100644
--- a/compiler/rustc_trait_selection/src/traits/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/normalize.rs
@@ -7,6 +7,7 @@ use rustc_infer::traits::{
     FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine,
 };
 use rustc_macros::extension;
+use rustc_middle::span_bug;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::{
     self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt,
@@ -63,10 +64,18 @@ impl<'tcx> At<'_, 'tcx> {
         if self.infcx.next_trait_solver() {
             crate::solve::deeply_normalize(self, value)
         } else {
+            if fulfill_cx.has_pending_obligations() {
+                let pending_obligations = fulfill_cx.pending_obligations();
+                span_bug!(
+                    pending_obligations[0].cause.span,
+                    "deeply_normalize should not be called with pending obligations: \
+                    {pending_obligations:#?}"
+                );
+            }
             let value = self
                 .normalize(value)
                 .into_value_registering_obligations(self.infcx, &mut *fulfill_cx);
-            let errors = fulfill_cx.select_where_possible(self.infcx);
+            let errors = fulfill_cx.select_all_or_error(self.infcx);
             let value = self.infcx.resolve_vars_if_possible(value);
             if errors.is_empty() { Ok(value) } else { Err(errors) }
         }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 01f6cccb375..49c34550f8e 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -14,7 +14,7 @@ use rustc_middle::traits::select::OverflowError;
 use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData};
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt};
+use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, Term, Ty, TyCtxt, TypingMode, Upcast};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::sym;
@@ -179,35 +179,11 @@ pub(super) fn poly_project_and_unify_term<'cx, 'tcx>(
 ) -> ProjectAndUnifyResult<'tcx> {
     let infcx = selcx.infcx;
     let r = infcx.commit_if_ok(|_snapshot| {
-        let old_universe = infcx.universe();
         let placeholder_predicate = infcx.enter_forall_and_leak_universe(obligation.predicate);
-        let new_universe = infcx.universe();
 
         let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate);
         match project_and_unify_term(selcx, &placeholder_obligation) {
             ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e),
-            ProjectAndUnifyResult::Holds(obligations)
-                if old_universe != new_universe
-                    && selcx.tcx().features().generic_associated_types_extended() =>
-            {
-                // If the `generic_associated_types_extended` feature is active, then we ignore any
-                // obligations references lifetimes from any universe greater than or equal to the
-                // universe just created. Otherwise, we can end up with something like `for<'a> I: 'a`,
-                // which isn't quite what we want. Ideally, we want either an implied
-                // `for<'a where I: 'a> I: 'a` or we want to "lazily" check these hold when we
-                // instantiate concrete regions. There is design work to be done here; until then,
-                // however, this allows experimenting potential GAT features without running into
-                // well-formedness issues.
-                let new_obligations = obligations
-                    .into_iter()
-                    .filter(|obligation| {
-                        let mut visitor = MaxUniverse::new();
-                        obligation.predicate.visit_with(&mut visitor);
-                        visitor.max_universe() < new_universe
-                    })
-                    .collect();
-                Ok(ProjectAndUnifyResult::Holds(new_obligations))
-            }
             other => Ok(other),
         }
     });
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index c6e41e57f0c..fe47e837dfb 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -59,12 +59,16 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     ty: Ty<'tcx>,
 ) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> {
-    let normalize_op = |ty| {
-        let ty = ocx.normalize(&ObligationCause::dummy(), param_env, ty);
+    let normalize_op = |ty| -> Result<_, NoSolution> {
+        // We must normalize the type so we can compute the right outlives components.
+        // for example, if we have some constrained param type like `T: Trait<Out = U>`,
+        // and we know that `&'a T::Out` is WF, then we want to imply `U: 'a`.
+        let ty = ocx
+            .deeply_normalize(&ObligationCause::dummy(), param_env, ty)
+            .map_err(|_| NoSolution)?;
         if !ocx.select_all_or_error().is_empty() {
             return Err(NoSolution);
         }
-        let ty = ocx.infcx.resolve_vars_if_possible(ty);
         let ty = OpportunisticRegionResolver::new(&ocx.infcx).fold_ty(ty);
         Ok(ty)
     };
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 712856e6a8f..19b4125e75c 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -626,7 +626,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         for assoc_type in assoc_types {
             let defs: &ty::Generics = tcx.generics_of(assoc_type);
 
-            if !defs.own_params.is_empty() && !tcx.features().generic_associated_types_extended() {
+            if !defs.own_params.is_empty() {
                 tcx.dcx().span_delayed_bug(
                     obligation.cause.span,
                     "GATs in trait object shouldn't have been considered",
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 50c4f9eff6f..41a35c31fe4 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1543,14 +1543,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         if self.can_use_global_caches(param_env, cache_fresh_trait_pred) {
             if let Some(res) = tcx.selection_cache.get(&(infcx.typing_env(param_env), pred), tcx) {
-                Some(res)
-            } else {
-                debug_assert_eq!(infcx.selection_cache.get(&(param_env, pred), tcx), None);
-                None
+                return Some(res);
+            } else if cfg!(debug_assertions) {
+                match infcx.selection_cache.get(&(param_env, pred), tcx) {
+                    None | Some(Err(Overflow(OverflowError::Canonical))) => {}
+                    res => bug!("unexpected local cache result: {res:?}"),
+                }
             }
-        } else {
-            infcx.selection_cache.get(&(param_env, pred), tcx)
         }
+
+        // Subtle: we need to check the local cache even if we're able to use the
+        // global cache as we don't cache overflow in the global cache but need to
+        // cache it as otherwise rustdoc hangs when compiling diesel.
+        infcx.selection_cache.get(&(param_env, pred), tcx)
     }
 
     /// Determines whether can we safely cache the result
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index a9cd705465e..1430cfae51f 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -15,6 +15,7 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::codes::*;
 use rustc_errors::{Diag, EmissionGuarantee};
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_infer::traits::Obligation;
 use rustc_middle::bug;
 use rustc_middle::query::LocalCrate;
 use rustc_middle::ty::print::PrintTraitRefExt as _;
@@ -224,21 +225,30 @@ pub(super) fn specialization_enabled_in(tcx: TyCtxt<'_>, _: LocalCrate) -> bool
     tcx.features().specialization() || tcx.features().min_specialization()
 }
 
-/// Is `impl1` a specialization of `impl2`?
+/// Is `specializing_impl_def_id` a specialization of `parent_impl_def_id`?
 ///
-/// Specialization is determined by the sets of types to which the impls apply;
-/// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies
-/// to.
+/// For every type that could apply to `specializing_impl_def_id`, we prove that
+/// the `parent_impl_def_id` also applies (i.e. it has a valid impl header and
+/// its where-clauses hold).
+///
+/// For the purposes of const traits, we also check that the specializing
+/// impl is not more restrictive than the parent impl. That is, if the
+/// `parent_impl_def_id` is a const impl (conditionally based off of some `~const`
+/// bounds), then `specializing_impl_def_id` must also be const for the same
+/// set of types.
 #[instrument(skip(tcx), level = "debug")]
-pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool {
+pub(super) fn specializes(
+    tcx: TyCtxt<'_>,
+    (specializing_impl_def_id, parent_impl_def_id): (DefId, DefId),
+) -> bool {
     // We check that the specializing impl comes from a crate that has specialization enabled,
     // or if the specializing impl is marked with `allow_internal_unstable`.
     //
     // We don't really care if the specialized impl (the parent) is in a crate that has
     // specialization enabled, since it's not being specialized, and it's already been checked
     // for coherence.
-    if !tcx.specialization_enabled_in(impl1_def_id.krate) {
-        let span = tcx.def_span(impl1_def_id);
+    if !tcx.specialization_enabled_in(specializing_impl_def_id.krate) {
+        let span = tcx.def_span(specializing_impl_def_id);
         if !span.allows_unstable(sym::specialization)
             && !span.allows_unstable(sym::min_specialization)
         {
@@ -246,7 +256,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
         }
     }
 
-    let impl1_trait_header = tcx.impl_trait_header(impl1_def_id).unwrap();
+    let specializing_impl_trait_header = tcx.impl_trait_header(specializing_impl_def_id).unwrap();
 
     // We determine whether there's a subset relationship by:
     //
@@ -261,27 +271,123 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
     // See RFC 1210 for more details and justification.
 
     // Currently we do not allow e.g., a negative impl to specialize a positive one
-    if impl1_trait_header.polarity != tcx.impl_polarity(impl2_def_id) {
+    if specializing_impl_trait_header.polarity != tcx.impl_polarity(parent_impl_def_id) {
         return false;
     }
 
-    // create a parameter environment corresponding to an identity instantiation of impl1,
-    // i.e. the most generic instantiation of impl1.
-    let param_env = tcx.param_env(impl1_def_id);
+    // create a parameter environment corresponding to an identity instantiation of the specializing impl,
+    // i.e. the most generic instantiation of the specializing impl.
+    let param_env = tcx.param_env(specializing_impl_def_id);
 
-    // Create an infcx, taking the predicates of impl1 as assumptions:
+    // Create an infcx, taking the predicates of the specializing impl as assumptions:
     let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
 
-    // Attempt to prove that impl2 applies, given all of the above.
-    fulfill_implication(
-        &infcx,
+    let specializing_impl_trait_ref =
+        specializing_impl_trait_header.trait_ref.instantiate_identity();
+    let cause = &ObligationCause::dummy();
+    debug!(
+        "fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)",
+        param_env, specializing_impl_trait_ref, parent_impl_def_id
+    );
+
+    // Attempt to prove that the parent impl applies, given all of the above.
+
+    let ocx = ObligationCtxt::new(&infcx);
+    let specializing_impl_trait_ref = ocx.normalize(cause, param_env, specializing_impl_trait_ref);
+
+    if !ocx.select_all_or_error().is_empty() {
+        infcx.dcx().span_delayed_bug(
+            infcx.tcx.def_span(specializing_impl_def_id),
+            format!("failed to fully normalize {specializing_impl_trait_ref}"),
+        );
+        return false;
+    }
+
+    let parent_args = infcx.fresh_args_for_item(DUMMY_SP, parent_impl_def_id);
+    let parent_impl_trait_ref = ocx.normalize(
+        cause,
         param_env,
-        impl1_trait_header.trait_ref.instantiate_identity(),
-        impl1_def_id,
-        impl2_def_id,
-        &ObligationCause::dummy(),
-    )
-    .is_ok()
+        infcx
+            .tcx
+            .impl_trait_ref(parent_impl_def_id)
+            .expect("expected source impl to be a trait impl")
+            .instantiate(infcx.tcx, parent_args),
+    );
+
+    // do the impls unify? If not, no specialization.
+    let Ok(()) = ocx.eq(cause, param_env, specializing_impl_trait_ref, parent_impl_trait_ref)
+    else {
+        return false;
+    };
+
+    // Now check that the source trait ref satisfies all the where clauses of the target impl.
+    // This is not just for correctness; we also need this to constrain any params that may
+    // only be referenced via projection predicates.
+    let predicates = ocx.normalize(
+        cause,
+        param_env,
+        infcx.tcx.predicates_of(parent_impl_def_id).instantiate(infcx.tcx, parent_args),
+    );
+    let obligations = predicates_for_generics(|_, _| cause.clone(), param_env, predicates);
+    ocx.register_obligations(obligations);
+
+    let errors = ocx.select_all_or_error();
+    if !errors.is_empty() {
+        // no dice!
+        debug!(
+            "fulfill_implication: for impls on {:?} and {:?}, \
+                 could not fulfill: {:?} given {:?}",
+            specializing_impl_trait_ref,
+            parent_impl_trait_ref,
+            errors,
+            param_env.caller_bounds()
+        );
+        return false;
+    }
+
+    // If the parent impl is const, then the specializing impl must be const,
+    // and it must not be *more restrictive* than the parent impl (that is,
+    // it cannot be const in fewer cases than the parent impl).
+    if tcx.is_conditionally_const(parent_impl_def_id) {
+        if !tcx.is_conditionally_const(specializing_impl_def_id) {
+            return false;
+        }
+
+        let const_conditions = ocx.normalize(
+            cause,
+            param_env,
+            infcx.tcx.const_conditions(parent_impl_def_id).instantiate(infcx.tcx, parent_args),
+        );
+        ocx.register_obligations(const_conditions.into_iter().map(|(trait_ref, _)| {
+            Obligation::new(
+                infcx.tcx,
+                cause.clone(),
+                param_env,
+                trait_ref.to_host_effect_clause(infcx.tcx, ty::BoundConstness::Maybe),
+            )
+        }));
+
+        let errors = ocx.select_all_or_error();
+        if !errors.is_empty() {
+            // no dice!
+            debug!(
+                "fulfill_implication: for impls on {:?} and {:?}, \
+                 could not fulfill: {:?} given {:?}",
+                specializing_impl_trait_ref,
+                parent_impl_trait_ref,
+                errors,
+                param_env.caller_bounds()
+            );
+            return false;
+        }
+    }
+
+    debug!(
+        "fulfill_implication: an impl for {:?} specializes {:?}",
+        specializing_impl_trait_ref, parent_impl_trait_ref
+    );
+
+    true
 }
 
 /// Query provider for `specialization_graph_of`.
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index f19a567cd84..83463babc4f 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -319,38 +319,35 @@ pub(crate) mod rustc {
         ) -> Result<Self, Err> {
             assert!(def.is_enum());
 
-            // Computes the variant of a given index.
-            let layout_of_variant = |index, encoding: Option<TagEncoding<VariantIdx>>| {
-                let tag = cx.tcx().tag_for_variant((cx.tcx().erase_regions(ty), index));
-                let variant_def = Def::Variant(def.variant(index));
-                let variant_layout = ty_variant(cx, (ty, layout), index);
-                Self::from_variant(
-                    variant_def,
-                    tag.map(|tag| (tag, index, encoding.unwrap())),
-                    (ty, variant_layout),
-                    layout.size,
-                    cx,
-                )
-            };
+            // Computes the layout of a variant.
+            let layout_of_variant =
+                |index, encoding: Option<TagEncoding<VariantIdx>>| -> Result<Self, Err> {
+                    let variant_layout = ty_variant(cx, (ty, layout), index);
+                    if variant_layout.is_uninhabited() {
+                        return Ok(Self::uninhabited());
+                    }
+                    let tag = cx.tcx().tag_for_variant((cx.tcx().erase_regions(ty), index));
+                    let variant_def = Def::Variant(def.variant(index));
+                    Self::from_variant(
+                        variant_def,
+                        tag.map(|tag| (tag, index, encoding.unwrap())),
+                        (ty, variant_layout),
+                        layout.size,
+                        cx,
+                    )
+                };
 
-            // We consider three kinds of enums, each demanding a different
-            // treatment of their layout computation:
-            // 1. enums that are uninhabited ZSTs
-            // 2. enums that delegate their layout to a variant
-            // 3. enums with multiple variants
             match layout.variants() {
-                Variants::Single { .. } if layout.is_uninhabited() && layout.size == Size::ZERO => {
-                    // The layout representation of uninhabited, ZST enums is
-                    // defined to be like that of the `!` type, as opposed of a
-                    // typical enum. Consequently, they cannot be descended into
-                    // as if they typical enums. We therefore special-case this
-                    // scenario and simply return an uninhabited `Tree`.
-                    Ok(Self::uninhabited())
-                }
                 Variants::Single { index } => {
-                    // `Variants::Single` on enums with variants denotes that
-                    // the enum delegates its layout to the variant at `index`.
-                    layout_of_variant(*index, None)
+                    // Hilariously, `Single` is used even for 0-variant enums;
+                    // `index` is just junk in that case.
+                    if ty.ty_adt_def().unwrap().variants().is_empty() {
+                        Ok(Self::uninhabited())
+                    } else {
+                        // `Variants::Single` on enums with variants denotes that
+                        // the enum delegates its layout to the variant at `index`.
+                        layout_of_variant(*index, None)
+                    }
                 }
                 Variants::Multiple { tag, tag_encoding, tag_field, .. } => {
                     // `Variants::Multiple` denotes an enum with multiple
@@ -369,7 +366,7 @@ pub(crate) mod rustc {
                         },
                     )?;
 
-                    return Ok(Self::def(Def::Adt(def)).then(variants));
+                    Ok(Self::def(Def::Adt(def)).then(variants))
                 }
             }
         }
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 66134b81b2a..0d656f1b63b 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -81,7 +81,7 @@ fn layout_of<'tcx>(
         record_layout_for_printing(&cx, layout);
     }
 
-    invariant::partially_check_layout(&cx, &layout);
+    invariant::layout_sanity_check(&cx, &layout);
 
     Ok(layout)
 }
diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs
index 26ea81daf78..f39b87622f4 100644
--- a/compiler/rustc_ty_utils/src/layout/invariant.rs
+++ b/compiler/rustc_ty_utils/src/layout/invariant.rs
@@ -1,11 +1,11 @@
 use std::assert_matches::assert_matches;
 
-use rustc_abi::{BackendRepr, FieldsShape, Scalar, Size, Variants};
+use rustc_abi::{BackendRepr, FieldsShape, Scalar, Size, TagEncoding, Variants};
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, TyAndLayout};
 
 /// Enforce some basic invariants on layouts.
-pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) {
+pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) {
     let tcx = cx.tcx();
 
     // Type-level uninhabitedness should always imply ABI uninhabitedness.
@@ -241,7 +241,17 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
 
     check_layout_abi(cx, layout);
 
-    if let Variants::Multiple { variants, .. } = &layout.variants {
+    if let Variants::Multiple { variants, tag, tag_encoding, .. } = &layout.variants {
+        if let TagEncoding::Niche { niche_start, untagged_variant, niche_variants } = tag_encoding {
+            let niche_size = tag.size(cx);
+            assert!(*niche_start <= niche_size.unsigned_int_max());
+            for (idx, variant) in variants.iter_enumerated() {
+                // Ensure all inhabited variants are accounted for.
+                if !variant.is_uninhabited() {
+                    assert!(idx == *untagged_variant || niche_variants.contains(&idx));
+                }
+            }
+        }
         for variant in variants.iter() {
             // No nested "multiple".
             assert_matches!(variant.variants, Variants::Single { .. });
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index d85da7d355e..1c85eb2a861 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -202,7 +202,7 @@ where
                         }
                     }
 
-                    _ if component.is_copy_modulo_regions(tcx, self.typing_env) => {}
+                    _ if tcx.type_is_copy_modulo_regions(self.typing_env, component) => {}
 
                     ty::Closure(_, args) => {
                         for upvar in args.as_closure().upvar_tys() {
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index c739832bc78..9c074383a5e 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -384,7 +384,7 @@ impl CString {
     ///     fn some_extern_function(s: *mut c_char);
     /// }
     ///
-    /// let c_string = CString::new("Hello!").expect("CString::new failed");
+    /// let c_string = CString::from(c"Hello!");
     /// let raw = c_string.into_raw();
     /// unsafe {
     ///     some_extern_function(raw);
@@ -429,7 +429,7 @@ impl CString {
     /// ```
     /// use std::ffi::CString;
     ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
+    /// let c_string = CString::from(c"foo");
     ///
     /// let ptr = c_string.into_raw();
     ///
@@ -487,7 +487,7 @@ impl CString {
     /// ```
     /// use std::ffi::CString;
     ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
+    /// let c_string = CString::from(c"foo");
     /// let bytes = c_string.into_bytes();
     /// assert_eq!(bytes, vec![b'f', b'o', b'o']);
     /// ```
@@ -508,7 +508,7 @@ impl CString {
     /// ```
     /// use std::ffi::CString;
     ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
+    /// let c_string = CString::from(c"foo");
     /// let bytes = c_string.into_bytes_with_nul();
     /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']);
     /// ```
@@ -530,7 +530,7 @@ impl CString {
     /// ```
     /// use std::ffi::CString;
     ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
+    /// let c_string = CString::from(c"foo");
     /// let bytes = c_string.as_bytes();
     /// assert_eq!(bytes, &[b'f', b'o', b'o']);
     /// ```
@@ -550,7 +550,7 @@ impl CString {
     /// ```
     /// use std::ffi::CString;
     ///
-    /// let c_string = CString::new("foo").expect("CString::new failed");
+    /// let c_string = CString::from(c"foo");
     /// let bytes = c_string.as_bytes_with_nul();
     /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']);
     /// ```
@@ -568,7 +568,7 @@ impl CString {
     /// ```
     /// use std::ffi::{CString, CStr};
     ///
-    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
+    /// let c_string = CString::from(c"foo");
     /// let cstr = c_string.as_c_str();
     /// assert_eq!(cstr,
     ///            CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
@@ -586,12 +586,9 @@ impl CString {
     /// # Examples
     ///
     /// ```
-    /// use std::ffi::{CString, CStr};
-    ///
-    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
+    /// let c_string = c"foo".to_owned();
     /// let boxed = c_string.into_boxed_c_str();
-    /// assert_eq!(&*boxed,
-    ///            CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
+    /// assert_eq!(boxed.to_bytes_with_nul(), b"foo\0");
     /// ```
     #[must_use = "`self` will be dropped if the result is not used"]
     #[stable(feature = "into_boxed_c_str", since = "1.20.0")]
@@ -658,7 +655,7 @@ impl CString {
     /// assert_eq!(
     ///     CString::from_vec_with_nul(b"abc\0".to_vec())
     ///         .expect("CString::from_vec_with_nul failed"),
-    ///     CString::new(b"abc".to_vec()).expect("CString::new failed")
+    ///     c"abc".to_owned()
     /// );
     /// ```
     ///
@@ -1168,11 +1165,12 @@ impl CStr {
     /// # Examples
     ///
     /// ```
-    /// use std::ffi::CString;
+    /// use std::ffi::{CStr, CString};
     ///
-    /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
-    /// let boxed = c_string.into_boxed_c_str();
-    /// assert_eq!(boxed.into_c_string(), CString::new("foo").expect("CString::new failed"));
+    /// let boxed: Box<CStr> = Box::from(c"foo");
+    /// let c_string: CString = c"foo".to_owned();
+    ///
+    /// assert_eq!(boxed.into_c_string(), c_string);
     /// ```
     #[rustc_allow_incoherent_impl]
     #[must_use = "`self` will be dropped if the result is not used"]
diff --git a/library/alloc/src/ffi/c_str/tests.rs b/library/alloc/src/ffi/c_str/tests.rs
index 8b7172b3f20..d6b797347c2 100644
--- a/library/alloc/src/ffi/c_str/tests.rs
+++ b/library/alloc/src/ffi/c_str/tests.rs
@@ -159,7 +159,7 @@ fn boxed_default() {
 
 #[test]
 fn test_c_str_clone_into() {
-    let mut c_string = CString::new("lorem").unwrap();
+    let mut c_string = c"lorem".to_owned();
     let c_ptr = c_string.as_ptr();
     let c_str = CStr::from_bytes_with_nul(b"ipsum\0").unwrap();
     c_str.clone_into(&mut c_string);
diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs
index 333e1bde31c..2210a7c24c0 100644
--- a/library/alloc/src/rc/tests.rs
+++ b/library/alloc/src/rc/tests.rs
@@ -349,9 +349,9 @@ fn test_unsized() {
 #[test]
 fn test_maybe_thin_unsized() {
     // If/when custom thin DSTs exist, this test should be updated to use one
-    use std::ffi::{CStr, CString};
+    use std::ffi::CStr;
 
-    let x: Rc<CStr> = Rc::from(CString::new("swordfish").unwrap().into_boxed_c_str());
+    let x: Rc<CStr> = Rc::from(c"swordfish");
     assert_eq!(format!("{x:?}"), "\"swordfish\"");
     let y: Weak<CStr> = Rc::downgrade(&x);
     drop(x);
diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs
index 3f66c889923..de5816fda97 100644
--- a/library/alloc/src/sync/tests.rs
+++ b/library/alloc/src/sync/tests.rs
@@ -412,9 +412,9 @@ fn test_unsized() {
 #[test]
 fn test_maybe_thin_unsized() {
     // If/when custom thin DSTs exist, this test should be updated to use one
-    use std::ffi::{CStr, CString};
+    use std::ffi::CStr;
 
-    let x: Arc<CStr> = Arc::from(CString::new("swordfish").unwrap().into_boxed_c_str());
+    let x: Arc<CStr> = Arc::from(c"swordfish");
     assert_eq!(format!("{x:?}"), "\"swordfish\"");
     let y: Weak<CStr> = Arc::downgrade(&x);
     drop(x);
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs
index 60936da2e0b..d884fa69efb 100644
--- a/library/core/src/alloc/layout.rs
+++ b/library/core/src/alloc/layout.rs
@@ -179,6 +179,7 @@ impl Layout {
     /// or other unsized type like a slice).
     #[stable(feature = "alloc_layout", since = "1.28.0")]
     #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
+    #[rustc_const_stable_indirect]
     #[must_use]
     #[inline]
     pub const fn for_value<T: ?Sized>(t: &T) -> Self {
@@ -215,7 +216,6 @@ impl Layout {
     /// [trait object]: ../../book/ch17-02-trait-objects.html
     /// [extern type]: ../../unstable-book/language-features/extern-types.html
     #[unstable(feature = "layout_for_ptr", issue = "69835")]
-    #[rustc_const_unstable(feature = "layout_for_ptr", issue = "69835")]
     #[must_use]
     pub const unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self {
         // SAFETY: we pass along the prerequisites of these functions to the caller
diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs
index 57f456c98b3..95d88c7f679 100644
--- a/library/core/src/arch.rs
+++ b/library/core/src/arch.rs
@@ -42,3 +42,30 @@ pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?)
 pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) {
     /* compiler built-in */
 }
+
+/// Compiles to a target-specific software breakpoint instruction or equivalent.
+///
+/// This will typically abort the program. It may result in a core dump, and/or the system logging
+/// debug information. Additional target-specific capabilities may be possible depending on
+/// debuggers or other tooling; in particular, a debugger may be able to resume execution.
+///
+/// If possible, this will produce an instruction sequence that allows a debugger to resume *after*
+/// the breakpoint, rather than resuming *at* the breakpoint; however, the exact behavior is
+/// target-specific and debugger-specific, and not guaranteed.
+///
+/// If the target platform does not have any kind of debug breakpoint instruction, this may compile
+/// to a trapping instruction (e.g. an undefined instruction) instead, or to some other form of
+/// target-specific abort that may or may not support convenient resumption.
+///
+/// The precise behavior and the precise instruction generated are not guaranteed, except that in
+/// normal execution with no debug tooling involved this will not continue executing.
+///
+/// - On x86 targets, this produces an `int3` instruction.
+/// - On aarch64 targets, this produces a `brk #0xf000` instruction.
+// When stabilizing this, update the comment on `core::intrinsics::breakpoint`.
+#[unstable(feature = "breakpoint", issue = "133724")]
+#[inline(always)]
+#[cfg(not(bootstrap))]
+pub fn breakpoint() {
+    core::intrinsics::breakpoint();
+}
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index 061690e88dd..84bbf985e8b 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -752,10 +752,10 @@ pub struct BuildHasherDefault<H>(marker::PhantomData<fn() -> H>);
 
 impl<H> BuildHasherDefault<H> {
     /// Creates a new BuildHasherDefault for Hasher `H`.
-    #[unstable(
+    #[stable(feature = "build_hasher_default_const_new", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(
         feature = "build_hasher_default_const_new",
-        issue = "123197",
-        reason = "recently added"
+        since = "CURRENT_RUSTC_VERSION"
     )]
     pub const fn new() -> Self {
         BuildHasherDefault(marker::PhantomData)
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index 46873fdc047..802b571c510 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -1381,6 +1381,18 @@ pub unsafe fn prefetch_write_instruction<T>(_data: *const T, _locality: i32) {
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 #[rustc_nounwind]
+#[cfg(not(bootstrap))]
+pub fn breakpoint() {
+    unreachable!()
+}
+
+/// Executes a breakpoint trap, for inspection by a debugger.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+#[cfg(bootstrap)]
 pub unsafe fn breakpoint() {
     unreachable!()
 }
@@ -4099,6 +4111,7 @@ pub const fn variant_count<T>() -> usize {
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
+#[rustc_intrinsic_const_stable_indirect]
 pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize {
     unreachable!()
 }
@@ -4114,6 +4127,7 @@ pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize {
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
+#[rustc_intrinsic_const_stable_indirect]
 pub const unsafe fn min_align_of_val<T: ?Sized>(_ptr: *const T) -> usize {
     unreachable!()
 }
diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs
index 5ddca9c4dce..0d24b0558c5 100644
--- a/library/core/src/intrinsics/simd.rs
+++ b/library/core/src/intrinsics/simd.rs
@@ -612,6 +612,20 @@ extern "rust-intrinsic" {
     #[rustc_nounwind]
     pub fn simd_fma<T>(x: T, y: T, z: T) -> T;
 
+    /// Computes `(x*y) + z` for each element, non-deterministically executing either
+    /// a fused multiply-add or two operations with rounding of the intermediate result.
+    ///
+    /// The operation is fused if the code generator determines that target instruction
+    /// set has support for a fused operation, and that the fused operation is more efficient
+    /// than the equivalent, separate pair of mul and add instructions. It is unspecified
+    /// whether or not a fused operation is selected, and that may depend on optimization
+    /// level and context, for example.
+    ///
+    /// `T` must be a vector of floats.
+    #[cfg(not(bootstrap))]
+    #[rustc_nounwind]
+    pub fn simd_relaxed_fma<T>(x: T, y: T, z: T) -> T;
+
     // Computes the sine of each element.
     ///
     /// `T` must be a vector of floats.
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 3c1a098374e..9b3d6902098 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -485,9 +485,9 @@ impl<T> MaybeUninit<T> {
     ///     }
     /// }
     /// ```
-    #[stable(feature = "maybe_uninit_write", since = "1.55.0")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_write", issue = "63567")]
     #[inline(always)]
+    #[stable(feature = "maybe_uninit_write", since = "1.55.0")]
+    #[rustc_const_stable(feature = "const_maybe_uninit_write", since = "CURRENT_RUSTC_VERSION")]
     pub const fn write(&mut self, val: T) -> &mut T {
         *self = MaybeUninit::new(val);
         // SAFETY: We just initialized this value.
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 4cf52042a57..78ad6880709 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -333,7 +333,7 @@ pub const fn size_of<T>() -> usize {
 #[inline]
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
+#[rustc_const_stable(feature = "const_size_of_val", since = "CURRENT_RUSTC_VERSION")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of_val")]
 pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
     // SAFETY: `val` is a reference, so it's a valid raw pointer
@@ -390,7 +390,6 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
 #[inline]
 #[must_use]
 #[unstable(feature = "layout_for_ptr", issue = "69835")]
-#[rustc_const_unstable(feature = "const_size_of_val_raw", issue = "46571")]
 pub const unsafe fn size_of_val_raw<T: ?Sized>(val: *const T) -> usize {
     // SAFETY: the caller must provide a valid raw pointer
     unsafe { intrinsics::size_of_val(val) }
@@ -485,7 +484,7 @@ pub const fn align_of<T>() -> usize {
 #[inline]
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
+#[rustc_const_stable(feature = "const_align_of_val", since = "CURRENT_RUSTC_VERSION")]
 #[allow(deprecated)]
 pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
     // SAFETY: val is a reference, so it's a valid raw pointer
@@ -534,7 +533,6 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
 #[inline]
 #[must_use]
 #[unstable(feature = "layout_for_ptr", issue = "69835")]
-#[rustc_const_unstable(feature = "const_align_of_val_raw", issue = "46571")]
 pub const unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize {
     // SAFETY: the caller must provide a valid raw pointer
     unsafe { intrinsics::min_align_of_val(val) }
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index 5e1098c877f..c82f0d7cd4a 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -803,7 +803,7 @@ impl f16 {
     /// ```
     #[inline]
     #[unstable(feature = "f16", issue = "116909")]
-    #[rustc_const_unstable(feature = "f128", issue = "116909")]
+    #[rustc_const_unstable(feature = "f16", issue = "116909")]
     pub const fn midpoint(self, other: f16) -> f16 {
         const LO: f16 = f16::MIN_POSITIVE * 2.;
         const HI: f16 = f16::MAX / 2.;
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index e97af081143..a9294306b1b 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -37,6 +37,8 @@ pub unsafe trait ZeroablePrimitive: Sized + Copy + private::Sealed {
 macro_rules! impl_zeroable_primitive {
     ($($NonZeroInner:ident ( $primitive:ty )),+ $(,)?) => {
         mod private {
+            use super::*;
+
             #[unstable(
                 feature = "nonzero_internals",
                 reason = "implementation detail which may disappear or be replaced at any time",
@@ -45,7 +47,11 @@ macro_rules! impl_zeroable_primitive {
             pub trait Sealed {}
 
             $(
-                #[derive(Debug, Clone, Copy, PartialEq)]
+                // This inner type is never shown directly, so intentionally does not have Debug
+                #[expect(missing_debug_implementations)]
+                // Since this struct is non-generic and derives Copy,
+                // the derived Clone is `*self` and thus doesn't field-project.
+                #[derive(Clone, Copy)]
                 #[repr(transparent)]
                 #[rustc_layout_scalar_valid_range_start(1)]
                 #[rustc_nonnull_optimization_guaranteed]
@@ -55,6 +61,16 @@ macro_rules! impl_zeroable_primitive {
                     issue = "none"
                 )]
                 pub struct $NonZeroInner($primitive);
+
+                // This is required to allow matching a constant.  We don't get it from a derive
+                // because the derived `PartialEq` would do a field projection, which is banned
+                // by <https://github.com/rust-lang/compiler-team/issues/807>.
+                #[unstable(
+                    feature = "nonzero_internals",
+                    reason = "implementation detail which may disappear or be replaced at any time",
+                    issue = "none"
+                )]
+                impl StructuralPartialEq for $NonZeroInner {}
             )+
         }
 
@@ -172,7 +188,7 @@ where
 {
     #[inline]
     fn clone(&self) -> Self {
-        Self(self.0)
+        *self
     }
 }
 
@@ -440,15 +456,21 @@ where
     #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")]
     #[inline]
     pub const fn get(self) -> T {
-        // FIXME: This can be changed to simply `self.0` once LLVM supports `!range` metadata
-        // for function arguments: https://github.com/llvm/llvm-project/issues/76628
-        //
         // Rustc can set range metadata only if it loads `self` from
         // memory somewhere. If the value of `self` was from by-value argument
         // of some not-inlined function, LLVM don't have range metadata
         // to understand that the value cannot be zero.
         //
-        // For now, using the transmute `assume`s the range at runtime.
+        // Using the transmute `assume`s the range at runtime.
+        //
+        // Even once LLVM supports `!range` metadata for function arguments
+        // (see <https://github.com/llvm/llvm-project/issues/76628>), this can't
+        // be `.0` because MCP#807 bans field-projecting into `scalar_valid_range`
+        // types, and it arguably wouldn't want to be anyway because if this is
+        // MIR-inlined, there's no opportunity to put that argument metadata anywhere.
+        //
+        // The good answer here will eventually be pattern types, which will hopefully
+        // allow it to go back to `.0`, maybe with a cast of some sort.
         //
         // SAFETY: `ZeroablePrimitive` guarantees that the size and bit validity
         // of `.0` is such that this transmute is sound.
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index c853db181ce..c79b2f7ad8e 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -2445,7 +2445,7 @@ macro_rules! uint_impl {
             //   to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic
             let (a, b) = self.overflowing_sub(rhs);
             let (c, d) = a.overflowing_sub(borrow as $SelfT);
-            (c, b || d)
+            (c, b | d)
         }
 
         /// Calculates `self` - `rhs` with a signed `rhs`
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index d37b7eedfcb..0ad1cad6914 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -7,7 +7,7 @@ use crate::pin::PinCoerceUnsized;
 use crate::ptr::Unique;
 use crate::slice::{self, SliceIndex};
 use crate::ub_checks::assert_unsafe_precondition;
-use crate::{fmt, hash, intrinsics, ptr};
+use crate::{fmt, hash, intrinsics, mem, ptr};
 
 /// `*mut T` but non-zero and [covariant].
 ///
@@ -69,6 +69,8 @@ use crate::{fmt, hash, intrinsics, ptr};
 #[rustc_nonnull_optimization_guaranteed]
 #[rustc_diagnostic_item = "NonNull"]
 pub struct NonNull<T: ?Sized> {
+    // Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to
+    // this is banned by <https://github.com/rust-lang/compiler-team/issues/807>.
     pointer: *const T,
 }
 
@@ -282,7 +284,7 @@ impl<T: ?Sized> NonNull<T> {
     pub fn addr(self) -> NonZero<usize> {
         // SAFETY: The pointer is guaranteed by the type to be non-null,
         // meaning that the address will be non-zero.
-        unsafe { NonZero::new_unchecked(self.pointer.addr()) }
+        unsafe { NonZero::new_unchecked(self.as_ptr().addr()) }
     }
 
     /// Creates a new pointer with the given address and the [provenance][crate::ptr#provenance] of
@@ -296,7 +298,7 @@ impl<T: ?Sized> NonNull<T> {
     #[stable(feature = "strict_provenance", since = "1.84.0")]
     pub fn with_addr(self, addr: NonZero<usize>) -> Self {
         // SAFETY: The result of `ptr::from::with_addr` is non-null because `addr` is guaranteed to be non-zero.
-        unsafe { NonNull::new_unchecked(self.pointer.with_addr(addr.get()) as *mut _) }
+        unsafe { NonNull::new_unchecked(self.as_ptr().with_addr(addr.get()) as *mut _) }
     }
 
     /// Creates a new pointer by mapping `self`'s address to a new one, preserving the
@@ -335,7 +337,12 @@ impl<T: ?Sized> NonNull<T> {
     #[must_use]
     #[inline(always)]
     pub const fn as_ptr(self) -> *mut T {
-        self.pointer as *mut T
+        // This is a transmute for the same reasons as `NonZero::get`.
+
+        // SAFETY: `NonNull` is `transparent` over a `*const T`, and `*const T`
+        // and `*mut T` have the same layout, so transitively we can transmute
+        // our `NonNull` to a `*mut T` directly.
+        unsafe { mem::transmute::<Self, *mut T>(self) }
     }
 
     /// Returns a shared reference to the value. If the value may be uninitialized, [`as_uninit_ref`]
@@ -484,7 +491,7 @@ impl<T: ?Sized> NonNull<T> {
         // Additionally safety contract of `offset` guarantees that the resulting pointer is
         // pointing to an allocation, there can't be an allocation at null, thus it's safe to
         // construct `NonNull`.
-        unsafe { NonNull { pointer: intrinsics::offset(self.pointer, count) } }
+        unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } }
     }
 
     /// Calculates the offset from a pointer in bytes.
@@ -508,7 +515,7 @@ impl<T: ?Sized> NonNull<T> {
         // Additionally safety contract of `offset` guarantees that the resulting pointer is
         // pointing to an allocation, there can't be an allocation at null, thus it's safe to
         // construct `NonNull`.
-        unsafe { NonNull { pointer: self.pointer.byte_offset(count) } }
+        unsafe { NonNull { pointer: self.as_ptr().byte_offset(count) } }
     }
 
     /// Adds an offset to a pointer (convenience for `.offset(count as isize)`).
@@ -560,7 +567,7 @@ impl<T: ?Sized> NonNull<T> {
         // Additionally safety contract of `offset` guarantees that the resulting pointer is
         // pointing to an allocation, there can't be an allocation at null, thus it's safe to
         // construct `NonNull`.
-        unsafe { NonNull { pointer: intrinsics::offset(self.pointer, count) } }
+        unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } }
     }
 
     /// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`).
@@ -584,7 +591,7 @@ impl<T: ?Sized> NonNull<T> {
         // Additionally safety contract of `add` guarantees that the resulting pointer is pointing
         // to an allocation, there can't be an allocation at null, thus it's safe to construct
         // `NonNull`.
-        unsafe { NonNull { pointer: self.pointer.byte_add(count) } }
+        unsafe { NonNull { pointer: self.as_ptr().byte_add(count) } }
     }
 
     /// Subtracts an offset from a pointer (convenience for
@@ -666,7 +673,7 @@ impl<T: ?Sized> NonNull<T> {
         // Additionally safety contract of `sub` guarantees that the resulting pointer is pointing
         // to an allocation, there can't be an allocation at null, thus it's safe to construct
         // `NonNull`.
-        unsafe { NonNull { pointer: self.pointer.byte_sub(count) } }
+        unsafe { NonNull { pointer: self.as_ptr().byte_sub(count) } }
     }
 
     /// Calculates the distance between two pointers within the same allocation. The returned value is in
@@ -763,7 +770,7 @@ impl<T: ?Sized> NonNull<T> {
         T: Sized,
     {
         // SAFETY: the caller must uphold the safety contract for `offset_from`.
-        unsafe { self.pointer.offset_from(origin.pointer) }
+        unsafe { self.as_ptr().offset_from(origin.as_ptr()) }
     }
 
     /// Calculates the distance between two pointers within the same allocation. The returned value is in
@@ -781,7 +788,7 @@ impl<T: ?Sized> NonNull<T> {
     #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
     pub const unsafe fn byte_offset_from<U: ?Sized>(self, origin: NonNull<U>) -> isize {
         // SAFETY: the caller must uphold the safety contract for `byte_offset_from`.
-        unsafe { self.pointer.byte_offset_from(origin.pointer) }
+        unsafe { self.as_ptr().byte_offset_from(origin.as_ptr()) }
     }
 
     // N.B. `wrapping_offset``, `wrapping_add`, etc are not implemented because they can wrap to null
@@ -856,7 +863,7 @@ impl<T: ?Sized> NonNull<T> {
         T: Sized,
     {
         // SAFETY: the caller must uphold the safety contract for `sub_ptr`.
-        unsafe { self.pointer.sub_ptr(subtracted.pointer) }
+        unsafe { self.as_ptr().sub_ptr(subtracted.as_ptr()) }
     }
 
     /// Calculates the distance between two pointers within the same allocation, *where it's known that
@@ -875,7 +882,7 @@ impl<T: ?Sized> NonNull<T> {
     #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
     pub const unsafe fn byte_sub_ptr<U: ?Sized>(self, origin: NonNull<U>) -> usize {
         // SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`.
-        unsafe { self.pointer.byte_sub_ptr(origin.pointer) }
+        unsafe { self.as_ptr().byte_sub_ptr(origin.as_ptr()) }
     }
 
     /// Reads the value from `self` without moving it. This leaves the
@@ -893,7 +900,7 @@ impl<T: ?Sized> NonNull<T> {
         T: Sized,
     {
         // SAFETY: the caller must uphold the safety contract for `read`.
-        unsafe { ptr::read(self.pointer) }
+        unsafe { ptr::read(self.as_ptr()) }
     }
 
     /// Performs a volatile read of the value from `self` without moving it. This
@@ -914,7 +921,7 @@ impl<T: ?Sized> NonNull<T> {
         T: Sized,
     {
         // SAFETY: the caller must uphold the safety contract for `read_volatile`.
-        unsafe { ptr::read_volatile(self.pointer) }
+        unsafe { ptr::read_volatile(self.as_ptr()) }
     }
 
     /// Reads the value from `self` without moving it. This leaves the
@@ -934,7 +941,7 @@ impl<T: ?Sized> NonNull<T> {
         T: Sized,
     {
         // SAFETY: the caller must uphold the safety contract for `read_unaligned`.
-        unsafe { ptr::read_unaligned(self.pointer) }
+        unsafe { ptr::read_unaligned(self.as_ptr()) }
     }
 
     /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
@@ -954,7 +961,7 @@ impl<T: ?Sized> NonNull<T> {
         T: Sized,
     {
         // SAFETY: the caller must uphold the safety contract for `copy`.
-        unsafe { ptr::copy(self.pointer, dest.as_ptr(), count) }
+        unsafe { ptr::copy(self.as_ptr(), dest.as_ptr(), count) }
     }
 
     /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
@@ -974,7 +981,7 @@ impl<T: ?Sized> NonNull<T> {
         T: Sized,
     {
         // SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`.
-        unsafe { ptr::copy_nonoverlapping(self.pointer, dest.as_ptr(), count) }
+        unsafe { ptr::copy_nonoverlapping(self.as_ptr(), dest.as_ptr(), count) }
     }
 
     /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
@@ -994,7 +1001,7 @@ impl<T: ?Sized> NonNull<T> {
         T: Sized,
     {
         // SAFETY: the caller must uphold the safety contract for `copy`.
-        unsafe { ptr::copy(src.pointer, self.as_ptr(), count) }
+        unsafe { ptr::copy(src.as_ptr(), self.as_ptr(), count) }
     }
 
     /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
@@ -1014,7 +1021,7 @@ impl<T: ?Sized> NonNull<T> {
         T: Sized,
     {
         // SAFETY: the caller must uphold the safety contract for `copy_nonoverlapping`.
-        unsafe { ptr::copy_nonoverlapping(src.pointer, self.as_ptr(), count) }
+        unsafe { ptr::copy_nonoverlapping(src.as_ptr(), self.as_ptr(), count) }
     }
 
     /// Executes the destructor (if any) of the pointed-to value.
@@ -1201,7 +1208,7 @@ impl<T: ?Sized> NonNull<T> {
 
         {
             // SAFETY: `align` has been checked to be a power of 2 above.
-            unsafe { ptr::align_offset(self.pointer, align) }
+            unsafe { ptr::align_offset(self.as_ptr(), align) }
         }
     }
 
@@ -1229,7 +1236,7 @@ impl<T: ?Sized> NonNull<T> {
     where
         T: Sized,
     {
-        self.pointer.is_aligned()
+        self.as_ptr().is_aligned()
     }
 
     /// Returns whether the pointer is aligned to `align`.
@@ -1266,7 +1273,7 @@ impl<T: ?Sized> NonNull<T> {
     #[must_use]
     #[unstable(feature = "pointer_is_aligned_to", issue = "96284")]
     pub fn is_aligned_to(self, align: usize) -> bool {
-        self.pointer.is_aligned_to(align)
+        self.as_ptr().is_aligned_to(align)
     }
 }
 
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index a5507f0f338..191eaccff98 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -858,7 +858,7 @@ impl<T> [T] {
 
     /// Gets a reference to the underlying array.
     ///
-    /// If `N` is not exactly equal to slice's the length of `self`, then this method returns `None`.
+    /// If `N` is not exactly equal to the length of `self`, then this method returns `None`.
     #[unstable(feature = "slice_as_array", issue = "133508")]
     #[inline]
     #[must_use]
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index ec4b42b966b..e0b1c21e1ec 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -13,7 +13,6 @@
 #![feature(bigint_helper_methods)]
 #![feature(cell_update)]
 #![feature(clone_to_uninit)]
-#![feature(const_align_of_val_raw)]
 #![feature(const_black_box)]
 #![feature(const_eval_select)]
 #![feature(const_nonnull_new)]
diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
index 7e9773f2fb9..454b13a7ee3 100644
--- a/library/core/tests/ptr.rs
+++ b/library/core/tests/ptr.rs
@@ -304,6 +304,7 @@ fn test_const_nonnull_new() {
 #[test]
 #[cfg(unix)] // printf may not be available on other platforms
 #[allow(deprecated)] // For SipHasher
+#[cfg_attr(not(bootstrap), allow(unpredictable_function_pointer_comparisons))]
 pub fn test_variadic_fnptr() {
     use core::ffi;
     use core::hash::{Hash, SipHasher};
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 09c0b61fb2b..109bc394634 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -204,6 +204,25 @@ use crate::ops::Index;
 ///     println!("{viking:?} has {health} hp");
 /// }
 /// ```
+///
+/// # Usage in `const` and `static`
+///
+/// As explained above, `HashMap` is randomly seeded: each `HashMap` instance uses a different seed,
+/// which means that `HashMap::new` cannot be used in const context. To construct a `HashMap` in the
+/// initializer of a `const` or `static` item, you will have to use a different hasher that does not
+/// involve a random seed, as demonstrated in the following example. **A `HashMap` constructed this
+/// way is not resistant against HashDoS!**
+///
+/// ```rust
+/// use std::collections::HashMap;
+/// use std::hash::{BuildHasherDefault, DefaultHasher};
+/// use std::sync::Mutex;
+///
+/// const EMPTY_MAP: HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>> =
+///     HashMap::with_hasher(BuildHasherDefault::new());
+/// static MAP: Mutex<HashMap<String, Vec<i32>, BuildHasherDefault<DefaultHasher>>> =
+///     Mutex::new(HashMap::with_hasher(BuildHasherDefault::new()));
+/// ```
 
 #[cfg_attr(not(test), rustc_diagnostic_item = "HashMap")]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -277,7 +296,10 @@ impl<K, V, S> HashMap<K, V, S> {
     /// ```
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
-    #[rustc_const_unstable(feature = "const_collections_with_hasher", issue = "102575")]
+    #[rustc_const_stable(
+        feature = "const_collections_with_hasher",
+        since = "CURRENT_RUSTC_VERSION"
+    )]
     pub const fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
         HashMap { base: base::HashMap::with_hasher(hash_builder) }
     }
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index 21a73259f61..4c81aaff458 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -101,6 +101,25 @@ use crate::ops::{BitAnd, BitOr, BitXor, Sub};
 /// [`HashMap`]: crate::collections::HashMap
 /// [`RefCell`]: crate::cell::RefCell
 /// [`Cell`]: crate::cell::Cell
+///
+/// # Usage in `const` and `static`
+///
+/// Like `HashMap`, `HashSet` is randomly seeded: each `HashSet` instance uses a different seed,
+/// which means that `HashSet::new` cannot be used in const context. To construct a `HashSet` in the
+/// initializer of a `const` or `static` item, you will have to use a different hasher that does not
+/// involve a random seed, as demonstrated in the following example. **A `HashSet` constructed this
+/// way is not resistant against HashDoS!**
+///
+/// ```rust
+/// use std::collections::HashSet;
+/// use std::hash::{BuildHasherDefault, DefaultHasher};
+/// use std::sync::Mutex;
+///
+/// const EMPTY_SET: HashSet<String, BuildHasherDefault<DefaultHasher>> =
+///     HashSet::with_hasher(BuildHasherDefault::new());
+/// static SET: Mutex<HashSet<String, BuildHasherDefault<DefaultHasher>>> =
+///     Mutex::new(HashSet::with_hasher(BuildHasherDefault::new()));
+/// ```
 #[cfg_attr(not(test), rustc_diagnostic_item = "HashSet")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct HashSet<T, S = RandomState> {
@@ -369,7 +388,10 @@ impl<T, S> HashSet<T, S> {
     /// ```
     #[inline]
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
-    #[rustc_const_unstable(feature = "const_collections_with_hasher", issue = "102575")]
+    #[rustc_const_stable(
+        feature = "const_collections_with_hasher",
+        since = "CURRENT_RUSTC_VERSION"
+    )]
     pub const fn with_hasher(hasher: S) -> HashSet<T, S> {
         HashSet { base: base::HashSet::with_hasher(hasher) }
     }
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 143878170f0..585946c1d50 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -320,7 +320,6 @@
 // Library features (core):
 // tidy-alphabetical-start
 #![feature(array_chunks)]
-#![feature(build_hasher_default_const_new)]
 #![feature(c_str_module)]
 #![feature(char_internals)]
 #![feature(clone_to_uninit)]
diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/pal/unix/process/process_common.rs
index 13290fed762..342818ac911 100644
--- a/library/std/src/sys/pal/unix/process/process_common.rs
+++ b/library/std/src/sys/pal/unix/process/process_common.rs
@@ -393,7 +393,7 @@ impl Command {
 fn os2c(s: &OsStr, saw_nul: &mut bool) -> CString {
     CString::new(s.as_bytes()).unwrap_or_else(|_e| {
         *saw_nul = true;
-        CString::new("<string-with-nul>").unwrap()
+        c"<string-with-nul>".to_owned()
     })
 }
 
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 2ff44fcd4c6..cfbf6548a38 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -1021,11 +1021,11 @@ impl Drop for PanicGuard {
 ///
 /// # Memory Ordering
 ///
-/// Calls to `park` _synchronize-with_ calls to `unpark`, meaning that memory
+/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory
 /// operations performed before a call to `unpark` are made visible to the thread that
 /// consumes the token and returns from `park`. Note that all `park` and `unpark`
-/// operations for a given thread form a total order and `park` synchronizes-with
-/// _all_ prior `unpark` operations.
+/// operations for a given thread form a total order and _all_ prior `unpark` operations
+/// synchronize-with `park`.
 ///
 /// In atomic ordering terms, `unpark` performs a `Release` operation and `park`
 /// performs the corresponding `Acquire` operation. Calls to `unpark` for the same
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 86d23d9bd02..c9697e670b7 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -324,9 +324,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.162"
+version = "0.2.167"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
+checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
 
 [[package]]
 name = "libredox"
@@ -558,9 +558,9 @@ dependencies = [
 
 [[package]]
 name = "sysinfo"
-version = "0.31.4"
+version = "0.33.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be"
+checksum = "948512566b1895f93b1592c7574baeb2de842f224f2aab158799ecadb8ebbb46"
 dependencies = [
  "core-foundation-sys",
  "libc",
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index fcd97b7b589..6da716b7a89 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -63,7 +63,7 @@ walkdir = "2.4"
 xz2 = "0.1"
 
 # Dependencies needed by the build-metrics feature
-sysinfo = { version = "0.31.2", default-features = false, optional = true, features = ["system"] }
+sysinfo = { version = "0.33.0", default-features = false, optional = true, features = ["system"] }
 
 [target.'cfg(windows)'.dependencies.junction]
 version = "1.0.0"
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index ee813de1c9e..74dfe2e7ec8 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -48,9 +48,9 @@ fn main() {
             err => {
                 drop(err);
                 if let Ok(pid) = pid {
-                    println!("WARNING: build directory locked by process {pid}, waiting for lock");
+                    eprintln!("WARNING: build directory locked by process {pid}, waiting for lock");
                 } else {
-                    println!("WARNING: build directory locked, waiting for lock");
+                    eprintln!("WARNING: build directory locked, waiting for lock");
                 }
                 let mut lock = t!(build_lock.write());
                 t!(lock.write(process::id().to_string().as_ref()));
@@ -70,13 +70,13 @@ fn main() {
     // changelog warning, not the `x.py setup` message.
     let suggest_setup = config.config.is_none() && !matches!(config.cmd, Subcommand::Setup { .. });
     if suggest_setup {
-        println!("WARNING: you have not made a `config.toml`");
-        println!(
+        eprintln!("WARNING: you have not made a `config.toml`");
+        eprintln!(
             "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \
             `cp config.example.toml config.toml`"
         );
     } else if let Some(suggestion) = &changelog_suggestion {
-        println!("{suggestion}");
+        eprintln!("{suggestion}");
     }
 
     let pre_commit = config.src.join(".git").join("hooks").join("pre-commit");
@@ -86,13 +86,13 @@ fn main() {
     Build::new(config).build();
 
     if suggest_setup {
-        println!("WARNING: you have not made a `config.toml`");
-        println!(
+        eprintln!("WARNING: you have not made a `config.toml`");
+        eprintln!(
             "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \
             `cp config.example.toml config.toml`"
         );
     } else if let Some(suggestion) = &changelog_suggestion {
-        println!("{suggestion}");
+        eprintln!("{suggestion}");
     }
 
     // Give a warning if the pre-commit script is in pre-commit and not pre-push.
@@ -102,14 +102,14 @@ fn main() {
     if fs::read_to_string(pre_commit).is_ok_and(|contents| {
         contents.contains("https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570")
     }) {
-        println!(
+        eprintln!(
             "WARNING: You have the pre-push script installed to .git/hooks/pre-commit. \
                   Consider moving it to .git/hooks/pre-push instead, which runs less often."
         );
     }
 
     if suggest_setup || changelog_suggestion.is_some() {
-        println!("NOTE: this message was printed twice to make it more likely to be seen");
+        eprintln!("NOTE: this message was printed twice to make it more likely to be seen");
     }
 
     if dump_bootstrap_shims {
diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs
index 88595ff7e51..e57ed488f97 100644
--- a/src/bootstrap/src/bin/rustc.rs
+++ b/src/bootstrap/src/bin/rustc.rs
@@ -306,7 +306,7 @@ fn main() {
         // should run on success, after this block.
     }
     if verbose > 0 {
-        println!("\nDid not run successfully: {status}\n{cmd:?}\n-------------");
+        eprintln!("\nDid not run successfully: {status}\n{cmd:?}\n-------------");
     }
 
     if let Some(mut on_fail) = on_fail {
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index d46c0ab7fef..2af2e83db8f 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -287,7 +287,7 @@ impl Step for CodegenBackend {
     fn run(self, builder: &Builder<'_>) {
         // FIXME: remove once https://github.com/rust-lang/rust/issues/112393 is resolved
         if builder.build.config.vendor && self.backend == "gcc" {
-            println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
+            eprintln!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
             return;
         }
 
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 0cacd6e4f37..4419b11ac19 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1611,7 +1611,7 @@ impl Step for Sysroot {
         let sysroot = sysroot_dir(compiler.stage);
 
         builder
-            .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
+            .verbose(|| eprintln!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
         let _ = fs::remove_dir_all(&sysroot);
         t!(fs::create_dir_all(&sysroot));
 
@@ -1681,7 +1681,7 @@ impl Step for Sysroot {
                     return true;
                 }
                 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
-                    builder.verbose_than(1, || println!("ignoring {}", path.display()));
+                    builder.verbose_than(1, || eprintln!("ignoring {}", path.display()));
                     false
                 } else {
                     true
@@ -2240,7 +2240,7 @@ pub fn stream_cargo(
         cargo.arg(arg);
     }
 
-    builder.verbose(|| println!("running: {cargo:?}"));
+    builder.verbose(|| eprintln!("running: {cargo:?}"));
 
     if builder.config.dry_run() {
         return true;
@@ -2261,12 +2261,12 @@ pub fn stream_cargo(
             Ok(msg) => {
                 if builder.config.json_output {
                     // Forward JSON to stdout.
-                    println!("{line}");
+                    eprintln!("{line}");
                 }
                 cb(msg)
             }
             // If this was informational, just print it out and continue
-            Err(_) => println!("{line}"),
+            Err(_) => eprintln!("{line}"),
         }
     }
 
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index a636c4a9ef1..57fce206f95 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -549,24 +549,24 @@ impl Step for DebuggerScripts {
             cp_debugger_script("natvis/liballoc.natvis");
             cp_debugger_script("natvis/libcore.natvis");
             cp_debugger_script("natvis/libstd.natvis");
-        } else {
-            cp_debugger_script("rust_types.py");
+        }
 
-            // gdb debugger scripts
-            builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
-            builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
+        cp_debugger_script("rust_types.py");
 
-            cp_debugger_script("gdb_load_rust_pretty_printers.py");
-            cp_debugger_script("gdb_lookup.py");
-            cp_debugger_script("gdb_providers.py");
+        // gdb debugger scripts
+        builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
+        builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
 
-            // lldb debugger scripts
-            builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
+        cp_debugger_script("gdb_load_rust_pretty_printers.py");
+        cp_debugger_script("gdb_lookup.py");
+        cp_debugger_script("gdb_providers.py");
 
-            cp_debugger_script("lldb_lookup.py");
-            cp_debugger_script("lldb_providers.py");
-            cp_debugger_script("lldb_commands")
-        }
+        // lldb debugger scripts
+        builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
+
+        cp_debugger_script("lldb_lookup.py");
+        cp_debugger_script("lldb_providers.py");
+        cp_debugger_script("lldb_commands")
     }
 }
 
@@ -2080,7 +2080,7 @@ fn maybe_install_llvm(
     {
         let mut cmd = command(llvm_config);
         cmd.arg("--libfiles");
-        builder.verbose(|| println!("running {cmd:?}"));
+        builder.verbose(|| eprintln!("running {cmd:?}"));
         let files = cmd.run_capture_stdout(builder).stdout();
         let build_llvm_out = &builder.llvm_out(builder.config.build);
         let target_llvm_out = &builder.llvm_out(target);
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index 29a96f77672..d32e06d8748 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -107,10 +107,10 @@ fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) {
         if let Some(adjective) = adjective { format!("{adjective} ") } else { String::new() };
     if len <= 10 {
         for path in paths {
-            println!("fmt: {verb} {adjective}file {path}");
+            eprintln!("fmt: {verb} {adjective}file {path}");
         }
     } else {
-        println!("fmt: {verb} {len} {adjective}files");
+        eprintln!("fmt: {verb} {len} {adjective}files");
     }
 }
 
@@ -199,7 +199,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
                 match get_modified_rs_files(build) {
                     Ok(Some(files)) => {
                         if files.is_empty() {
-                            println!("fmt info: No modified files detected for formatting.");
+                            eprintln!("fmt info: No modified files detected for formatting.");
                             return;
                         }
 
diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs
index 3a8f9e48c0d..1af7b954f5e 100644
--- a/src/bootstrap/src/core/build_steps/setup.rs
+++ b/src/bootstrap/src/core/build_steps/setup.rs
@@ -134,7 +134,7 @@ impl Step for Profile {
                     t!(fs::remove_file(path));
                 }
                 _ => {
-                    println!("Exiting.");
+                    eprintln!("Exiting.");
                     crate::exit!(1);
                 }
             }
@@ -184,15 +184,15 @@ pub fn setup(config: &Config, profile: Profile) {
         Profile::Dist => &["dist", "build"],
     };
 
-    println!();
+    eprintln!();
 
-    println!("To get started, try one of the following commands:");
+    eprintln!("To get started, try one of the following commands:");
     for cmd in suggestions {
-        println!("- `x.py {cmd}`");
+        eprintln!("- `x.py {cmd}`");
     }
 
     if profile != Profile::Dist {
-        println!(
+        eprintln!(
             "For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
         );
     }
@@ -224,7 +224,7 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
     t!(fs::write(path, settings));
 
     let include_path = profile.include_path(&config.src);
-    println!("`x.py` will now use the configuration at {}", include_path.display());
+    eprintln!("`x.py` will now use the configuration at {}", include_path.display());
 }
 
 /// Creates a toolchain link for stage1 using `rustup`
@@ -256,7 +256,7 @@ impl Step for Link {
         }
 
         if !rustup_installed(builder) {
-            println!("WARNING: `rustup` is not installed; Skipping `stage1` toolchain linking.");
+            eprintln!("WARNING: `rustup` is not installed; Skipping `stage1` toolchain linking.");
             return;
         }
 
@@ -296,7 +296,7 @@ fn attempt_toolchain_link(builder: &Builder<'_>, stage_path: &str) {
     }
 
     if try_link_toolchain(builder, stage_path) {
-        println!(
+        eprintln!(
             "Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain"
         );
     } else {
@@ -321,14 +321,14 @@ fn toolchain_is_linked(builder: &Builder<'_>) -> bool {
                 return false;
             }
             // The toolchain has already been linked.
-            println!(
+            eprintln!(
                 "`stage1` toolchain already linked; not attempting to link `stage1` toolchain"
             );
         }
         None => {
             // In this case, we don't know if the `stage1` toolchain has been linked;
             // but `rustup` failed, so let's not go any further.
-            println!(
+            eprintln!(
                 "`rustup` failed to list current toolchains; not attempting to link `stage1` toolchain"
             );
         }
@@ -389,9 +389,9 @@ pub fn interactive_path() -> io::Result<Profile> {
         input.parse()
     }
 
-    println!("Welcome to the Rust project! What do you want to do with x.py?");
+    eprintln!("Welcome to the Rust project! What do you want to do with x.py?");
     for ((letter, _), profile) in abbrev_all() {
-        println!("{}) {}: {}", letter, profile, profile.purpose());
+        eprintln!("{}) {}: {}", letter, profile, profile.purpose());
     }
     let template = loop {
         print!(
@@ -488,7 +488,7 @@ fn install_git_hook_maybe(builder: &Builder<'_>, config: &Config) -> io::Result<
         return Ok(());
     }
 
-    println!(
+    eprintln!(
         "\nRust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
 If you'd like, x.py can install a git hook for you that will automatically run `test tidy` before
 pushing your code to ensure your code is up to par. If you decide later that this behavior is
@@ -496,7 +496,7 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
     );
 
     if prompt_user("Would you like to install the git hook?: [y/N]")? != Some(PromptResult::Yes) {
-        println!("Ok, skipping installation!");
+        eprintln!("Ok, skipping installation!");
         return Ok(());
     }
     if !hooks_dir.exists() {
@@ -513,7 +513,7 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
             );
             return Err(e);
         }
-        Ok(_) => println!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"),
+        Ok(_) => eprintln!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"),
     };
     Ok(())
 }
@@ -654,7 +654,7 @@ impl Step for Editor {
                 if let Some(editor_kind) = editor_kind {
                     while !t!(create_editor_settings_maybe(config, editor_kind.clone())) {}
                 } else {
-                    println!("Ok, skipping editor setup!");
+                    eprintln!("Ok, skipping editor setup!");
                 }
             }
             Err(e) => eprintln!("Could not determine the editor: {e}"),
@@ -687,7 +687,7 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
             mismatched_settings = Some(false);
         }
     }
-    println!(
+    eprintln!(
         "\nx.py can automatically install the recommended `{settings_filename}` file for rustc development"
     );
 
@@ -706,7 +706,7 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
         Some(PromptResult::Yes) => true,
         Some(PromptResult::Print) => false,
         _ => {
-            println!("Ok, skipping settings!");
+            eprintln!("Ok, skipping settings!");
             return Ok(true);
         }
     };
@@ -733,9 +733,9 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
             _ => "Created",
         };
         fs::write(&settings_path, editor.settings_template())?;
-        println!("{verb} `{}`", settings_filename);
+        eprintln!("{verb} `{}`", settings_filename);
     } else {
-        println!("\n{}", editor.settings_template());
+        eprintln!("\n{}", editor.settings_template());
     }
     Ok(should_create)
 }
diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs
index ba9b1b2fc33..7b2d9fff8f5 100644
--- a/src/bootstrap/src/core/build_steps/suggest.rs
+++ b/src/bootstrap/src/core/build_steps/suggest.rs
@@ -66,6 +66,6 @@ pub fn suggest(builder: &Builder<'_>, run: bool) {
             build.build();
         }
     } else {
-        println!("HELP: consider using the `--run` flag to automatically run suggested tests");
+        eprintln!("HELP: consider using the `--run` flag to automatically run suggested tests");
     }
 }
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 4fa91c1a571..6da37530d96 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -471,11 +471,11 @@ impl Miri {
         // We re-use the `cargo` from above.
         cargo.arg("--print-sysroot");
 
-        builder.verbose(|| println!("running: {cargo:?}"));
+        builder.verbose(|| eprintln!("running: {cargo:?}"));
         let stdout = cargo.run_capture_stdout(builder).stdout();
         // Output is "<sysroot>\n".
         let sysroot = stdout.trim_end();
-        builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
+        builder.verbose(|| eprintln!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
         PathBuf::from(sysroot)
     }
 }
@@ -2478,7 +2478,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
         }
     }
 
-    builder.verbose(|| println!("doc tests for: {}", markdown.display()));
+    builder.verbose(|| eprintln!("doc tests for: {}", markdown.display()));
     let mut cmd = builder.rustdoc_cmd(compiler);
     builder.add_rust_test_threads(&mut cmd);
     // allow for unstable options such as new editions
@@ -2756,6 +2756,10 @@ impl Step for Crate {
             // `lib.rs` file, and a `lib.miri.rs` file exists in the same folder, we build that
             // instead. But crucially we only do that for the library, not the test builds.
             cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
+            // std needs to be built with `-Zforce-unstable-if-unmarked`. For some reason the builder
+            // does not set this directly, but relies on the rustc wrapper to set it, and we are not using
+            // the wrapper -- hence we have to set it ourselves.
+            cargo.rustflag("-Zforce-unstable-if-unmarked");
             cargo
         } else {
             // Also prepare a sysroot for the target.
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index dd138508bea..38abca8b8da 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -523,7 +523,7 @@ impl Builder<'_> {
 
         let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8");
         if self.is_verbose() && !matches!(self.config.dry_run, DryRun::SelfCheck) {
-            println!("using sysroot {sysroot_str}");
+            eprintln!("using sysroot {sysroot_str}");
         }
 
         let mut rustflags = Rustflags::new(target);
@@ -1033,6 +1033,15 @@ impl Builder<'_> {
 
         if mode == Mode::Rustc {
             rustflags.arg("-Wrustc::internal");
+            // cfg(bootstrap) - remove this check when lint is in bootstrap compiler
+            if stage != 0 {
+                // Lint is allow by default so downstream tools don't get a lit
+                // they can do nothing about
+                // We shouldn't be preinterning symbols used by tests
+                if cmd_kind != Kind::Test {
+                    rustflags.arg("-Drustc::symbol_intern_string_literal");
+                }
+            }
             // FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all
             // of the individual lints are satisfied.
             rustflags.arg("-Wkeyword_idents_2024");
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 73bc7195ac2..ffe3e053e72 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -392,14 +392,14 @@ impl StepDescription {
     fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
         if builder.config.skip.iter().any(|e| pathset.has(e, builder.kind)) {
             if !matches!(builder.config.dry_run, DryRun::SelfCheck) {
-                println!("Skipping {pathset:?} because it is excluded");
+                eprintln!("Skipping {pathset:?} because it is excluded");
             }
             return true;
         }
 
         if !builder.config.skip.is_empty() && !matches!(builder.config.dry_run, DryRun::SelfCheck) {
             builder.verbose(|| {
-                println!(
+                eprintln!(
                     "{:?} not skipped for {:?} -- not in {:?}",
                     pathset, self.name, builder.config.skip
                 )
@@ -765,6 +765,54 @@ impl Kind {
     }
 }
 
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+struct Libdir {
+    compiler: Compiler,
+    target: TargetSelection,
+}
+
+impl Step for Libdir {
+    type Output = PathBuf;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.never()
+    }
+
+    fn run(self, builder: &Builder<'_>) -> PathBuf {
+        let relative_sysroot_libdir = builder.sysroot_libdir_relative(self.compiler);
+        let sysroot = builder.sysroot(self.compiler).join(relative_sysroot_libdir).join("rustlib");
+
+        if !builder.config.dry_run() {
+            // Avoid deleting the `rustlib/` directory we just copied (in `impl Step for
+            // Sysroot`).
+            if !builder.download_rustc() {
+                let sysroot_target_libdir = sysroot.join(self.target).join("lib");
+                builder.verbose(|| {
+                    eprintln!(
+                        "Removing sysroot {} to avoid caching bugs",
+                        sysroot_target_libdir.display()
+                    )
+                });
+                let _ = fs::remove_dir_all(&sysroot_target_libdir);
+                t!(fs::create_dir_all(&sysroot_target_libdir));
+            }
+
+            if self.compiler.stage == 0 {
+                // The stage 0 compiler for the build triple is always pre-built. Ensure that
+                // `libLLVM.so` ends up in the target libdir, so that ui-fulldeps tests can use
+                // it when run.
+                dist::maybe_install_llvm_target(
+                    builder,
+                    self.compiler.host,
+                    &builder.sysroot(self.compiler),
+                );
+            }
+        }
+
+        sysroot
+    }
+}
+
 impl<'a> Builder<'a> {
     fn get_step_descriptions(kind: Kind) -> Vec<StepDescription> {
         macro_rules! describe {
@@ -1165,56 +1213,13 @@ impl<'a> Builder<'a> {
 
     /// Returns the bindir for a compiler's sysroot.
     pub fn sysroot_target_bindir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf {
-        self.sysroot_target_libdir(compiler, target).parent().unwrap().join("bin")
+        self.ensure(Libdir { compiler, target }).join(target).join("bin")
     }
 
     /// Returns the libdir where the standard library and other artifacts are
     /// found for a compiler's sysroot.
     pub fn sysroot_target_libdir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf {
-        #[derive(Debug, Clone, Hash, PartialEq, Eq)]
-        struct Libdir {
-            compiler: Compiler,
-            target: TargetSelection,
-        }
-        impl Step for Libdir {
-            type Output = PathBuf;
-
-            fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-                run.never()
-            }
-
-            fn run(self, builder: &Builder<'_>) -> PathBuf {
-                let lib = builder.sysroot_libdir_relative(self.compiler);
-                let sysroot = builder
-                    .sysroot(self.compiler)
-                    .join(lib)
-                    .join("rustlib")
-                    .join(self.target)
-                    .join("lib");
-                // Avoid deleting the rustlib/ directory we just copied
-                // (in `impl Step for Sysroot`).
-                if !builder.download_rustc() {
-                    builder.verbose(|| {
-                        println!("Removing sysroot {} to avoid caching bugs", sysroot.display())
-                    });
-                    let _ = fs::remove_dir_all(&sysroot);
-                    t!(fs::create_dir_all(&sysroot));
-                }
-
-                if self.compiler.stage == 0 {
-                    // The stage 0 compiler for the build triple is always pre-built.
-                    // Ensure that `libLLVM.so` ends up in the target libdir, so that ui-fulldeps tests can use it when run.
-                    dist::maybe_install_llvm_target(
-                        builder,
-                        self.compiler.host,
-                        &builder.sysroot(self.compiler),
-                    );
-                }
-
-                sysroot
-            }
-        }
-        self.ensure(Libdir { compiler, target })
+        self.ensure(Libdir { compiler, target }).join(target).join("lib")
     }
 
     pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
@@ -1432,11 +1437,11 @@ impl<'a> Builder<'a> {
                 panic!("{}", out);
             }
             if let Some(out) = self.cache.get(&step) {
-                self.verbose_than(1, || println!("{}c {:?}", "  ".repeat(stack.len()), step));
+                self.verbose_than(1, || eprintln!("{}c {:?}", "  ".repeat(stack.len()), step));
 
                 return out;
             }
-            self.verbose_than(1, || println!("{}> {:?}", "  ".repeat(stack.len()), step));
+            self.verbose_than(1, || eprintln!("{}> {:?}", "  ".repeat(stack.len()), step));
             stack.push(Box::new(step.clone()));
         }
 
@@ -1457,7 +1462,7 @@ impl<'a> Builder<'a> {
             let step_string = format!("{step:?}");
             let brace_index = step_string.find('{').unwrap_or(0);
             let type_string = type_name::<S>();
-            println!(
+            eprintln!(
                 "[TIMING] {} {} -- {}.{:03}",
                 &type_string.strip_prefix("bootstrap::").unwrap_or(type_string),
                 &step_string[brace_index..],
@@ -1474,7 +1479,9 @@ impl<'a> Builder<'a> {
             let cur_step = stack.pop().expect("step stack empty");
             assert_eq!(cur_step.downcast_ref(), Some(&step));
         }
-        self.verbose_than(1, || println!("{}< {:?}", "  ".repeat(self.stack.borrow().len()), step));
+        self.verbose_than(1, || {
+            eprintln!("{}< {:?}", "  ".repeat(self.stack.borrow().len()), step)
+        });
         self.cache.put(step, out.clone());
         out
     }
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index a1c8bff0db9..b2ffbd9c70f 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -738,3 +738,49 @@ mod dist {
         ]);
     }
 }
+
+mod sysroot_target_dirs {
+    use super::{
+        Build, Builder, Compiler, TEST_TRIPLE_1, TEST_TRIPLE_2, TargetSelection, configure,
+    };
+
+    #[test]
+    fn test_sysroot_target_libdir() {
+        let build = Build::new(configure("build", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]));
+        let builder = Builder::new(&build);
+        let target_triple_1 = TargetSelection::from_user(TEST_TRIPLE_1);
+        let compiler = Compiler { stage: 1, host: target_triple_1 };
+        let target_triple_2 = TargetSelection::from_user(TEST_TRIPLE_2);
+        let actual = builder.sysroot_target_libdir(compiler, target_triple_2);
+
+        assert_eq!(
+            builder
+                .sysroot(compiler)
+                .join(builder.sysroot_libdir_relative(compiler))
+                .join("rustlib")
+                .join(TEST_TRIPLE_2)
+                .join("lib"),
+            actual
+        );
+    }
+
+    #[test]
+    fn test_sysroot_target_bindir() {
+        let build = Build::new(configure("build", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]));
+        let builder = Builder::new(&build);
+        let target_triple_1 = TargetSelection::from_user(TEST_TRIPLE_1);
+        let compiler = Compiler { stage: 1, host: target_triple_1 };
+        let target_triple_2 = TargetSelection::from_user(TEST_TRIPLE_2);
+        let actual = builder.sysroot_target_bindir(compiler, target_triple_2);
+
+        assert_eq!(
+            builder
+                .sysroot(compiler)
+                .join(builder.sysroot_libdir_relative(compiler))
+                .join("rustlib")
+                .join(TEST_TRIPLE_2)
+                .join("bin"),
+            actual
+        );
+    }
+}
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index b0fbff79b90..aa5cce2fb1b 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -1293,7 +1293,7 @@ impl Config {
                     .map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids))
                 {
                     if !changes.is_empty() {
-                        println!(
+                        eprintln!(
                             "WARNING: There have been changes to x.py since you last updated:\n{}",
                             crate::human_readable_changes(&changes)
                         );
@@ -1559,7 +1559,7 @@ impl Config {
         }
 
         if cargo_clippy.is_some() && rustc.is_none() {
-            println!(
+            eprintln!(
                 "WARNING: Using `build.cargo-clippy` without `build.rustc` usually fails due to toolchain conflict."
             );
         }
@@ -1841,7 +1841,7 @@ impl Config {
 
             // FIXME: Remove this option at the end of 2024.
             if parallel_compiler.is_some() {
-                println!(
+                eprintln!(
                     "WARNING: The `rust.parallel-compiler` option is deprecated and does nothing. The parallel compiler (with one thread) is now the default"
                 );
             }
@@ -1873,7 +1873,7 @@ impl Config {
                         if available_backends.contains(&backend) {
                             panic!("Invalid value '{s}' for 'rust.codegen-backends'. Instead, please use '{backend}'.");
                         } else {
-                            println!("HELP: '{s}' for 'rust.codegen-backends' might fail. \
+                            eprintln!("HELP: '{s}' for 'rust.codegen-backends' might fail. \
                                 Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \
                                 In this case, it would be referred to as '{backend}'.");
                         }
@@ -1902,7 +1902,7 @@ impl Config {
         // tests may fail due to using a different channel than the one used by the compiler during tests.
         if let Some(commit) = &config.download_rustc_commit {
             if is_user_configured_rust_channel {
-                println!(
+                eprintln!(
                     "WARNING: `rust.download-rustc` is enabled. The `rust.channel` option will be overridden by the CI rustc's channel."
                 );
 
@@ -1992,10 +1992,10 @@ impl Config {
 
             if config.llvm_from_ci {
                 let warn = |option: &str| {
-                    println!(
+                    eprintln!(
                         "WARNING: `{option}` will only be used on `compiler/rustc_llvm` build, not for the LLVM build."
                     );
-                    println!(
+                    eprintln!(
                         "HELP: To use `{option}` for LLVM builds, set `download-ci-llvm` option to false."
                     );
                 };
@@ -2014,12 +2014,12 @@ impl Config {
                 // if they've chosen a different value.
 
                 if libzstd.is_some() {
-                    println!(
+                    eprintln!(
                         "WARNING: when using `download-ci-llvm`, the local `llvm.libzstd` option, \
                         like almost all `llvm.*` options, will be ignored and set by the LLVM CI \
                         artifacts builder config."
                     );
-                    println!(
+                    eprintln!(
                         "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false."
                     );
                 }
@@ -2088,7 +2088,7 @@ impl Config {
                             if available_backends.contains(&backend) {
                                 panic!("Invalid value '{s}' for 'target.{triple}.codegen-backends'. Instead, please use '{backend}'.");
                             } else {
-                                println!("HELP: '{s}' for 'target.{triple}.codegen-backends' might fail. \
+                                eprintln!("HELP: '{s}' for 'target.{triple}.codegen-backends' might fail. \
                                     Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \
                                     In this case, it would be referred to as '{backend}'.");
                             }
@@ -2304,7 +2304,7 @@ impl Config {
         if self.dry_run() {
             return Ok(());
         }
-        self.verbose(|| println!("running: {cmd:?}"));
+        self.verbose(|| eprintln!("running: {cmd:?}"));
         build_helper::util::try_run(cmd, self.is_verbose())
     }
 
@@ -2479,7 +2479,7 @@ impl Config {
                         // This happens when LLVM submodule is updated in CI, we should disable ci-rustc without an error
                         // to not break CI. For non-CI environments, we should return an error.
                         if CiEnv::is_ci() {
-                            println!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled.");
+                            eprintln!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled.");
                             return None;
                         } else {
                             panic!("ERROR: LLVM submodule has changes, `download-rustc` can't be used.");
@@ -2490,8 +2490,8 @@ impl Config {
                         let ci_config_toml = match self.get_builder_toml("ci-rustc") {
                             Ok(ci_config_toml) => ci_config_toml,
                             Err(e) if e.to_string().contains("unknown field") => {
-                                println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
-                                println!("HELP: Consider rebasing to a newer commit if available.");
+                                eprintln!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
+                                eprintln!("HELP: Consider rebasing to a newer commit if available.");
                                 return None;
                             },
                             Err(e) => {
@@ -2505,6 +2505,7 @@ impl Config {
                         // Check the config compatibility
                         // FIXME: this doesn't cover `--set` flags yet.
                         let res = check_incompatible_options_for_ci_rustc(
+                            self.build,
                             current_config_toml,
                             ci_config_toml,
                         );
@@ -2515,7 +2516,7 @@ impl Config {
                             .is_some_and(|s| s == "1" || s == "true");
 
                         if disable_ci_rustc_if_incompatible && res.is_err() {
-                            println!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env.");
+                            eprintln!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env.");
                             return None;
                         }
 
@@ -2700,7 +2701,7 @@ impl Config {
             return;
         }
 
-        println!("Updating submodule {relative_path}");
+        eprintln!("Updating submodule {relative_path}");
         self.check_run(
             helpers::git(Some(&self.src))
                 .run_always()
@@ -2823,7 +2824,7 @@ impl Config {
             Some(StringOrBool::Bool(true)) => false,
             Some(StringOrBool::String(s)) if s == "if-unchanged" => {
                 if !self.rust_info.is_managed_git_subrepository() {
-                    println!(
+                    eprintln!(
                         "ERROR: `download-rustc=if-unchanged` is only compatible with Git managed sources."
                     );
                     crate::exit!(1);
@@ -2856,10 +2857,10 @@ impl Config {
                 if if_unchanged {
                     return None;
                 }
-                println!("ERROR: could not find commit hash for downloading rustc");
-                println!("HELP: maybe your repository history is too shallow?");
-                println!("HELP: consider setting `rust.download-rustc=false` in config.toml");
-                println!("HELP: or fetch enough history to include one upstream commit");
+                eprintln!("ERROR: could not find commit hash for downloading rustc");
+                eprintln!("HELP: maybe your repository history is too shallow?");
+                eprintln!("HELP: consider setting `rust.download-rustc=false` in config.toml");
+                eprintln!("HELP: or fetch enough history to include one upstream commit");
                 crate::exit!(1);
             }
         };
@@ -2898,7 +2899,7 @@ impl Config {
         let if_unchanged = || {
             if self.rust_info.is_from_tarball() {
                 // Git is needed for running "if-unchanged" logic.
-                println!(
+                eprintln!(
                     "WARNING: 'if-unchanged' has no effect on tarball sources; ignoring `download-ci-llvm`."
                 );
                 return false;
@@ -2947,10 +2948,10 @@ impl Config {
         // Only commits merged by bors will have CI artifacts.
         let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap();
         if commit.is_empty() {
-            println!("error: could not find commit hash for downloading components from CI");
-            println!("help: maybe your repository history is too shallow?");
-            println!("help: consider disabling `{option_name}`");
-            println!("help: or fetch enough history to include one upstream commit");
+            eprintln!("error: could not find commit hash for downloading components from CI");
+            eprintln!("help: maybe your repository history is too shallow?");
+            eprintln!("help: consider disabling `{option_name}`");
+            eprintln!("help: or fetch enough history to include one upstream commit");
             crate::exit!(1);
         }
 
@@ -2962,14 +2963,14 @@ impl Config {
         if has_changes {
             if if_unchanged {
                 if self.is_verbose() {
-                    println!(
+                    eprintln!(
                         "warning: saw changes to one of {modified_paths:?} since {commit}; \
                             ignoring `{option_name}`"
                     );
                 }
                 return None;
             }
-            println!(
+            eprintln!(
                 "warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}"
             );
         }
@@ -3006,7 +3007,7 @@ pub(crate) fn check_incompatible_options_for_ci_llvm(
         ($current:expr, $expected:expr) => {
             if let Some(current) = &$current {
                 if Some(current) != $expected.as_ref() {
-                    println!(
+                    eprintln!(
                         "WARNING: `llvm.{}` has no effect with `llvm.download-ci-llvm`. \
                         Current value: {:?}, Expected value(s): {}{:?}",
                         stringify!($expected).replace("_", "-"),
@@ -3086,17 +3087,18 @@ pub(crate) fn check_incompatible_options_for_ci_llvm(
 /// Compares the current Rust options against those in the CI rustc builder and detects any incompatible options.
 /// It does this by destructuring the `Rust` instance to make sure every `Rust` field is covered and not missing.
 fn check_incompatible_options_for_ci_rustc(
+    host: TargetSelection,
     current_config_toml: TomlConfig,
     ci_config_toml: TomlConfig,
 ) -> Result<(), String> {
     macro_rules! err {
-        ($current:expr, $expected:expr) => {
+        ($current:expr, $expected:expr, $config_section:expr) => {
             if let Some(current) = &$current {
                 if Some(current) != $expected.as_ref() {
                     return Err(format!(
-                        "ERROR: Setting `rust.{}` is incompatible with `rust.download-rustc`. \
+                        "ERROR: Setting `{}` is incompatible with `rust.download-rustc`. \
                         Current value: {:?}, Expected value(s): {}{:?}",
-                        stringify!($expected).replace("_", "-"),
+                        format!("{}.{}", $config_section, stringify!($expected).replace("_", "-")),
                         $current,
                         if $expected.is_some() { "None/" } else { "" },
                         $expected,
@@ -3107,13 +3109,13 @@ fn check_incompatible_options_for_ci_rustc(
     }
 
     macro_rules! warn {
-        ($current:expr, $expected:expr) => {
+        ($current:expr, $expected:expr, $config_section:expr) => {
             if let Some(current) = &$current {
                 if Some(current) != $expected.as_ref() {
-                    println!(
-                        "WARNING: `rust.{}` has no effect with `rust.download-rustc`. \
+                    eprintln!(
+                        "WARNING: `{}` has no effect with `rust.download-rustc`. \
                         Current value: {:?}, Expected value(s): {}{:?}",
-                        stringify!($expected).replace("_", "-"),
+                        format!("{}.{}", $config_section, stringify!($expected).replace("_", "-")),
                         $current,
                         if $expected.is_some() { "None/" } else { "" },
                         $expected,
@@ -3123,6 +3125,31 @@ fn check_incompatible_options_for_ci_rustc(
         };
     }
 
+    let current_profiler = current_config_toml.build.as_ref().and_then(|b| b.profiler);
+    let profiler = ci_config_toml.build.as_ref().and_then(|b| b.profiler);
+    err!(current_profiler, profiler, "build");
+
+    let current_optimized_compiler_builtins =
+        current_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins);
+    let optimized_compiler_builtins =
+        ci_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins);
+    err!(current_optimized_compiler_builtins, optimized_compiler_builtins, "build");
+
+    // We always build the in-tree compiler on cross targets, so we only care
+    // about the host target here.
+    let host_str = host.to_string();
+    if let Some(current_cfg) = current_config_toml.target.as_ref().and_then(|c| c.get(&host_str)) {
+        if current_cfg.profiler.is_some() {
+            let ci_target_toml = ci_config_toml.target.as_ref().and_then(|c| c.get(&host_str));
+            let ci_cfg = ci_target_toml.ok_or(format!(
+                "Target specific config for '{host_str}' is not present for CI-rustc"
+            ))?;
+
+            let profiler = &ci_cfg.profiler;
+            err!(current_cfg.profiler, profiler, "build");
+        }
+    }
+
     let (Some(current_rust_config), Some(ci_rust_config)) =
         (current_config_toml.rust, ci_config_toml.rust)
     else {
@@ -3196,24 +3223,24 @@ fn check_incompatible_options_for_ci_rustc(
     // If the option belongs to the first category, we call `err` macro for a hard error;
     // otherwise, we just print a warning with `warn` macro.
 
-    err!(current_rust_config.optimize, optimize);
-    err!(current_rust_config.randomize_layout, randomize_layout);
-    err!(current_rust_config.debug_logging, debug_logging);
-    err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc);
-    err!(current_rust_config.rpath, rpath);
-    err!(current_rust_config.strip, strip);
-    err!(current_rust_config.lld_mode, lld_mode);
-    err!(current_rust_config.llvm_tools, llvm_tools);
-    err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker);
-    err!(current_rust_config.jemalloc, jemalloc);
-    err!(current_rust_config.default_linker, default_linker);
-    err!(current_rust_config.stack_protector, stack_protector);
-    err!(current_rust_config.lto, lto);
-    err!(current_rust_config.std_features, std_features);
-
-    warn!(current_rust_config.channel, channel);
-    warn!(current_rust_config.description, description);
-    warn!(current_rust_config.incremental, incremental);
+    err!(current_rust_config.optimize, optimize, "rust");
+    err!(current_rust_config.randomize_layout, randomize_layout, "rust");
+    err!(current_rust_config.debug_logging, debug_logging, "rust");
+    err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc, "rust");
+    err!(current_rust_config.rpath, rpath, "rust");
+    err!(current_rust_config.strip, strip, "rust");
+    err!(current_rust_config.lld_mode, lld_mode, "rust");
+    err!(current_rust_config.llvm_tools, llvm_tools, "rust");
+    err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker, "rust");
+    err!(current_rust_config.jemalloc, jemalloc, "rust");
+    err!(current_rust_config.default_linker, default_linker, "rust");
+    err!(current_rust_config.stack_protector, stack_protector, "rust");
+    err!(current_rust_config.lto, lto, "rust");
+    err!(current_rust_config.std_features, std_features, "rust");
+
+    warn!(current_rust_config.channel, channel, "rust");
+    warn!(current_rust_config.description, description, "rust");
+    warn!(current_rust_config.incremental, incremental, "rust");
 
     Ok(())
 }
diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs
index bfeb811508c..66b9f5ed84e 100644
--- a/src/bootstrap/src/core/config/flags.rs
+++ b/src/bootstrap/src/core/config/flags.rs
@@ -196,12 +196,12 @@ impl Flags {
         if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) =
             HelpVerboseOnly::try_parse_from(normalize_args(args))
         {
-            println!("NOTE: updating submodules before printing available paths");
+            eprintln!("NOTE: updating submodules before printing available paths");
             let config = Config::parse(Self::parse(&[String::from("build")]));
             let build = Build::new(config);
             let paths = Builder::get_help(&build, subcommand);
             if let Some(s) = paths {
-                println!("{s}");
+                eprintln!("{s}");
             } else {
                 panic!("No paths available for subcommand `{}`", subcommand.as_str());
             }
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index db35e6907e6..05b91c518cf 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -77,7 +77,7 @@ impl Config {
         if self.dry_run() && !cmd.run_always {
             return true;
         }
-        self.verbose(|| println!("running: {cmd:?}"));
+        self.verbose(|| eprintln!("running: {cmd:?}"));
         check_run(cmd, self.is_verbose())
     }
 
@@ -144,7 +144,7 @@ impl Config {
     /// Please see <https://nixos.org/patchelf.html> for more information
     fn fix_bin_or_dylib(&self, fname: &Path) {
         assert_eq!(SHOULD_FIX_BINS_AND_DYLIBS.get(), Some(&true));
-        println!("attempting to patch {}", fname.display());
+        eprintln!("attempting to patch {}", fname.display());
 
         // Only build `.nix-deps` once.
         static NIX_DEPS_DIR: OnceLock<PathBuf> = OnceLock::new();
@@ -206,7 +206,7 @@ impl Config {
     }
 
     fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) {
-        self.verbose(|| println!("download {url}"));
+        self.verbose(|| eprintln!("download {url}"));
         // Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/.
         let tempfile = self.tempdir().join(dest_path.file_name().unwrap());
         // While bootstrap itself only supports http and https downloads, downstream forks might
@@ -226,7 +226,7 @@ impl Config {
     }
 
     fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) {
-        println!("downloading {url}");
+        eprintln!("downloading {url}");
         // Try curl. If that fails and we are on windows, fallback to PowerShell.
         // options should be kept in sync with
         // src/bootstrap/src/core/download.rs
@@ -341,7 +341,7 @@ impl Config {
             short_path = short_path.strip_prefix(pattern).unwrap_or(short_path);
             let dst_path = dst.join(short_path);
             self.verbose(|| {
-                println!("extracting {} to {}", original_path.display(), dst.display())
+                eprintln!("extracting {} to {}", original_path.display(), dst.display())
             });
             if !t!(member.unpack_in(dst)) {
                 panic!("path traversal attack ??");
@@ -365,7 +365,7 @@ impl Config {
     pub(crate) fn verify(&self, path: &Path, expected: &str) -> bool {
         use sha2::Digest;
 
-        self.verbose(|| println!("verifying {}", path.display()));
+        self.verbose(|| eprintln!("verifying {}", path.display()));
 
         if self.dry_run() {
             return false;
@@ -391,7 +391,7 @@ impl Config {
         let verified = checksum == expected;
 
         if !verified {
-            println!(
+            eprintln!(
                 "invalid checksum: \n\
                 found:    {checksum}\n\
                 expected: {expected}",
@@ -421,7 +421,7 @@ enum DownloadSource {
 /// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions.
 impl Config {
     pub(crate) fn download_clippy(&self) -> PathBuf {
-        self.verbose(|| println!("downloading stage0 clippy artifacts"));
+        self.verbose(|| eprintln!("downloading stage0 clippy artifacts"));
 
         let date = &self.stage0_metadata.compiler.date;
         let version = &self.stage0_metadata.compiler.version;
@@ -518,7 +518,7 @@ impl Config {
     }
 
     pub(crate) fn download_ci_rustc(&self, commit: &str) {
-        self.verbose(|| println!("using downloaded stage2 artifacts from CI (commit {commit})"));
+        self.verbose(|| eprintln!("using downloaded stage2 artifacts from CI (commit {commit})"));
 
         let version = self.artifact_version_part(commit);
         // download-rustc doesn't need its own cargo, it can just use beta's. But it does need the
@@ -539,7 +539,7 @@ impl Config {
 
     #[cfg(not(feature = "bootstrap-self-test"))]
     pub(crate) fn download_beta_toolchain(&self) {
-        self.verbose(|| println!("downloading stage0 beta artifacts"));
+        self.verbose(|| eprintln!("downloading stage0 beta artifacts"));
 
         let date = &self.stage0_metadata.compiler.date;
         let version = &self.stage0_metadata.compiler.version;
@@ -677,7 +677,7 @@ impl Config {
                     return;
                 } else {
                     self.verbose(|| {
-                        println!(
+                        eprintln!(
                             "ignoring cached file {} due to failed verification",
                             tarball.display()
                         )
@@ -776,10 +776,10 @@ download-rustc = false
                     t!(check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml));
                 }
                 Err(e) if e.to_string().contains("unknown field") => {
-                    println!(
+                    eprintln!(
                         "WARNING: CI LLVM has some fields that are no longer supported in bootstrap; download-ci-llvm will be disabled."
                     );
-                    println!("HELP: Consider rebasing to a newer commit if available.");
+                    eprintln!("HELP: Consider rebasing to a newer commit if available.");
                 }
                 Err(e) => {
                     eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}");
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index dcf68cbeeda..71e7f40f032 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -237,11 +237,11 @@ than building it.
                 stage0_supported_target_list.intersection(&missing_targets_hashset).collect();
 
             if !duplicated_targets.is_empty() {
-                println!(
+                eprintln!(
                     "Following targets supported from the stage0 compiler, please remove them from STAGE0_MISSING_TARGETS list."
                 );
                 for duplicated_target in duplicated_targets {
-                    println!("  {duplicated_target}");
+                    eprintln!("  {duplicated_target}");
                 }
                 std::process::exit(1);
             }
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 0ecf61ffcd9..5f778223d7d 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -406,11 +406,11 @@ impl Build {
             .unwrap()
             .trim();
         if local_release.split('.').take(2).eq(version.split('.').take(2)) {
-            build.verbose(|| println!("auto-detected local-rebuild {local_release}"));
+            build.verbose(|| eprintln!("auto-detected local-rebuild {local_release}"));
             build.local_rebuild = true;
         }
 
-        build.verbose(|| println!("finding compilers"));
+        build.verbose(|| eprintln!("finding compilers"));
         utils::cc_detect::find(&build);
         // When running `setup`, the profile is about to change, so any requirements we have now may
         // be different on the next invocation. Don't check for them until the next time x.py is
@@ -418,7 +418,7 @@ impl Build {
         //
         // Similarly, for `setup` we don't actually need submodules or cargo metadata.
         if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
-            build.verbose(|| println!("running sanity check"));
+            build.verbose(|| eprintln!("running sanity check"));
             crate::core::sanity::check(&mut build);
 
             // Make sure we update these before gathering metadata so we don't get an error about missing
@@ -436,7 +436,7 @@ impl Build {
             // Now, update all existing submodules.
             build.update_existing_submodules();
 
-            build.verbose(|| println!("learning about cargo"));
+            build.verbose(|| eprintln!("learning about cargo"));
             crate::core::metadata::build(&mut build);
         }
 
@@ -605,7 +605,7 @@ impl Build {
         let stamp = dir.join(".stamp");
         let mut cleared = false;
         if mtime(&stamp) < mtime(input) {
-            self.verbose(|| println!("Dirty - {}", dir.display()));
+            self.verbose(|| eprintln!("Dirty - {}", dir.display()));
             let _ = fs::remove_dir_all(dir);
             cleared = true;
         } else if stamp.exists() {
@@ -890,7 +890,7 @@ impl Build {
         let executed_at = std::panic::Location::caller();
 
         self.verbose(|| {
-            println!("running: {command:?} (created at {created_at}, executed at {executed_at})")
+            eprintln!("running: {command:?} (created at {created_at}, executed at {executed_at})")
         });
 
         let cmd = command.as_command_mut();
@@ -947,7 +947,7 @@ Executed at: {executed_at}"#,
 
         let fail = |message: &str, output: CommandOutput| -> ! {
             if self.is_verbose() {
-                println!("{message}");
+                eprintln!("{message}");
             } else {
                 let (stdout, stderr) = (output.stdout_if_present(), output.stderr_if_present());
                 // If the command captures output, the user would not see any indication that
@@ -957,16 +957,16 @@ Executed at: {executed_at}"#,
                     if let Some(stdout) =
                         output.stdout_if_present().take_if(|s| !s.trim().is_empty())
                     {
-                        println!("STDOUT:\n{stdout}\n");
+                        eprintln!("STDOUT:\n{stdout}\n");
                     }
                     if let Some(stderr) =
                         output.stderr_if_present().take_if(|s| !s.trim().is_empty())
                     {
-                        println!("STDERR:\n{stderr}\n");
+                        eprintln!("STDERR:\n{stderr}\n");
                     }
-                    println!("Command {command:?} has failed. Rerun with -v to see more details.");
+                    eprintln!("Command {command:?} has failed. Rerun with -v to see more details.");
                 } else {
-                    println!("Command has failed. Rerun with -v to see more details.");
+                    eprintln!("Command has failed. Rerun with -v to see more details.");
                 }
             }
             exit!(1);
@@ -1011,7 +1011,7 @@ Executed at: {executed_at}"#,
         match self.config.dry_run {
             DryRun::SelfCheck => (),
             DryRun::Disabled | DryRun::UserSelected => {
-                println!("{msg}");
+                eprintln!("{msg}");
             }
         }
     }
@@ -1666,7 +1666,7 @@ Executed at: {executed_at}"#,
         if self.config.dry_run() {
             return;
         }
-        self.verbose_than(1, || println!("Copy/Link {src:?} to {dst:?}"));
+        self.verbose_than(1, || eprintln!("Copy/Link {src:?} to {dst:?}"));
         if src == dst {
             return;
         }
@@ -1775,7 +1775,7 @@ Executed at: {executed_at}"#,
             return;
         }
         let dst = dstdir.join(src.file_name().unwrap());
-        self.verbose_than(1, || println!("Install {src:?} to {dst:?}"));
+        self.verbose_than(1, || eprintln!("Install {src:?} to {dst:?}"));
         t!(fs::create_dir_all(dstdir));
         if !src.exists() {
             panic!("ERROR: File \"{}\" not found!", src.display());
diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs
index 0df00469452..e8d5b60948a 100644
--- a/src/bootstrap/src/utils/cc_detect.rs
+++ b/src/bootstrap/src/utils/cc_detect.rs
@@ -155,15 +155,15 @@ pub fn find_target(build: &Build, target: TargetSelection) {
         build.cxx.borrow_mut().insert(target, compiler);
     }
 
-    build.verbose(|| println!("CC_{} = {:?}", target.triple, build.cc(target)));
-    build.verbose(|| println!("CFLAGS_{} = {cflags:?}", target.triple));
+    build.verbose(|| eprintln!("CC_{} = {:?}", target.triple, build.cc(target)));
+    build.verbose(|| eprintln!("CFLAGS_{} = {cflags:?}", target.triple));
     if let Ok(cxx) = build.cxx(target) {
         let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx);
-        build.verbose(|| println!("CXX_{} = {cxx:?}", target.triple));
-        build.verbose(|| println!("CXXFLAGS_{} = {cxxflags:?}", target.triple));
+        build.verbose(|| eprintln!("CXX_{} = {cxx:?}", target.triple));
+        build.verbose(|| eprintln!("CXXFLAGS_{} = {cxxflags:?}", target.triple));
     }
     if let Some(ar) = ar {
-        build.verbose(|| println!("AR_{} = {ar:?}", target.triple));
+        build.verbose(|| eprintln!("AR_{} = {ar:?}", target.triple));
         build.ar.borrow_mut().insert(target, ar);
     }
 
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 923cc2dfc28..c0d52fd3430 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -135,7 +135,7 @@ impl Drop for TimeIt {
     fn drop(&mut self) {
         let time = self.1.elapsed();
         if !self.0 {
-            println!("\tfinished in {}.{:03} seconds", time.as_secs(), time.subsec_millis());
+            eprintln!("\tfinished in {}.{:03} seconds", time.as_secs(), time.subsec_millis());
         }
     }
 }
@@ -267,12 +267,12 @@ pub fn check_run(cmd: &mut BootstrapCommand, print_cmd_on_fail: bool) -> bool {
     let status = match cmd.as_command_mut().status() {
         Ok(status) => status,
         Err(e) => {
-            println!("failed to execute command: {cmd:?}\nERROR: {e}");
+            eprintln!("failed to execute command: {cmd:?}\nERROR: {e}");
             return false;
         }
     };
     if !status.success() && print_cmd_on_fail {
-        println!(
+        eprintln!(
             "\n\ncommand did not execute successfully: {cmd:?}\n\
              expected success, got: {status}\n\n"
         );
diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs
index 3b31fa36e88..06d3add6281 100644
--- a/src/bootstrap/src/utils/metrics.rs
+++ b/src/bootstrap/src/utils/metrics.rs
@@ -56,7 +56,7 @@ impl BuildMetrics {
             running_steps: Vec::new(),
 
             system_info: System::new_with_specifics(
-                RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
+                RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
             ),
             timer_start: None,
             invocation_timer_start: Instant::now(),
@@ -161,8 +161,9 @@ impl BuildMetrics {
 
         let dest = build.out.join("metrics.json");
 
-        let mut system =
-            System::new_with_specifics(RefreshKind::new().with_cpu(CpuRefreshKind::everything()));
+        let mut system = System::new_with_specifics(
+            RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
+        );
         system.refresh_cpu_usage();
         system.refresh_memory();
 
@@ -184,7 +185,7 @@ impl BuildMetrics {
                 if version.format_version == CURRENT_FORMAT_VERSION {
                     t!(serde_json::from_slice::<JsonRoot>(&contents)).invocations
                 } else {
-                    println!(
+                    eprintln!(
                         "WARNING: overriding existing build/metrics.json, as it's not \
                          compatible with build metrics format version {CURRENT_FORMAT_VERSION}."
                     );
diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs
index eb2c8254dc0..27e1c5d01b7 100644
--- a/src/bootstrap/src/utils/render_tests.rs
+++ b/src/bootstrap/src/utils/render_tests.rs
@@ -56,7 +56,7 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut BootstrapCommand, stream: bool) ->
     let cmd = cmd.as_command_mut();
     cmd.stdout(Stdio::piped());
 
-    builder.verbose(|| println!("running: {cmd:?}"));
+    builder.verbose(|| eprintln!("running: {cmd:?}"));
 
     let mut process = cmd.spawn().unwrap();
 
@@ -71,7 +71,7 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut BootstrapCommand, stream: bool) ->
 
     let result = process.wait_with_output().unwrap();
     if !result.status.success() && builder.is_verbose() {
-        println!(
+        eprintln!(
             "\n\ncommand did not execute successfully: {cmd:?}\n\
              expected success, got: {}",
             result.status
@@ -135,7 +135,9 @@ impl<'a> Renderer<'a> {
         if self.up_to_date_tests > 0 {
             let n = self.up_to_date_tests;
             let s = if n > 1 { "s" } else { "" };
-            println!("help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n");
+            eprintln!(
+                "help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n"
+            );
         }
     }
 
@@ -190,7 +192,7 @@ impl<'a> Renderer<'a> {
         if let Some(exec_time) = test.exec_time {
             print!(" ({exec_time:.2?})");
         }
-        println!();
+        eprintln!();
     }
 
     fn render_test_outcome_terse(&mut self, outcome: Outcome<'_>, test: &TestOutcome) {
@@ -200,7 +202,7 @@ impl<'a> Renderer<'a> {
                 let executed = format!("{:>width$}", self.executed_tests - 1, width = total.len());
                 print!(" {executed}/{total}");
             }
-            println!();
+            eprintln!();
             self.terse_tests_in_line = 0;
         }
 
@@ -212,31 +214,31 @@ impl<'a> Renderer<'a> {
     fn render_suite_outcome(&self, outcome: Outcome<'_>, suite: &SuiteOutcome) {
         // The terse output doesn't end with a newline, so we need to add it ourselves.
         if !self.builder.config.verbose_tests {
-            println!();
+            eprintln!();
         }
 
         if !self.failures.is_empty() {
-            println!("\nfailures:\n");
+            eprintln!("\nfailures:\n");
             for failure in &self.failures {
                 if failure.stdout.is_some() || failure.message.is_some() {
-                    println!("---- {} stdout ----", failure.name);
+                    eprintln!("---- {} stdout ----", failure.name);
                     if let Some(stdout) = &failure.stdout {
-                        println!("{stdout}");
+                        eprintln!("{stdout}");
                     }
                     if let Some(message) = &failure.message {
-                        println!("NOTE: {message}");
+                        eprintln!("NOTE: {message}");
                     }
                 }
             }
 
-            println!("\nfailures:");
+            eprintln!("\nfailures:");
             for failure in &self.failures {
-                println!("    {}", failure.name);
+                eprintln!("    {}", failure.name);
             }
         }
 
         if !self.benches.is_empty() {
-            println!("\nbenchmarks:");
+            eprintln!("\nbenchmarks:");
 
             let mut rows = Vec::new();
             for bench in &self.benches {
@@ -251,13 +253,13 @@ impl<'a> Renderer<'a> {
             let max_1 = rows.iter().map(|r| r.1.len()).max().unwrap_or(0);
             let max_2 = rows.iter().map(|r| r.2.len()).max().unwrap_or(0);
             for row in &rows {
-                println!("    {:<max_0$} {:>max_1$} {:>max_2$}", row.0, row.1, row.2);
+                eprintln!("    {:<max_0$} {:>max_1$} {:>max_2$}", row.0, row.1, row.2);
             }
         }
 
         print!("\ntest result: ");
         self.builder.colored_stdout(|stdout| outcome.write_long(stdout)).unwrap();
-        println!(
+        eprintln!(
             ". {} passed; {} failed; {} ignored; {} measured; {} filtered out{time}\n",
             suite.passed,
             suite.failed,
@@ -274,7 +276,7 @@ impl<'a> Renderer<'a> {
     fn render_message(&mut self, message: Message) {
         match message {
             Message::Suite(SuiteMessage::Started { test_count }) => {
-                println!("\nrunning {test_count} tests");
+                eprintln!("\nrunning {test_count} tests");
                 self.executed_tests = 0;
                 self.terse_tests_in_line = 0;
                 self.tests_count = Some(test_count);
@@ -314,7 +316,7 @@ impl<'a> Renderer<'a> {
                 self.failures.push(outcome);
             }
             Message::Test(TestMessage::Timeout { name }) => {
-                println!("test {name} has been running for a long time");
+                eprintln!("test {name} has been running for a long time");
             }
             Message::Test(TestMessage::Started) => {} // Not useful
         }
diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs
index 3c6c7a7fa18..f60498a4872 100644
--- a/src/bootstrap/src/utils/tarball.rs
+++ b/src/bootstrap/src/utils/tarball.rs
@@ -344,7 +344,7 @@ impl<'a> Tarball<'a> {
         // For `x install` tarball files aren't needed, so we can speed up the process by not producing them.
         let compression_profile = if self.builder.kind == Kind::Install {
             self.builder.verbose(|| {
-                println!("Forcing dist.compression-profile = 'no-op' for `x install`.")
+                eprintln!("Forcing dist.compression-profile = 'no-op' for `x install`.")
             });
             // "no-op" indicates that the rust-installer won't produce compressed tarball sources.
             "no-op"
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 454c855c75d..2ea37c168dd 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -338,6 +338,7 @@ auto:
         --set rust.jemalloc
         --set llvm.ninja=false
         --set rust.lto=thin
+        --set rust.codegen-units=1
       RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
       SELECT_XCODE: /Applications/Xcode_15.4.app
       USE_XCODE_CLANG: 1
diff --git a/src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md b/src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md
new file mode 100644
index 00000000000..bea667dcf44
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md
@@ -0,0 +1,7 @@
+# `debug-info-type-line-numbers`
+
+---
+
+This option causes additional type and line information to be emitted in debug
+info to provide richer information to debuggers. This is currently off by
+default as it causes some compilation scenarios to be noticeably slower.
diff --git a/src/doc/unstable-book/src/compiler-flags/randomize-layout.md b/src/doc/unstable-book/src/compiler-flags/randomize-layout.md
new file mode 100644
index 00000000000..84c6712bc23
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/randomize-layout.md
@@ -0,0 +1,23 @@
+# `randomize-layout`
+
+The tracking issue for this feature is: [#106764](https://github.com/rust-lang/rust/issues/106764).
+
+------------------------
+
+The `-Zrandomize-layout` flag changes the layout algorithm for `repr(Rust)` types defined in the current crate from its normal
+optimization goals to pseudorandomly rearranging fields within the degrees of freedom provided by the largely unspecified
+default representation. This also affects type sizes and padding.
+Downstream intantiations of generic types defined in a crate with randomization enabled will also be randomized.
+
+It can be used to find unsafe code that accidentally relies on unspecified behavior.
+
+Randomization is not guaranteed to use a different permutation for each compilation session.
+`-Zlayout-seed=<u64>` can be used to supply additional entropy.
+
+Randomization only approximates the intended freedom of repr(Rust). Sometimes two distinct types may still consistently
+result in the same layout due to limitations of the current implementation. Randomization may become
+more aggressive over time as our coverage of the available degrees of freedoms improves.
+Corollary: Randomization is not a safety oracle. Two struct layouts being observably the same under different layout seeds
+on the current compiler version does not guarantee that future compiler versions won't give them distinct layouts.
+
+Randomization may also become less aggressive in the future if additional guarantees get added to the default layout.
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 5b407ea9a2b..34141c47cf3 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2647,7 +2647,7 @@ fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) {
             });
             args.tokens = TokenStream::new(tokens);
         }
-        ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {}
+        ast::AttrArgs::Empty | ast::AttrArgs::Eq { .. } => {}
     }
 }
 
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index 582ef7d2c48..5e4e6f27a15 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -17,17 +17,18 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
     ///
     /// This is true for html, and false for json. See #80664
     const RUN_ON_MODULE: bool;
+
     /// This associated type is the type where the current module information is stored.
     ///
     /// For each module, we go through their items by calling for each item:
     ///
-    /// 1. save_module_data
-    /// 2. item
-    /// 3. set_back_info
+    /// 1. `save_module_data`
+    /// 2. `item`
+    /// 3. `restore_module_data`
     ///
-    /// However,the `item` method might update information in `self` (for example if the child is
-    /// a module). To prevent it to impact the other children of the current module, we need to
-    /// reset the information between each call to `item` by using `set_back_info`.
+    /// This is because the `item` method might update information in `self` (for example if the child
+    /// is a module). To prevent it from impacting the other children of the current module, we need to
+    /// reset the information between each call to `item` by using `restore_module_data`.
     type ModuleData;
 
     /// Sets up any state required for the renderer. When this is called the cache has already been
@@ -41,18 +42,18 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
 
     /// This method is called right before call [`Self::item`]. This method returns a type
     /// containing information that needs to be reset after the [`Self::item`] method has been
-    /// called with the [`Self::set_back_info`] method.
+    /// called with the [`Self::restore_module_data`] method.
     ///
     /// In short it goes like this:
     ///
     /// ```ignore (not valid code)
-    /// let reset_data = type.save_module_data();
-    /// type.item(item)?;
-    /// type.set_back_info(reset_data);
+    /// let reset_data = renderer.save_module_data();
+    /// renderer.item(item)?;
+    /// renderer.restore_module_data(reset_data);
     /// ```
     fn save_module_data(&mut self) -> Self::ModuleData;
     /// Used to reset current module's information.
-    fn set_back_info(&mut self, info: Self::ModuleData);
+    fn restore_module_data(&mut self, info: Self::ModuleData);
 
     /// Renders a single non-module item. This means no recursive sub-item rendering is required.
     fn item(&mut self, item: clean::Item) -> Result<(), Error>;
@@ -91,7 +92,7 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
         for it in module.items {
             let info = cx.save_module_data();
             run_format_inner(cx, it, prof)?;
-            cx.set_back_info(info);
+            cx.restore_module_data(info);
         }
 
         cx.mod_item_out()?;
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index d18673c8140..5e3d06a4ae7 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -32,12 +32,11 @@ use std::iter::Peekable;
 use std::ops::{ControlFlow, Range};
 use std::path::PathBuf;
 use std::str::{self, CharIndices};
-use std::sync::OnceLock;
 
 use pulldown_cmark::{
     BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html,
 };
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Diag, DiagMessage};
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::TyCtxt;
@@ -1882,66 +1881,63 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<Rust
 
 #[derive(Clone, Default, Debug)]
 pub struct IdMap {
-    map: FxHashMap<Cow<'static, str>, usize>,
+    map: FxHashMap<String, usize>,
     existing_footnotes: usize,
 }
 
-// The map is pre-initialized and then can be used as is to prevent cloning it for each item
-// (in the sidebar rendering).
-static DEFAULT_ID_MAP: OnceLock<FxHashSet<&'static str>> = OnceLock::new();
-
-fn init_id_map() -> FxHashSet<&'static str> {
-    let mut map = FxHashSet::default();
-    // This is the list of IDs used in JavaScript.
-    map.insert("help");
-    map.insert("settings");
-    map.insert("not-displayed");
-    map.insert("alternative-display");
-    map.insert("search");
-    map.insert("crate-search");
-    map.insert("crate-search-div");
-    // This is the list of IDs used in HTML generated in Rust (including the ones
-    // used in tera template files).
-    map.insert("themeStyle");
-    map.insert("settings-menu");
-    map.insert("help-button");
-    map.insert("sidebar-button");
-    map.insert("main-content");
-    map.insert("toggle-all-docs");
-    map.insert("all-types");
-    map.insert("default-settings");
-    map.insert("sidebar-vars");
-    map.insert("copy-path");
-    map.insert("rustdoc-toc");
-    map.insert("rustdoc-modnav");
-    // This is the list of IDs used by rustdoc sections (but still generated by
-    // rustdoc).
-    map.insert("fields");
-    map.insert("variants");
-    map.insert("implementors-list");
-    map.insert("synthetic-implementors-list");
-    map.insert("foreign-impls");
-    map.insert("implementations");
-    map.insert("trait-implementations");
-    map.insert("synthetic-implementations");
-    map.insert("blanket-implementations");
-    map.insert("required-associated-types");
-    map.insert("provided-associated-types");
-    map.insert("provided-associated-consts");
-    map.insert("required-associated-consts");
-    map.insert("required-methods");
-    map.insert("provided-methods");
-    map.insert("dyn-compatibility");
-    map.insert("implementors");
-    map.insert("synthetic-implementors");
-    map.insert("implementations-list");
-    map.insert("trait-implementations-list");
-    map.insert("synthetic-implementations-list");
-    map.insert("blanket-implementations-list");
-    map.insert("deref-methods");
-    map.insert("layout");
-    map.insert("aliased-type");
-    map
+fn is_default_id(id: &str) -> bool {
+    matches!(
+        id,
+        // This is the list of IDs used in JavaScript.
+        "help"
+        | "settings"
+        | "not-displayed"
+        | "alternative-display"
+        | "search"
+        | "crate-search"
+        | "crate-search-div"
+        // This is the list of IDs used in HTML generated in Rust (including the ones
+        // used in tera template files).
+        | "themeStyle"
+        | "settings-menu"
+        | "help-button"
+        | "sidebar-button"
+        | "main-content"
+        | "toggle-all-docs"
+        | "all-types"
+        | "default-settings"
+        | "sidebar-vars"
+        | "copy-path"
+        | "rustdoc-toc"
+        | "rustdoc-modnav"
+        // This is the list of IDs used by rustdoc sections (but still generated by
+        // rustdoc).
+        | "fields"
+        | "variants"
+        | "implementors-list"
+        | "synthetic-implementors-list"
+        | "foreign-impls"
+        | "implementations"
+        | "trait-implementations"
+        | "synthetic-implementations"
+        | "blanket-implementations"
+        | "required-associated-types"
+        | "provided-associated-types"
+        | "provided-associated-consts"
+        | "required-associated-consts"
+        | "required-methods"
+        | "provided-methods"
+        | "dyn-compatibility"
+        | "implementors"
+        | "synthetic-implementors"
+        | "implementations-list"
+        | "trait-implementations-list"
+        | "synthetic-implementations-list"
+        | "blanket-implementations-list"
+        | "deref-methods"
+        | "layout"
+        | "aliased-type"
+    )
 }
 
 impl IdMap {
@@ -1953,7 +1949,7 @@ impl IdMap {
         let id = match self.map.get_mut(candidate.as_ref()) {
             None => {
                 let candidate = candidate.to_string();
-                if DEFAULT_ID_MAP.get_or_init(init_id_map).contains(candidate.as_str()) {
+                if is_default_id(&candidate) {
                     let id = format!("{}-{}", candidate, 1);
                     self.map.insert(candidate.into(), 2);
                     id
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 40468aef4db..2d5df75e7dc 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -601,7 +601,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         self.info
     }
 
-    fn set_back_info(&mut self, info: Self::ModuleData) {
+    fn restore_module_data(&mut self, info: Self::ModuleData) {
         self.info = info;
     }
 
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index c37506e3588..9827f97d28d 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -9,7 +9,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
-use rustc_span::{FileName, sym};
+use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, sym};
 use tracing::info;
 
 use crate::clean;
@@ -50,8 +50,14 @@ struct LocalSourcesCollector<'a, 'tcx> {
     src_root: &'a Path,
 }
 
-fn is_real_and_local(span: clean::Span, sess: &Session) -> bool {
-    span.cnum(sess) == LOCAL_CRATE && span.filename(sess).is_real()
+fn filename_real_and_local(span: clean::Span, sess: &Session) -> Option<RealFileName> {
+    if span.cnum(sess) == LOCAL_CRATE
+        && let FileName::Real(file) = span.filename(sess)
+    {
+        Some(file)
+    } else {
+        None
+    }
 }
 
 impl LocalSourcesCollector<'_, '_> {
@@ -60,16 +66,8 @@ impl LocalSourcesCollector<'_, '_> {
         let span = item.span(self.tcx);
         let Some(span) = span else { return };
         // skip all synthetic "files"
-        if !is_real_and_local(span, sess) {
-            return;
-        }
-        let filename = span.filename(sess);
-        let p = if let FileName::Real(file) = filename {
-            match file.into_local_path() {
-                Some(p) => p,
-                None => return,
-            }
-        } else {
+        let Some(p) = filename_real_and_local(span, sess).and_then(|file| file.into_local_path())
+        else {
             return;
         };
         if self.local_sources.contains_key(&*p) {
@@ -135,8 +133,7 @@ impl DocVisitor<'_> for SourceCollector<'_, '_> {
         // If we're not rendering sources, there's nothing to do.
         // If we're including source files, and we haven't seen this file yet,
         // then we need to render it out to the filesystem.
-        if is_real_and_local(span, sess) {
-            let filename = span.filename(sess);
+        if let Some(filename) = filename_real_and_local(span, sess) {
             let span = span.inner();
             let pos = sess.source_map().lookup_source_file(span.lo());
             let file_span = span.with_lo(pos.start_pos).with_hi(pos.end_position());
@@ -152,7 +149,7 @@ impl DocVisitor<'_> for SourceCollector<'_, '_> {
                         span,
                         format!(
                             "failed to render source code for `{filename}`: {e}",
-                            filename = filename.prefer_local(),
+                            filename = filename.to_string_lossy(FileNameDisplayPreference::Local),
                         ),
                     );
                     false
@@ -168,18 +165,13 @@ impl SourceCollector<'_, '_> {
     /// Renders the given filename into its corresponding HTML source file.
     fn emit_source(
         &mut self,
-        filename: &FileName,
+        file: &RealFileName,
         file_span: rustc_span::Span,
     ) -> Result<(), Error> {
-        let p = match *filename {
-            FileName::Real(ref file) => {
-                if let Some(local_path) = file.local_path() {
-                    local_path.to_path_buf()
-                } else {
-                    unreachable!("only the current crate should have sources emitted");
-                }
-            }
-            _ => return Ok(()),
+        let p = if let Some(local_path) = file.local_path() {
+            local_path.to_path_buf()
+        } else {
+            unreachable!("only the current crate should have sources emitted");
         };
         if self.emitted_local_sources.contains(&*p) {
             // We've already emitted this source
@@ -233,8 +225,10 @@ impl SourceCollector<'_, '_> {
         cur.push(&fname);
 
         let title = format!("{} - source", src_fname.to_string_lossy());
-        let desc =
-            format!("Source of the Rust file `{}`.", filename.prefer_remapped_unconditionaly());
+        let desc = format!(
+            "Source of the Rust file `{}`.",
+            file.to_string_lossy(FileNameDisplayPreference::Remapped)
+        );
         let page = layout::Page {
             title: &title,
             css_class: "src",
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 1c8303d4c20..bb967b7f163 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -321,8 +321,8 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
         MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), renderer)),
         TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), renderer)),
         ImplItem(i) => ItemEnum::Impl((*i).into_json(renderer)),
-        StaticItem(s) => ItemEnum::Static(s.into_json(renderer)),
-        ForeignStaticItem(s, _) => ItemEnum::Static(s.into_json(renderer)),
+        StaticItem(s) => ItemEnum::Static(convert_static(s, rustc_hir::Safety::Safe, renderer)),
+        ForeignStaticItem(s, safety) => ItemEnum::Static(convert_static(s, safety, renderer)),
         ForeignTypeItem => ItemEnum::ExternType,
         TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_json(renderer)),
         // FIXME(generic_const_items): Add support for generic free consts
@@ -831,17 +831,20 @@ impl FromClean<Box<clean::TypeAlias>> for TypeAlias {
     }
 }
 
-impl FromClean<clean::Static> for Static {
-    fn from_clean(stat: clean::Static, renderer: &JsonRenderer<'_>) -> Self {
-        let tcx = renderer.tcx;
-        Static {
-            type_: (*stat.type_).into_json(renderer),
-            is_mutable: stat.mutability == ast::Mutability::Mut,
-            expr: stat
-                .expr
-                .map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e)))
-                .unwrap_or_default(),
-        }
+fn convert_static(
+    stat: clean::Static,
+    safety: rustc_hir::Safety,
+    renderer: &JsonRenderer<'_>,
+) -> Static {
+    let tcx = renderer.tcx;
+    Static {
+        type_: (*stat.type_).into_json(renderer),
+        is_mutable: stat.mutability == ast::Mutability::Mut,
+        is_unsafe: safety == rustc_hir::Safety::Unsafe,
+        expr: stat
+            .expr
+            .map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e)))
+            .unwrap_or_default(),
     }
 }
 
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 9efcf6b4983..789a5614967 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -163,11 +163,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
     }
 
     fn save_module_data(&mut self) -> Self::ModuleData {
-        unreachable!("RUN_ON_MODULE = false should never call save_module_data")
+        unreachable!("RUN_ON_MODULE = false, should never call save_module_data")
     }
-
-    fn set_back_info(&mut self, _info: Self::ModuleData) {
-        unreachable!("RUN_ON_MODULE = false should never call set_back_info")
+    fn restore_module_data(&mut self, _info: Self::ModuleData) {
+        unreachable!("RUN_ON_MODULE = false, should never call set_back_info")
     }
 
     /// Inserts an item into the index. This should be used rather than directly calling insert on
@@ -248,7 +247,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
     }
 
     fn mod_item_in(&mut self, _item: &clean::Item) -> Result<(), Error> {
-        unreachable!("RUN_ON_MODULE = false should never call mod_item_in")
+        unreachable!("RUN_ON_MODULE = false, should never call mod_item_in")
     }
 
     fn after_krate(&mut self) -> Result<(), Error> {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 436d36d899e..8bc543f7e72 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -68,7 +68,7 @@ extern crate test;
 // See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs
 // about jemalloc.
 #[cfg(feature = "jemalloc")]
-extern crate jemalloc_sys;
+extern crate tikv_jemalloc_sys as jemalloc_sys;
 
 use std::env::{self, VarError};
 use std::io::{self, IsTerminal};
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 104d0d16c3c7c3fef2435fef6efb2d57b70fff7
+Subproject 1268e87bdbaed0693a9d782ccd5a21e2cab2de3
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index f553a78d766..84b33e3d860 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc
 /// This integer is incremented with every breaking change to the API,
 /// and is returned along with the JSON blob as [`Crate::format_version`].
 /// Consuming code should assert that this value matches the format version(s) that it supports.
-pub const FORMAT_VERSION: u32 = 36;
+pub const FORMAT_VERSION: u32 = 37;
 
 /// The root of the emitted JSON blob.
 ///
@@ -1238,6 +1238,22 @@ pub struct Static {
     ///
     /// It's not guaranteed that it'll match the actual source code for the initial value.
     pub expr: String,
+
+    /// Is the static `unsafe`?
+    ///
+    /// This is only true if it's in an `extern` block, and not explicity marked
+    /// as `safe`.
+    ///
+    /// ```rust
+    /// unsafe extern {
+    ///     static A: i32;      // unsafe
+    ///     safe static B: i32; // safe
+    /// }
+    ///
+    /// static C: i32 = 0;     // safe
+    /// static mut D: i32 = 0; // safe
+    /// ```
+    pub is_unsafe: bool,
 }
 
 /// A primitive type declaration. Declarations of this kind can only come from the core library.
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 4c39aaff66862cc0da52fe529aa1990bb8bb9a2
+Subproject 05f54fdc34310f458033af8a63ce1d699fae8bf
diff --git a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs
index fadd5272880..97cffeb098e 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs
@@ -9,7 +9,7 @@ use rustc_span::sym;
 
 pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
     if let AttrKind::Normal(normal_attr) = &attr.kind {
-        if let AttrArgs::Eq(_, AttrArgsEq::Ast(_)) = &normal_attr.item.args {
+        if let AttrArgs::Eq { value:  AttrArgsEq::Ast(_), .. } = &normal_attr.item.args {
             // `#[should_panic = ".."]` found, good
             return;
         }
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index c4a0c8f1865..022ed180ed8 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -744,7 +744,6 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::unit_types::LET_UNIT_VALUE_INFO,
     crate::unit_types::UNIT_ARG_INFO,
     crate::unit_types::UNIT_CMP_INFO,
-    crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO,
     crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO,
     crate::unnecessary_literal_bound::UNNECESSARY_LITERAL_BOUND_INFO,
     crate::unnecessary_map_on_constructor::UNNECESSARY_MAP_ON_CONSTRUCTOR_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
index 77dbe9b78a1..3ea792d8b83 100644
--- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
@@ -74,6 +74,8 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[
     #[clippy::version = "1.53.0"]
     ("clippy::filter_map", "clippy::manual_filter_map"),
     #[clippy::version = ""]
+    ("clippy::fn_address_comparisons", "unpredictable_function_pointer_comparisons"),
+    #[clippy::version = ""]
     ("clippy::identity_conversion", "clippy::useless_conversion"),
     #[clippy::version = "pre 1.29.0"]
     ("clippy::if_let_redundant_pattern_matching", "clippy::redundant_pattern_matching"),
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index b1d192adff9..c449a1a875b 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -7,7 +7,7 @@ use clippy_utils::{
     peel_middle_ty_refs,
 };
 use core::mem;
-use rustc_ast::util::parser::{PREC_PREFIX, PREC_UNAMBIGUOUS};
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
@@ -963,7 +963,7 @@ fn report<'tcx>(
             // expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's
             // `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary.
             /*
-            expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < PREC_PREFIX {
+            expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < ExprPrecedence::Prefix {
                 Cow::Owned(format!("({expr_str})"))
             } else {
                 expr_str
@@ -999,13 +999,13 @@ fn report<'tcx>(
                 data.first_expr.span,
                 state.msg,
                 |diag| {
-                    let (precedence, calls_field) = match cx.tcx.parent_hir_node(data.first_expr.hir_id) {
+                    let needs_paren = match cx.tcx.parent_hir_node(data.first_expr.hir_id) {
                         Node::Expr(e) => match e.kind {
-                            ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false),
-                            ExprKind::Call(..) => (PREC_UNAMBIGUOUS, matches!(expr.kind, ExprKind::Field(..))),
-                            _ => (e.precedence(), false),
+                            ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => false,
+                            ExprKind::Call(..) => expr.precedence() < ExprPrecedence::Unambiguous || matches!(expr.kind, ExprKind::Field(..)),
+                            _ => expr.precedence() < e.precedence(),
                         },
-                        _ => (0, false),
+                        _ => false,
                     };
                     let is_in_tuple = matches!(
                         get_parent_expr(cx, data.first_expr),
@@ -1016,7 +1016,7 @@ fn report<'tcx>(
                     );
 
                     let sugg = if !snip_is_macro
-                        && (calls_field || expr.precedence() < precedence)
+                        && needs_paren
                         && !has_enclosing_paren(&snip)
                         && !is_in_tuple
                     {
@@ -1049,16 +1049,16 @@ fn report<'tcx>(
                 }
             }
 
-            let (prefix, precedence) = match mutability {
+            let (prefix, needs_paren) = match mutability {
                 Some(mutability) if !ty.is_ref() => {
                     let prefix = match mutability {
                         Mutability::Not => "&",
                         Mutability::Mut => "&mut ",
                     };
-                    (prefix, PREC_PREFIX)
+                    (prefix, expr.precedence() < ExprPrecedence::Prefix)
                 },
-                None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", 0),
-                _ => ("", 0),
+                None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", false),
+                _ => ("", false),
             };
             span_lint_hir_and_then(
                 cx,
@@ -1070,7 +1070,7 @@ fn report<'tcx>(
                     let mut app = Applicability::MachineApplicable;
                     let (snip, snip_is_macro) =
                         snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app);
-                    let sugg = if !snip_is_macro && expr.precedence() < precedence && !has_enclosing_paren(&snip) {
+                    let sugg = if !snip_is_macro && needs_paren && !has_enclosing_paren(&snip) {
                         format!("{prefix}({snip})")
                     } else {
                         format!("{prefix}{snip}")
@@ -1157,7 +1157,7 @@ impl<'tcx> Dereferencing<'tcx> {
                         },
                         Some(parent) if !parent.span.from_expansion() => {
                             // Double reference might be needed at this point.
-                            if parent.precedence() == PREC_UNAMBIGUOUS {
+                            if parent.precedence() == ExprPrecedence::Unambiguous {
                                 // Parentheses would be needed here, don't lint.
                                 *outer_pat = None;
                             } else {
diff --git a/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs b/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs
index 49978d4a655..2182689f985 100644
--- a/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs
@@ -12,7 +12,7 @@ pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
         if !attr.span.from_expansion()
             && let AttrKind::Normal(ref normal) = attr.kind
             && normal.item.path == sym::doc
-            && let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args
+            && let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args
             && !attr.span.contains(meta.span)
             // Since the `include_str` is already expanded at this point, we can only take the
             // whole attribute snippet and then modify for our suggestion.
diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs
index 4f22931a4de..b38e362410e 100644
--- a/src/tools/clippy/clippy_lints/src/large_include_file.rs
+++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs
@@ -96,7 +96,7 @@ impl LateLintPass<'_> for LargeIncludeFile {
             && let AttrKind::Normal(ref normal) = attr.kind
             && let Some(doc) = attr.doc_str()
             && doc.as_str().len() as u64 > self.max_file_size
-            && let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args
+            && let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args
             && !attr.span.contains(meta.span)
             // Since the `include_str` is already expanded at this point, we can only take the
             // whole attribute snippet and then modify for our suggestion.
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index c9064df25ac..e80cca6e7db 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -363,7 +363,6 @@ mod uninhabited_references;
 mod uninit_vec;
 mod unit_return_expecting_ord;
 mod unit_types;
-mod unnamed_address;
 mod unnecessary_box_returns;
 mod unnecessary_literal_bound;
 mod unnecessary_map_on_constructor;
@@ -786,7 +785,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap));
     store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(conf)));
     store.register_late_pass(|_| Box::<redundant_pub_crate::RedundantPubCrate>::default());
-    store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress));
     store.register_late_pass(|_| Box::<dereference::Dereferencing<'_>>::default());
     store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse));
     store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend));
diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
index 35dc8e9aa4e..12719c4f94b 100644
--- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{indent_of, snippet, snippet_with_applicability};
 use clippy_utils::visitors::contains_break_or_continue;
 use rustc_ast::Mutability;
-use rustc_ast::util::parser::PREC_PREFIX;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind, is_range_literal};
 use rustc_lint::LateContext;
@@ -84,7 +84,7 @@ pub(super) fn check<'tcx>(
         if !prefix.is_empty()
             && (
                 // Precedence of internal expression is less than or equal to precedence of `&expr`.
-                arg_expression.precedence() <= PREC_PREFIX || is_range_literal(arg_expression)
+                arg_expression.precedence() <= ExprPrecedence::Prefix || is_range_literal(arg_expression)
             )
         {
             arg_snip = format!("({arg_snip})").into();
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs
index 9c6df4d8ac0..bac5cf88cfb 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs
@@ -7,7 +7,7 @@ use clippy_utils::{
     CaptureKind, can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res,
     path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while,
 };
-use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
 use rustc_hir::def::Res;
@@ -117,7 +117,7 @@ where
     // it's being passed by value.
     let scrutinee = peel_hir_expr_refs(scrutinee).0;
     let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
-    let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < PREC_UNAMBIGUOUS {
+    let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < ExprPrecedence::Unambiguous {
         format!("({scrutinee_str})")
     } else {
         scrutinee_str.into()
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
index 865a42b65c6..20e4d233525 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
@@ -148,7 +148,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
                                 _ => {},
                             }
                         }
-                        requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env());
+                        requires_copy |= !cx.type_is_copy_modulo_regions(ty);
                         break;
                     }
                 },
@@ -158,7 +158,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
         }
 
         if can_lint
-            && (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()))
+            && (!requires_copy || cx.type_is_copy_modulo_regions(arg_ty))
             // This case could be handled, but a fair bit of care would need to be taken.
             && (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.typing_env()))
         {
diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
index a0ba2aaf552..429afff9b66 100644
--- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs
+++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
@@ -2,7 +2,7 @@ use clippy_utils::consts::{self, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::sugg::has_enclosing_paren;
-use rustc_ast::util::parser::PREC_PREFIX;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
@@ -58,7 +58,7 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
     {
         let mut applicability = Applicability::MachineApplicable;
         let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability);
-        let suggestion = if !from_macro && exp.precedence() < PREC_PREFIX && !has_enclosing_paren(&snip) {
+        let suggestion = if !from_macro && exp.precedence() < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) {
             format!("-({snip})")
         } else {
             format!("-{snip}")
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index 4b96858d8f6..77abe7151f0 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -251,7 +251,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex
     {
         let mut applicability = Applicability::MachineApplicable;
         let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
-        let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())
+        let by_ref = !cx.type_is_copy_modulo_regions(caller_ty)
             && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
         let sugg = if let Some(else_inner) = r#else {
             if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index 79baa914b03..8e3472b1b5a 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::is_type_lang_item;
 use clippy_utils::{get_parent_expr, peel_middle_ty_refs};
-use rustc_ast::util::parser::PREC_PREFIX;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
 use rustc_lint::{LateContext, LateLintPass, Lint};
@@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
             let (expr_ty, expr_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(expr));
             let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed));
             let parent_expr = get_parent_expr(cx, expr);
-            let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence() > PREC_PREFIX);
+            let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence() > ExprPrecedence::Prefix);
 
             if expr_ty == indexed_ty {
                 if expr_ref_count > indexed_ref_count {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
index 8d71036084d..0d5cf45a5e6 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
@@ -1,7 +1,7 @@
 use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::sugg::Sugg;
-use rustc_ast::util::parser::AssocOp;
+use rustc_ast::util::parser::ExprPrecedence;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Node};
 use rustc_hir_typeck::cast::check_cast;
@@ -44,8 +44,7 @@ pub(super) fn check<'tcx>(
     };
 
     if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id)
-        && parent.precedence()
-            > i8::try_from(AssocOp::As.precedence()).expect("AssocOp always returns a precedence < 128")
+        && parent.precedence() > ExprPrecedence::Cast
     {
         sugg = format!("({sugg})");
     }
diff --git a/src/tools/clippy/clippy_lints/src/unnamed_address.rs b/src/tools/clippy/clippy_lints/src/unnamed_address.rs
deleted file mode 100644
index cd2dacc9f09..00000000000
--- a/src/tools/clippy/clippy_lints/src/unnamed_address.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-use clippy_utils::diagnostics::span_lint;
-use rustc_hir::{BinOpKind, Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty;
-use rustc_session::declare_lint_pass;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for comparisons with an address of a function item.
-    ///
-    /// ### Why is this bad?
-    /// Function item address is not guaranteed to be unique and could vary
-    /// between different code generation units. Furthermore different function items could have
-    /// the same address after being merged together.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// type F = fn();
-    /// fn a() {}
-    /// let f: F = a;
-    /// if f == a {
-    ///     // ...
-    /// }
-    /// ```
-    #[clippy::version = "1.44.0"]
-    pub FN_ADDRESS_COMPARISONS,
-    correctness,
-    "comparison with an address of a function item"
-}
-
-declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS]);
-
-impl LateLintPass<'_> for UnnamedAddress {
-    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        fn is_comparison(binop: BinOpKind) -> bool {
-            matches!(
-                binop,
-                BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt
-            )
-        }
-
-        fn is_fn_def(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-            matches!(cx.typeck_results().expr_ty(expr).kind(), ty::FnDef(..))
-        }
-
-        if let ExprKind::Binary(binop, left, right) = expr.kind
-            && is_comparison(binop.node)
-            && cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr()
-            && cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr()
-            && (is_fn_def(cx, left) || is_fn_def(cx, right))
-        {
-            span_lint(
-                cx,
-                FN_ADDRESS_COMPARISONS,
-                expr.span,
-                "comparing with a non-unique address of a function item",
-            );
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index c90f4a6ebfe..620a9b56eb5 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -872,8 +872,8 @@ pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool {
     match (l, r) {
         (Empty, Empty) => true,
         (Delimited(la), Delimited(ra)) => eq_delim_args(la, ra),
-        (Eq(_, AttrArgsEq::Ast(le)), Eq(_, AttrArgsEq::Ast(re))) => eq_expr(le, re),
-        (Eq(_, AttrArgsEq::Hir(ll)), Eq(_, AttrArgsEq::Hir(rl))) => ll.kind == rl.kind,
+        (Eq { value: AttrArgsEq::Ast(le), .. }, Eq{ value: AttrArgsEq::Ast(re), .. }) => eq_expr(le, re),
+        (Eq { value: AttrArgsEq::Hir(ll), .. }, Eq{ value: AttrArgsEq::Hir(rl), .. }) => ll.kind == rl.kind,
         _ => false,
     }
 }
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 39c9d234a1a..260d1b801e3 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -38,7 +38,7 @@ pub use type_certainty::expr_type_is_certain;
 
 /// Checks if the given type implements copy.
 pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
-    ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())
+    cx.type_is_copy_modulo_regions(ty)
 }
 
 /// This checks whether a given type is known to implement Debug.
diff --git a/src/tools/clippy/tests/ui/fn_address_comparisons.rs b/src/tools/clippy/tests/ui/fn_address_comparisons.rs
deleted file mode 100644
index 35535bd4fdd..00000000000
--- a/src/tools/clippy/tests/ui/fn_address_comparisons.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use std::fmt::Debug;
-use std::ptr;
-use std::rc::Rc;
-use std::sync::Arc;
-
-fn a() {}
-
-#[warn(clippy::fn_address_comparisons)]
-fn main() {
-    type F = fn();
-    let f: F = a;
-    let g: F = f;
-
-    // These should fail:
-    let _ = f == a;
-    //~^ ERROR: comparing with a non-unique address of a function item
-    //~| NOTE: `-D clippy::fn-address-comparisons` implied by `-D warnings`
-    let _ = f != a;
-    //~^ ERROR: comparing with a non-unique address of a function item
-
-    // These should be fine:
-    let _ = f == g;
-}
diff --git a/src/tools/clippy/tests/ui/fn_address_comparisons.stderr b/src/tools/clippy/tests/ui/fn_address_comparisons.stderr
deleted file mode 100644
index e6de7e35807..00000000000
--- a/src/tools/clippy/tests/ui/fn_address_comparisons.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error: comparing with a non-unique address of a function item
-  --> tests/ui/fn_address_comparisons.rs:15:13
-   |
-LL |     let _ = f == a;
-   |             ^^^^^^
-   |
-   = note: `-D clippy::fn-address-comparisons` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::fn_address_comparisons)]`
-
-error: comparing with a non-unique address of a function item
-  --> tests/ui/fn_address_comparisons.rs:18:13
-   |
-LL |     let _ = f != a;
-   |             ^^^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 0d6e07aa546..47149622ef7 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -59,6 +59,7 @@
 #![allow(unknown_lints)]
 #![allow(unused_labels)]
 #![allow(ambiguous_wide_pointer_comparisons)]
+#![allow(unpredictable_function_pointer_comparisons)]
 #![allow(clippy::reversed_empty_ranges)]
 #![warn(clippy::almost_complete_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
 #![warn(clippy::disallowed_names)] //~ ERROR: lint `clippy::blacklisted_name`
@@ -74,6 +75,7 @@
 #![warn(clippy::mixed_read_write_in_expression)] //~ ERROR: lint `clippy::eval_order_dependence`
 #![warn(clippy::manual_find_map)] //~ ERROR: lint `clippy::find_map`
 #![warn(clippy::manual_filter_map)] //~ ERROR: lint `clippy::filter_map`
+#![warn(unpredictable_function_pointer_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
 #![warn(clippy::useless_conversion)] //~ ERROR: lint `clippy::identity_conversion`
 #![warn(clippy::redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching`
 #![warn(clippy::match_result_ok)] //~ ERROR: lint `clippy::if_let_some_result`
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 2ac59718786..7a78a5d280d 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -59,6 +59,7 @@
 #![allow(unknown_lints)]
 #![allow(unused_labels)]
 #![allow(ambiguous_wide_pointer_comparisons)]
+#![allow(unpredictable_function_pointer_comparisons)]
 #![allow(clippy::reversed_empty_ranges)]
 #![warn(clippy::almost_complete_letter_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
 #![warn(clippy::blacklisted_name)] //~ ERROR: lint `clippy::blacklisted_name`
@@ -74,6 +75,7 @@
 #![warn(clippy::eval_order_dependence)] //~ ERROR: lint `clippy::eval_order_dependence`
 #![warn(clippy::find_map)] //~ ERROR: lint `clippy::find_map`
 #![warn(clippy::filter_map)] //~ ERROR: lint `clippy::filter_map`
+#![warn(clippy::fn_address_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
 #![warn(clippy::identity_conversion)] //~ ERROR: lint `clippy::identity_conversion`
 #![warn(clippy::if_let_redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching`
 #![warn(clippy::if_let_some_result)] //~ ERROR: lint `clippy::if_let_some_result`
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index a5ae727b7ee..dc24bc16d0e 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> tests/ui/rename.rs:63:9
+  --> tests/ui/rename.rs:64:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -8,394 +8,400 @@ LL | #![warn(clippy::almost_complete_letter_range)]
    = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> tests/ui/rename.rs:64:9
+  --> tests/ui/rename.rs:65:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_conditions`
-  --> tests/ui/rename.rs:65:9
+  --> tests/ui/rename.rs:66:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_conditions`
-  --> tests/ui/rename.rs:66:9
+  --> tests/ui/rename.rs:67:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
 
 error: lint `clippy::blocks_in_if_conditions` has been renamed to `clippy::blocks_in_conditions`
-  --> tests/ui/rename.rs:67:9
+  --> tests/ui/rename.rs:68:9
    |
 LL | #![warn(clippy::blocks_in_if_conditions)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> tests/ui/rename.rs:68:9
+  --> tests/ui/rename.rs:69:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> tests/ui/rename.rs:69:9
+  --> tests/ui/rename.rs:70:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> tests/ui/rename.rs:70:9
+  --> tests/ui/rename.rs:71:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> tests/ui/rename.rs:71:9
+  --> tests/ui/rename.rs:72:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> tests/ui/rename.rs:72:9
+  --> tests/ui/rename.rs:73:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> tests/ui/rename.rs:73:9
+  --> tests/ui/rename.rs:74:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> tests/ui/rename.rs:74:9
+  --> tests/ui/rename.rs:75:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map`
-  --> tests/ui/rename.rs:75:9
+  --> tests/ui/rename.rs:76:9
    |
 LL | #![warn(clippy::find_map)]
    |         ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map`
 
 error: lint `clippy::filter_map` has been renamed to `clippy::manual_filter_map`
-  --> tests/ui/rename.rs:76:9
+  --> tests/ui/rename.rs:77:9
    |
 LL | #![warn(clippy::filter_map)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_filter_map`
 
+error: lint `clippy::fn_address_comparisons` has been renamed to `unpredictable_function_pointer_comparisons`
+  --> tests/ui/rename.rs:78:9
+   |
+LL | #![warn(clippy::fn_address_comparisons)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unpredictable_function_pointer_comparisons`
+
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> tests/ui/rename.rs:77:9
+  --> tests/ui/rename.rs:79:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_redundant_pattern_matching` has been renamed to `clippy::redundant_pattern_matching`
-  --> tests/ui/rename.rs:78:9
+  --> tests/ui/rename.rs:80:9
    |
 LL | #![warn(clippy::if_let_redundant_pattern_matching)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_pattern_matching`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> tests/ui/rename.rs:79:9
+  --> tests/ui/rename.rs:81:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl`
-  --> tests/ui/rename.rs:80:9
+  --> tests/ui/rename.rs:82:9
    |
 LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl`
 
 error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl`
-  --> tests/ui/rename.rs:81:9
+  --> tests/ui/rename.rs:83:9
    |
 LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl`
 
 error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
-  --> tests/ui/rename.rs:82:9
+  --> tests/ui/rename.rs:84:9
    |
 LL | #![warn(clippy::integer_arithmetic)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> tests/ui/rename.rs:83:9
+  --> tests/ui/rename.rs:85:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> tests/ui/rename.rs:84:9
+  --> tests/ui/rename.rs:86:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> tests/ui/rename.rs:85:9
+  --> tests/ui/rename.rs:87:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> tests/ui/rename.rs:86:9
+  --> tests/ui/rename.rs:88:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> tests/ui/rename.rs:87:9
+  --> tests/ui/rename.rs:89:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> tests/ui/rename.rs:88:9
+  --> tests/ui/rename.rs:90:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> tests/ui/rename.rs:89:9
+  --> tests/ui/rename.rs:91:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::overflow_check_conditional` has been renamed to `clippy::panicking_overflow_checks`
-  --> tests/ui/rename.rs:90:9
+  --> tests/ui/rename.rs:92:9
    |
 LL | #![warn(clippy::overflow_check_conditional)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::panicking_overflow_checks`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> tests/ui/rename.rs:91:9
+  --> tests/ui/rename.rs:93:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> tests/ui/rename.rs:92:9
+  --> tests/ui/rename.rs:94:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> tests/ui/rename.rs:93:9
+  --> tests/ui/rename.rs:95:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> tests/ui/rename.rs:94:9
+  --> tests/ui/rename.rs:96:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> tests/ui/rename.rs:95:9
+  --> tests/ui/rename.rs:97:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> tests/ui/rename.rs:96:9
+  --> tests/ui/rename.rs:98:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::thread_local_initializer_can_be_made_const` has been renamed to `clippy::missing_const_for_thread_local`
-  --> tests/ui/rename.rs:97:9
+  --> tests/ui/rename.rs:99:9
    |
 LL | #![warn(clippy::thread_local_initializer_can_be_made_const)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::missing_const_for_thread_local`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> tests/ui/rename.rs:98:9
+  --> tests/ui/rename.rs:100:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default`
-  --> tests/ui/rename.rs:99:9
+  --> tests/ui/rename.rs:101:9
    |
 LL | #![warn(clippy::unwrap_or_else_default)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> tests/ui/rename.rs:100:9
+  --> tests/ui/rename.rs:102:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting`
-  --> tests/ui/rename.rs:101:9
+  --> tests/ui/rename.rs:103:9
    |
 LL | #![warn(clippy::cast_ref_to_mut)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting`
 
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> tests/ui/rename.rs:102:9
+  --> tests/ui/rename.rs:104:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
 error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
-  --> tests/ui/rename.rs:103:9
+  --> tests/ui/rename.rs:105:9
    |
 LL | #![warn(clippy::cmp_nan)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> tests/ui/rename.rs:104:9
+  --> tests/ui/rename.rs:106:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
-  --> tests/ui/rename.rs:105:9
+  --> tests/ui/rename.rs:107:9
    |
 LL | #![warn(clippy::drop_copy)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
 
 error: lint `clippy::drop_ref` has been renamed to `dropping_references`
-  --> tests/ui/rename.rs:106:9
+  --> tests/ui/rename.rs:108:9
    |
 LL | #![warn(clippy::drop_ref)]
    |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
 
 error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks`
-  --> tests/ui/rename.rs:107:9
+  --> tests/ui/rename.rs:109:9
    |
 LL | #![warn(clippy::fn_null_check)]
    |         ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> tests/ui/rename.rs:108:9
+  --> tests/ui/rename.rs:110:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> tests/ui/rename.rs:109:9
+  --> tests/ui/rename.rs:111:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> tests/ui/rename.rs:110:9
+  --> tests/ui/rename.rs:112:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
-  --> tests/ui/rename.rs:111:9
+  --> tests/ui/rename.rs:113:9
    |
 LL | #![warn(clippy::forget_copy)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
 
 error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
-  --> tests/ui/rename.rs:112:9
+  --> tests/ui/rename.rs:114:9
    |
 LL | #![warn(clippy::forget_ref)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> tests/ui/rename.rs:113:9
+  --> tests/ui/rename.rs:115:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> tests/ui/rename.rs:114:9
+  --> tests/ui/rename.rs:116:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> tests/ui/rename.rs:115:9
+  --> tests/ui/rename.rs:117:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
-  --> tests/ui/rename.rs:116:9
+  --> tests/ui/rename.rs:118:9
    |
 LL | #![warn(clippy::invalid_utf8_in_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> tests/ui/rename.rs:117:9
+  --> tests/ui/rename.rs:119:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs`
-  --> tests/ui/rename.rs:118:9
+  --> tests/ui/rename.rs:120:9
    |
 LL | #![warn(clippy::maybe_misused_cfg)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> tests/ui/rename.rs:119:9
+  --> tests/ui/rename.rs:121:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs`
-  --> tests/ui/rename.rs:120:9
+  --> tests/ui/rename.rs:122:9
    |
 LL | #![warn(clippy::mismatched_target_os)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> tests/ui/rename.rs:121:9
+  --> tests/ui/rename.rs:123:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> tests/ui/rename.rs:122:9
+  --> tests/ui/rename.rs:124:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`
-  --> tests/ui/rename.rs:123:9
+  --> tests/ui/rename.rs:125:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries`
 
 error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
-  --> tests/ui/rename.rs:124:9
+  --> tests/ui/rename.rs:126:9
    |
 LL | #![warn(clippy::undropped_manually_drops)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> tests/ui/rename.rs:125:9
+  --> tests/ui/rename.rs:127:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> tests/ui/rename.rs:126:9
+  --> tests/ui/rename.rs:128:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
 error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons`
-  --> tests/ui/rename.rs:127:9
+  --> tests/ui/rename.rs:129:9
    |
 LL | #![warn(clippy::vtable_address_comparisons)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons`
 
 error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges`
-  --> tests/ui/rename.rs:128:9
+  --> tests/ui/rename.rs:130:9
    |
 LL | #![warn(clippy::reverse_range_loop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges`
 
-error: aborting due to 66 previous errors
+error: aborting due to 67 previous errors
 
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index e6fbba943a4..36f876bcdc6 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -1,4 +1,4 @@
-use std::collections::{HashMap, HashSet};
+use std::collections::{BTreeSet, HashMap, HashSet};
 use std::ffi::OsString;
 use std::path::{Path, PathBuf};
 use std::process::Command;
@@ -486,6 +486,9 @@ impl Config {
     }
 }
 
+/// Known widths of `target_has_atomic`.
+pub const KNOWN_TARGET_HAS_ATOMIC_WIDTHS: &[&str] = &["8", "16", "32", "64", "128", "ptr"];
+
 #[derive(Debug, Clone)]
 pub struct TargetCfgs {
     pub current: TargetCfg,
@@ -611,6 +614,17 @@ impl TargetCfgs {
                 ("panic", Some("abort")) => cfg.panic = PanicStrategy::Abort,
                 ("panic", Some("unwind")) => cfg.panic = PanicStrategy::Unwind,
                 ("panic", other) => panic!("unexpected value for panic cfg: {other:?}"),
+
+                ("target_has_atomic", Some(width))
+                    if KNOWN_TARGET_HAS_ATOMIC_WIDTHS.contains(&width) =>
+                {
+                    cfg.target_has_atomic.insert(width.to_string());
+                }
+                ("target_has_atomic", Some(other)) => {
+                    panic!("unexpected value for `target_has_atomic` cfg: {other:?}")
+                }
+                // Nightly-only std-internal impl detail.
+                ("target_has_atomic", None) => {}
                 _ => {}
             }
         }
@@ -645,6 +659,12 @@ pub struct TargetCfg {
     pub(crate) xray: bool,
     #[serde(default = "default_reloc_model")]
     pub(crate) relocation_model: String,
+
+    // Not present in target cfg json output, additional derived information.
+    #[serde(skip)]
+    /// Supported target atomic widths: e.g. `8` to `128` or `ptr`. This is derived from the builtin
+    /// `target_has_atomic` `cfg`s e.g. `target_has_atomic="8"`.
+    pub(crate) target_has_atomic: BTreeSet<String>,
 }
 
 impl TargetCfg {
diff --git a/src/tools/compiletest/src/compute_diff.rs b/src/tools/compiletest/src/compute_diff.rs
index 92c80c27de0..3ace6c5b6d7 100644
--- a/src/tools/compiletest/src/compute_diff.rs
+++ b/src/tools/compiletest/src/compute_diff.rs
@@ -144,7 +144,7 @@ where
     }
 
     if !wrote_data {
-        println!("note: diff is identical to nightly rustdoc");
+        eprintln!("note: diff is identical to nightly rustdoc");
         assert!(diff_output.metadata().unwrap().len() == 0);
         return false;
     } else if verbose {
diff --git a/src/tools/compiletest/src/debuggers.rs b/src/tools/compiletest/src/debuggers.rs
index b605bc813f1..e75c8a5993e 100644
--- a/src/tools/compiletest/src/debuggers.rs
+++ b/src/tools/compiletest/src/debuggers.rs
@@ -20,7 +20,7 @@ pub(crate) fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
     }
 
     if config.remote_test_client.is_some() && !config.target.contains("android") {
-        println!(
+        eprintln!(
             "WARNING: debuginfo tests are not available when \
              testing with remote"
         );
@@ -28,7 +28,7 @@ pub(crate) fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
     }
 
     if config.target.contains("android") {
-        println!(
+        eprintln!(
             "{} debug-info test uses tcp 5039 port.\
              please reserve it",
             config.target
@@ -50,7 +50,7 @@ pub(crate) fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
     config.lldb_python_dir.as_ref()?;
 
     if let Some(350) = config.lldb_version {
-        println!(
+        eprintln!(
             "WARNING: The used version of LLDB (350) has a \
              known issue that breaks debuginfo tests. See \
              issue #32520 for more information. Skipping all \
diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs
index 952533e904c..5638d471890 100644
--- a/src/tools/compiletest/src/directive-list.rs
+++ b/src/tools/compiletest/src/directive-list.rs
@@ -17,7 +17,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "check-run-results",
     "check-stdout",
     "check-test-line-numbers-match",
-    "compare-output-lines-by-subset",
     "compile-flags",
     "doc-flags",
     "dont-check-compiler-stderr",
@@ -154,6 +153,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "needs-sanitizer-thread",
     "needs-std-debug-assertions",
     "needs-symlink",
+    "needs-target-has-atomic",
     "needs-threads",
     "needs-unwind",
     "needs-wasmtime",
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index fe4c5fdd8b5..91558d0c898 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -115,9 +115,6 @@ pub struct TestProps {
     pub dont_check_compiler_stdout: bool,
     // For UI tests, allows compiler to generate arbitrary output to stderr
     pub dont_check_compiler_stderr: bool,
-    // When checking the output of stdout or stderr check
-    // that the lines of expected output are a subset of the actual output.
-    pub compare_output_lines_by_subset: bool,
     // Don't force a --crate-type=dylib flag on the command line
     //
     // Set this for example if you have an auxiliary test file that contains
@@ -240,7 +237,6 @@ mod directives {
     pub const KNOWN_BUG: &'static str = "known-bug";
     pub const TEST_MIR_PASS: &'static str = "test-mir-pass";
     pub const REMAP_SRC_BASE: &'static str = "remap-src-base";
-    pub const COMPARE_OUTPUT_LINES_BY_SUBSET: &'static str = "compare-output-lines-by-subset";
     pub const LLVM_COV_FLAGS: &'static str = "llvm-cov-flags";
     pub const FILECHECK_FLAGS: &'static str = "filecheck-flags";
     pub const NO_AUTO_CHECK_CFG: &'static str = "no-auto-check-cfg";
@@ -274,7 +270,6 @@ impl TestProps {
             check_run_results: false,
             dont_check_compiler_stdout: false,
             dont_check_compiler_stderr: false,
-            compare_output_lines_by_subset: false,
             no_prefer_dynamic: false,
             pretty_mode: "normal".to_string(),
             pretty_compare_only: false,
@@ -550,11 +545,6 @@ impl TestProps {
                         |s| s.trim().to_string(),
                     );
                     config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base);
-                    config.set_name_directive(
-                        ln,
-                        COMPARE_OUTPUT_LINES_BY_SUBSET,
-                        &mut self.compare_output_lines_by_subset,
-                    );
 
                     if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) {
                         self.llvm_cov_flags.extend(split_flags(&flags));
@@ -1135,6 +1125,8 @@ fn parse_normalize_rule(header: &str) -> Option<(String, String)> {
     .captures(header)?;
     let regex = captures["regex"].to_owned();
     let replacement = captures["replacement"].to_owned();
+    // FIXME: Support escaped new-line in strings.
+    let replacement = replacement.replace("\\n", "\n");
     Some((regex, replacement))
 }
 
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index 77570c58db5..e19dcd992fc 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -1,4 +1,4 @@
-use crate::common::{Config, Sanitizer};
+use crate::common::{Config, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer};
 use crate::header::{IgnoreDecision, llvm_has_libzstd};
 
 pub(super) fn handle_needs(
@@ -171,11 +171,54 @@ pub(super) fn handle_needs(
         },
     ];
 
-    let (name, comment) = match ln.split_once([':', ' ']) {
-        Some((name, comment)) => (name, Some(comment)),
+    let (name, rest) = match ln.split_once([':', ' ']) {
+        Some((name, rest)) => (name, Some(rest)),
         None => (ln, None),
     };
 
+    // FIXME(jieyouxu): tighten up this parsing to reject using both `:` and ` ` as means to
+    // delineate value.
+    if name == "needs-target-has-atomic" {
+        let Some(rest) = rest else {
+            return IgnoreDecision::Error {
+                message: "expected `needs-target-has-atomic` to have a comma-separated list of atomic widths".to_string(),
+            };
+        };
+
+        // Expect directive value to be a list of comma-separated atomic widths.
+        let specified_widths = rest
+            .split(',')
+            .map(|width| width.trim())
+            .map(ToString::to_string)
+            .collect::<Vec<String>>();
+
+        for width in &specified_widths {
+            if !KNOWN_TARGET_HAS_ATOMIC_WIDTHS.contains(&width.as_str()) {
+                return IgnoreDecision::Error {
+                    message: format!(
+                        "unknown width specified in `needs-target-has-atomic`: `{width}` is not a \
+                        known `target_has_atomic_width`, known values are `{:?}`",
+                        KNOWN_TARGET_HAS_ATOMIC_WIDTHS
+                    ),
+                };
+            }
+        }
+
+        let satisfies_all_specified_widths = specified_widths
+            .iter()
+            .all(|specified| config.target_cfg().target_has_atomic.contains(specified));
+        if satisfies_all_specified_widths {
+            return IgnoreDecision::Continue;
+        } else {
+            return IgnoreDecision::Ignore {
+                reason: format!(
+                    "skipping test as target does not support all of the required `target_has_atomic` widths `{:?}`",
+                    specified_widths
+                ),
+            };
+        }
+    }
+
     if !name.starts_with("needs-") {
         return IgnoreDecision::Continue;
     }
@@ -193,7 +236,7 @@ pub(super) fn handle_needs(
                 break;
             } else {
                 return IgnoreDecision::Ignore {
-                    reason: if let Some(comment) = comment {
+                    reason: if let Some(comment) = rest {
                         format!("{} ({})", need.ignore_reason, comment.trim())
                     } else {
                         need.ignore_reason.into()
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 4d75c38dd32..cd7c6f8361e 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -787,3 +787,40 @@ fn test_not_trailing_directive() {
     run_path(&mut poisoned, Path::new("a.rs"), b"//@ revisions: incremental");
     assert!(!poisoned);
 }
+
+#[test]
+fn test_needs_target_has_atomic() {
+    use std::collections::BTreeSet;
+
+    // `x86_64-unknown-linux-gnu` supports `["8", "16", "32", "64", "ptr"]` but not `128`.
+
+    let config = cfg().target("x86_64-unknown-linux-gnu").build();
+    // Expectation sanity check.
+    assert_eq!(
+        config.target_cfg().target_has_atomic,
+        BTreeSet::from([
+            "8".to_string(),
+            "16".to_string(),
+            "32".to_string(),
+            "64".to_string(),
+            "ptr".to_string()
+        ]),
+        "expected `x86_64-unknown-linux-gnu` to not have 128-bit atomic support"
+    );
+
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8"));
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 16"));
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 32"));
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 64"));
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: ptr"));
+
+    assert!(check_ignore(&config, "//@ needs-target-has-atomic: 128"));
+
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8,16,32,64,ptr"));
+
+    assert!(check_ignore(&config, "//@ needs-target-has-atomic: 8,16,32,64,ptr,128"));
+
+    // Check whitespace between widths is permitted.
+    assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8, ptr"));
+    assert!(check_ignore(&config, "//@ needs-target-has-atomic: 8, ptr, 128"));
+}
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index bf4a3124075..447568065f5 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -188,8 +188,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
     let (argv0, args_) = args.split_first().unwrap();
     if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
         let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
-        println!("{}", opts.usage(&message));
-        println!();
+        eprintln!("{}", opts.usage(&message));
+        eprintln!();
         panic!()
     }
 
@@ -200,8 +200,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
 
     if matches.opt_present("h") || matches.opt_present("help") {
         let message = format!("Usage: {} [OPTIONS]  [TESTNAME...]", argv0);
-        println!("{}", opts.usage(&message));
-        println!();
+        eprintln!("{}", opts.usage(&message));
+        eprintln!();
         panic!()
     }
 
@@ -501,7 +501,7 @@ pub fn run_tests(config: Arc<Config>) {
             // easy to miss which tests failed, and as such fail to reproduce
             // the failure locally.
 
-            println!(
+            eprintln!(
                 "Some tests failed in compiletest suite={}{} mode={} host={} target={}",
                 config.suite,
                 config
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 93e5980f1f5..8c747a1d93f 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -350,10 +350,13 @@ impl<'test> TestCx<'test> {
             }
         } else {
             if proc_res.status.success() {
-                self.fatal_proc_rec(
-                    &format!("{} test compiled successfully!", self.config.mode)[..],
-                    proc_res,
-                );
+                {
+                    self.error(&format!("{} test did not emit an error", self.config.mode));
+                    if self.config.mode == crate::common::Mode::Ui {
+                        println!("note: by default, ui tests are expected not to compile");
+                    }
+                    proc_res.fatal(None, || ());
+                };
             }
 
             if !self.props.dont_check_failure_status {
@@ -771,20 +774,20 @@ impl<'test> TestCx<'test> {
                 unexpected.len(),
                 not_found.len()
             ));
-            println!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline);
+            eprintln!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline);
             if !unexpected.is_empty() {
-                println!("{}", "--- unexpected errors (from JSON output) ---".green());
+                eprintln!("{}", "--- unexpected errors (from JSON output) ---".green());
                 for error in &unexpected {
-                    println!("{}", error.render_for_expected());
+                    eprintln!("{}", error.render_for_expected());
                 }
-                println!("{}", "---".green());
+                eprintln!("{}", "---".green());
             }
             if !not_found.is_empty() {
-                println!("{}", "--- not found errors (from test file) ---".red());
+                eprintln!("{}", "--- not found errors (from test file) ---".red());
                 for error in &not_found {
-                    println!("{}", error.render_for_expected());
+                    eprintln!("{}", error.render_for_expected());
                 }
-                println!("{}", "---\n".red());
+                eprintln!("{}", "---\n".red());
             }
             panic!("errors differ from expected");
         }
@@ -1873,18 +1876,18 @@ impl<'test> TestCx<'test> {
 
     fn maybe_dump_to_stdout(&self, out: &str, err: &str) {
         if self.config.verbose {
-            println!("------stdout------------------------------");
-            println!("{}", out);
-            println!("------stderr------------------------------");
-            println!("{}", err);
-            println!("------------------------------------------");
+            eprintln!("------stdout------------------------------");
+            eprintln!("{}", out);
+            eprintln!("------stderr------------------------------");
+            eprintln!("{}", err);
+            eprintln!("------------------------------------------");
         }
     }
 
     fn error(&self, err: &str) {
         match self.revision {
-            Some(rev) => println!("\nerror in revision `{}`: {}", rev, err),
-            None => println!("\nerror: {}", err),
+            Some(rev) => eprintln!("\nerror in revision `{}`: {}", rev, err),
+            None => eprintln!("\nerror: {}", err),
         }
     }
 
@@ -1969,7 +1972,7 @@ impl<'test> TestCx<'test> {
         if !self.config.has_html_tidy {
             return;
         }
-        println!("info: generating a diff against nightly rustdoc");
+        eprintln!("info: generating a diff against nightly rustdoc");
 
         let suffix =
             self.safe_revision().map_or("nightly".into(), |path| path.to_owned() + "-nightly");
@@ -2079,7 +2082,7 @@ impl<'test> TestCx<'test> {
                 .output()
                 .unwrap();
             assert!(output.status.success());
-            println!("{}", String::from_utf8_lossy(&output.stdout));
+            eprintln!("{}", String::from_utf8_lossy(&output.stdout));
             eprintln!("{}", String::from_utf8_lossy(&output.stderr));
         } else {
             use colored::Colorize;
@@ -2479,7 +2482,7 @@ impl<'test> TestCx<'test> {
                 )"#
             )
             .replace_all(&output, |caps: &Captures<'_>| {
-                println!("{}", &caps[0]);
+                eprintln!("{}", &caps[0]);
                 caps[0].replace(r"\", "/")
             })
             .replace("\r\n", "\n")
@@ -2541,13 +2544,10 @@ impl<'test> TestCx<'test> {
             return 0;
         }
 
-        // If `compare-output-lines-by-subset` is not explicitly enabled then
-        // auto-enable it when a `runner` is in use since wrapper tools might
-        // provide extra output on failure, for example a WebAssembly runtime
-        // might print the stack trace of an `unreachable` instruction by
-        // default.
-        let compare_output_by_lines =
-            self.props.compare_output_lines_by_subset || self.config.runner.is_some();
+        // Wrapper tools set by `runner` might provide extra output on failure,
+        // for example a WebAssembly runtime might print the stack trace of an
+        // `unreachable` instruction by default.
+        let compare_output_by_lines = self.config.runner.is_some();
 
         let tmp;
         let (expected, actual): (&str, &str) = if compare_output_by_lines {
@@ -2581,16 +2581,16 @@ impl<'test> TestCx<'test> {
         if let Err(err) = fs::write(&actual_path, &actual) {
             self.fatal(&format!("failed to write {stream} to `{actual_path:?}`: {err}",));
         }
-        println!("Saved the actual {stream} to {actual_path:?}");
+        eprintln!("Saved the actual {stream} to {actual_path:?}");
 
         let expected_path =
             expected_output_path(self.testpaths, self.revision, &self.config.compare_mode, stream);
 
         if !self.config.bless {
             if expected.is_empty() {
-                println!("normalized {}:\n{}\n", stream, actual);
+                eprintln!("normalized {}:\n{}\n", stream, actual);
             } else {
-                println!("diff of {stream}:\n");
+                eprintln!("diff of {stream}:\n");
                 if let Some(diff_command) = self.config.diff_command.as_deref() {
                     let mut args = diff_command.split_whitespace();
                     let name = args.next().unwrap();
@@ -2625,10 +2625,10 @@ impl<'test> TestCx<'test> {
             if let Err(err) = fs::write(&expected_path, &actual) {
                 self.fatal(&format!("failed to write {stream} to `{expected_path:?}`: {err}"));
             }
-            println!("Blessing the {stream} of {test_name} in {expected_path:?}");
+            eprintln!("Blessing the {stream} of {test_name} in {expected_path:?}");
         }
 
-        println!("\nThe actual {0} differed from the expected {0}.", stream);
+        eprintln!("\nThe actual {0} differed from the expected {0}.", stream);
 
         if self.config.bless { 0 } else { 1 }
     }
@@ -2707,7 +2707,7 @@ impl<'test> TestCx<'test> {
         fs::create_dir_all(&incremental_dir).unwrap();
 
         if self.config.verbose {
-            println!("init_incremental_test: incremental_dir={}", incremental_dir.display());
+            eprintln!("init_incremental_test: incremental_dir={}", incremental_dir.display());
         }
     }
 
@@ -2765,7 +2765,7 @@ impl ProcRes {
             }
         }
 
-        println!(
+        eprintln!(
             "status: {}\ncommand: {}\n{}\n{}\n",
             self.status,
             self.cmdline,
@@ -2776,7 +2776,7 @@ impl ProcRes {
 
     pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! {
         if let Some(e) = err {
-            println!("\nerror: {}", e);
+            eprintln!("\nerror: {}", e);
         }
         self.print_info();
         on_failure();
diff --git a/src/tools/compiletest/src/runtest/codegen_units.rs b/src/tools/compiletest/src/runtest/codegen_units.rs
index 6c866cbef21..6acd140183d 100644
--- a/src/tools/compiletest/src/runtest/codegen_units.rs
+++ b/src/tools/compiletest/src/runtest/codegen_units.rs
@@ -64,13 +64,13 @@ impl TestCx<'_> {
         if !missing.is_empty() {
             missing.sort();
 
-            println!("\nThese items should have been contained but were not:\n");
+            eprintln!("\nThese items should have been contained but were not:\n");
 
             for item in &missing {
-                println!("{}", item);
+                eprintln!("{}", item);
             }
 
-            println!("\n");
+            eprintln!("\n");
         }
 
         if !unexpected.is_empty() {
@@ -80,24 +80,24 @@ impl TestCx<'_> {
                 sorted
             };
 
-            println!("\nThese items were contained but should not have been:\n");
+            eprintln!("\nThese items were contained but should not have been:\n");
 
             for item in sorted {
-                println!("{}", item);
+                eprintln!("{}", item);
             }
 
-            println!("\n");
+            eprintln!("\n");
         }
 
         if !wrong_cgus.is_empty() {
             wrong_cgus.sort_by_key(|pair| pair.0.name.clone());
-            println!("\nThe following items were assigned to wrong codegen units:\n");
+            eprintln!("\nThe following items were assigned to wrong codegen units:\n");
 
             for &(ref expected_item, ref actual_item) in &wrong_cgus {
-                println!("{}", expected_item.name);
-                println!("  expected: {}", codegen_units_to_str(&expected_item.codegen_units));
-                println!("  actual:   {}", codegen_units_to_str(&actual_item.codegen_units));
-                println!();
+                eprintln!("{}", expected_item.name);
+                eprintln!("  expected: {}", codegen_units_to_str(&expected_item.codegen_units));
+                eprintln!("  actual:   {}", codegen_units_to_str(&actual_item.codegen_units));
+                eprintln!();
             }
         }
 
diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs
index c621c22ac99..7322e730e53 100644
--- a/src/tools/compiletest/src/runtest/debuginfo.rs
+++ b/src/tools/compiletest/src/runtest/debuginfo.rs
@@ -260,7 +260,7 @@ impl TestCx<'_> {
                 cmdline,
             };
             if adb.kill().is_err() {
-                println!("Adb process is already finished.");
+                eprintln!("Adb process is already finished.");
             }
         } else {
             let rust_src_root =
@@ -275,7 +275,7 @@ impl TestCx<'_> {
 
             match self.config.gdb_version {
                 Some(version) => {
-                    println!("NOTE: compiletest thinks it is using GDB version {}", version);
+                    eprintln!("NOTE: compiletest thinks it is using GDB version {}", version);
 
                     if version > extract_gdb_version("7.4").unwrap() {
                         // Add the directory containing the pretty printers to
@@ -297,7 +297,7 @@ impl TestCx<'_> {
                     }
                 }
                 _ => {
-                    println!(
+                    eprintln!(
                         "NOTE: compiletest does not know which version of \
                          GDB it is using"
                     );
@@ -392,10 +392,10 @@ impl TestCx<'_> {
 
         match self.config.lldb_version {
             Some(ref version) => {
-                println!("NOTE: compiletest thinks it is using LLDB version {}", version);
+                eprintln!("NOTE: compiletest thinks it is using LLDB version {}", version);
             }
             _ => {
-                println!(
+                eprintln!(
                     "NOTE: compiletest does not know which version of \
                      LLDB it is using"
                 );
diff --git a/src/tools/compiletest/src/runtest/rustdoc_json.rs b/src/tools/compiletest/src/runtest/rustdoc_json.rs
index 31fdb0a5d13..84376d346af 100644
--- a/src/tools/compiletest/src/runtest/rustdoc_json.rs
+++ b/src/tools/compiletest/src/runtest/rustdoc_json.rs
@@ -29,7 +29,7 @@ impl TestCx<'_> {
 
         if !res.status.success() {
             self.fatal_proc_rec_with_ctx("jsondocck failed!", &res, |_| {
-                println!("Rustdoc Output:");
+                eprintln!("Rustdoc Output:");
                 proc_res.print_info();
             })
         }
diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs
index bb747c68029..414f1a6adb3 100644
--- a/src/tools/compiletest/src/runtest/ui.rs
+++ b/src/tools/compiletest/src/runtest/ui.rs
@@ -109,10 +109,10 @@ impl TestCx<'_> {
         }
 
         if errors > 0 {
-            println!("To update references, rerun the tests and pass the `--bless` flag");
+            eprintln!("To update references, rerun the tests and pass the `--bless` flag");
             let relative_path_to_file =
                 self.testpaths.relative_dir.join(self.testpaths.file.file_name().unwrap());
-            println!(
+            eprintln!(
                 "To only update this specific test, also pass `--test-args {}`",
                 relative_path_to_file.display(),
             );
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index bff02f1db9f..7b50e62c29b 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -30,7 +30,7 @@ fn path_div() -> &'static str {
 pub fn logv(config: &Config, s: String) {
     debug!("{}", s);
     if config.verbose {
-        println!("{}", s);
+        eprintln!("{}", s);
     }
 }
 
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index cb02914fd93..473b4fba928 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -31,8 +31,8 @@ directories = "5"
 # Copied from `compiler/rustc/Cargo.toml`.
 # But only for some targets, it fails for others. Rustc configures this in its CI, but we can't
 # easily use that since we support of-tree builds.
-[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies.jemalloc-sys]
-version = "0.5.0"
+[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies.tikv-jemalloc-sys]
+version = "0.6.0"
 features = ['unprefixed_malloc_on_supported_platforms']
 
 [target.'cfg(unix)'.dependencies]
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index c61c62c73da..1e0e31f01ab 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -316,6 +316,8 @@ fn jemalloc_magic() {
     // See there for further comments.
     use std::os::raw::{c_int, c_void};
 
+    use tikv_jemalloc_sys as jemalloc_sys;
+
     #[used]
     static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc;
     #[used]
diff --git a/src/tools/miri/tests/fail/breakpoint.rs b/src/tools/miri/tests/fail/breakpoint.rs
index 2dd87ea6083..42943d58191 100644
--- a/src/tools/miri/tests/fail/breakpoint.rs
+++ b/src/tools/miri/tests/fail/breakpoint.rs
@@ -1,7 +1,5 @@
 #![feature(core_intrinsics)]
 
 fn main() {
-    unsafe {
-        core::intrinsics::breakpoint() //~ ERROR: trace/breakpoint trap
-    };
+    core::intrinsics::breakpoint(); //~ ERROR: trace/breakpoint trap
 }
diff --git a/src/tools/miri/tests/fail/breakpoint.stderr b/src/tools/miri/tests/fail/breakpoint.stderr
index ca98e81f1f4..f203cb0c15f 100644
--- a/src/tools/miri/tests/fail/breakpoint.stderr
+++ b/src/tools/miri/tests/fail/breakpoint.stderr
@@ -1,8 +1,8 @@
 error: abnormal termination: trace/breakpoint trap
   --> tests/fail/breakpoint.rs:LL:CC
    |
-LL |         core::intrinsics::breakpoint()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap
+LL |     core::intrinsics::breakpoint();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap
    |
    = note: BACKTRACE:
    = note: inside `main` at tests/fail/breakpoint.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs
new file mode 100644
index 00000000000..bd02e7f5fb4
--- /dev/null
+++ b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs
@@ -0,0 +1,27 @@
+// Validity makes this fail at the wrong place.
+//@compile-flags: -Zmiri-disable-validation
+use std::mem;
+
+// This enum has untagged variant idx 1, with niche_variants being 0..=2
+// and niche_start being 2.
+// That means the untagged variants is in the niche variant range!
+// However, using the corresponding value (2+1 = 3) is not a valid encoding of this variant.
+#[derive(Copy, Clone, PartialEq)]
+enum Foo {
+    Var1,
+    Var2(bool),
+    Var3,
+}
+
+fn main() {
+    unsafe {
+        assert!(Foo::Var2(false) == mem::transmute(0u8));
+        assert!(Foo::Var2(true) == mem::transmute(1u8));
+        assert!(Foo::Var1 == mem::transmute(2u8));
+        assert!(Foo::Var3 == mem::transmute(4u8));
+
+        let invalid: Foo = mem::transmute(3u8);
+        assert!(matches!(invalid, Foo::Var2(_)));
+        //~^ ERROR: invalid tag
+    }
+}
diff --git a/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr
new file mode 100644
index 00000000000..759dbc36380
--- /dev/null
+++ b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: enum value has invalid tag: 0x03
+  --> tests/fail/enum-untagged-variant-invalid-encoding.rs:LL:CC
+   |
+LL |         assert!(matches!(invalid, Foo::Var2(_)));
+   |                          ^^^^^^^ enum value has invalid tag: 0x03
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at tests/fail/enum-untagged-variant-invalid-encoding.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs
index a35c92636ce..4b49e105562 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs
@@ -47,9 +47,8 @@ fn test_readlink() {
     assert_eq!(res, small_buf.len() as isize);
 
     // Test that we report a proper error for a missing path.
-    let bad_path = CString::new("MIRI_MISSING_FILE_NAME").unwrap();
     let res = unsafe {
-        libc::readlink(bad_path.as_ptr(), small_buf.as_mut_ptr().cast(), small_buf.len())
+        libc::readlink(c"MIRI_MISSING_FILE_NAME".as_ptr(), small_buf.as_mut_ptr().cast(), small_buf.len())
     };
     assert_eq!(res, -1);
     assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound);
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs
index ab3fd6733ff..cffcf4a867f 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs
@@ -2,7 +2,6 @@
 //@compile-flags: -Zmiri-isolation-error=warn-nobacktrace
 //@normalize-stderr-test: "(stat(x)?)" -> "$$STAT"
 
-use std::ffi::CString;
 use std::fs;
 use std::io::{Error, ErrorKind};
 
@@ -13,10 +12,9 @@ fn main() {
     }
 
     // test `readlink`
-    let symlink_c_str = CString::new("foo.txt").unwrap();
     let mut buf = vec![0; "foo_link.txt".len() + 1];
     unsafe {
-        assert_eq!(libc::readlink(symlink_c_str.as_ptr(), buf.as_mut_ptr(), buf.len()), -1);
+        assert_eq!(libc::readlink(c"foo.txt".as_ptr(), buf.as_mut_ptr(), buf.len()), -1);
         assert_eq!(Error::last_os_error().raw_os_error(), Some(libc::EACCES));
     }
 
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs
index 10be78798a6..727533a9de6 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs
@@ -55,12 +55,12 @@ fn test_memcpy() {
 }
 
 fn test_strcpy() {
-    use std::ffi::{CStr, CString};
+    use std::ffi::CStr;
 
     // case: src_size equals dest_size
     unsafe {
-        let src = CString::new("rust").unwrap();
-        let size = src.as_bytes_with_nul().len();
+        let src = c"rust";
+        let size = src.to_bytes_with_nul().len();
         let dest = libc::malloc(size);
         libc::strcpy(dest as *mut libc::c_char, src.as_ptr());
         assert_eq!(CStr::from_ptr(dest as *const libc::c_char), src.as_ref());
@@ -69,8 +69,8 @@ fn test_strcpy() {
 
     // case: src_size is less than dest_size
     unsafe {
-        let src = CString::new("rust").unwrap();
-        let size = src.as_bytes_with_nul().len();
+        let src = c"rust";
+        let size = src.to_bytes_with_nul().len();
         let dest = libc::malloc(size + 1);
         libc::strcpy(dest as *mut libc::c_char, src.as_ptr());
         assert_eq!(CStr::from_ptr(dest as *const libc::c_char), src.as_ref());
diff --git a/src/tools/miri/tests/pass/async-closure-captures.rs b/src/tools/miri/tests/pass/async-closure-captures.rs
index cac26bfe146..423ef7a5cf7 100644
--- a/src/tools/miri/tests/pass/async-closure-captures.rs
+++ b/src/tools/miri/tests/pass/async-closure-captures.rs
@@ -1,6 +1,6 @@
 // Same as rustc's `tests/ui/async-await/async-closures/captures.rs`, keep in sync
 
-#![feature(async_closure, noop_waker)]
+#![feature(async_closure, noop_waker, async_trait_bounds)]
 
 use std::future::Future;
 use std::pin::pin;
diff --git a/src/tools/miri/tests/pass/async-closure-drop.rs b/src/tools/miri/tests/pass/async-closure-drop.rs
index 9b2fc2948bf..264da5a9518 100644
--- a/src/tools/miri/tests/pass/async-closure-drop.rs
+++ b/src/tools/miri/tests/pass/async-closure-drop.rs
@@ -1,4 +1,4 @@
-#![feature(async_closure, noop_waker, async_fn_traits)]
+#![feature(async_closure, noop_waker, async_trait_bounds)]
 
 use std::future::Future;
 use std::pin::pin;
diff --git a/src/tools/miri/tests/pass/function_pointers.rs b/src/tools/miri/tests/pass/function_pointers.rs
index a5c4bc5e0d9..7145be334a1 100644
--- a/src/tools/miri/tests/pass/function_pointers.rs
+++ b/src/tools/miri/tests/pass/function_pointers.rs
@@ -1,3 +1,5 @@
+#![allow(unpredictable_function_pointer_comparisons)]
+
 use std::mem;
 
 trait Answer {
diff --git a/src/tools/miri/tests/pass/issues/issue-91636.rs b/src/tools/miri/tests/pass/issues/issue-91636.rs
index 00370165812..d0cadcd2c70 100644
--- a/src/tools/miri/tests/pass/issues/issue-91636.rs
+++ b/src/tools/miri/tests/pass/issues/issue-91636.rs
@@ -1,3 +1,5 @@
+#![allow(unpredictable_function_pointer_comparisons)]
+
 type BuiltIn = for<'a> fn(&str);
 
 struct Function {
diff --git a/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs b/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs
index 660afff3dca..006748ddb08 100644
--- a/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs
+++ b/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs
@@ -62,15 +62,13 @@ fn memusage_linux() -> MemoryUsage {
     // mallinfo2 is very recent, so its presence needs to be detected at runtime.
     // Both are abysmally slow.
 
-    use std::ffi::CStr;
     use std::sync::atomic::{AtomicUsize, Ordering};
 
     static MALLINFO2: AtomicUsize = AtomicUsize::new(1);
 
     let mut mallinfo2 = MALLINFO2.load(Ordering::Relaxed);
     if mallinfo2 == 1 {
-        let cstr = CStr::from_bytes_with_nul(b"mallinfo2\0").unwrap();
-        mallinfo2 = unsafe { libc::dlsym(libc::RTLD_DEFAULT, cstr.as_ptr()) } as usize;
+        mallinfo2 = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c"mallinfo2".as_ptr()) } as usize;
         // NB: races don't matter here, since they'll always store the same value
         MALLINFO2.store(mallinfo2, Ordering::Relaxed);
     }
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index e065f01ebba..afa0b9a6760 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -307,7 +307,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "intl_pluralrules",
     "itertools",
     "itoa",
-    "jemalloc-sys",
     "jobserver",
     "lazy_static",
     "leb128",
@@ -392,6 +391,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "thiserror-impl",
     "thorin-dwp",
     "thread_local",
+    "tikv-jemalloc-sys",
     "time",
     "time-core",
     "time-macros",
diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs
index e2d1b85797f..9dc49b57d59 100644
--- a/src/tools/tidy/src/error_codes.rs
+++ b/src/tools/tidy/src/error_codes.rs
@@ -38,7 +38,7 @@ const IGNORE_UI_TEST_CHECK: &[&str] =
 macro_rules! verbose_print {
     ($verbose:expr, $($fmt:tt)*) => {
         if $verbose {
-            println!("{}", format_args!($($fmt)*));
+            eprintln!("{}", format_args!($($fmt)*));
         }
     };
 }
@@ -49,8 +49,8 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
     // Stage 1: create list
     let error_codes = extract_error_codes(root_path, &mut errors);
     if verbose {
-        println!("Found {} error codes", error_codes.len());
-        println!("Highest error code: `{}`", error_codes.iter().max().unwrap());
+        eprintln!("Found {} error codes", error_codes.len());
+        eprintln!("Highest error code: `{}`", error_codes.iter().max().unwrap());
     }
 
     // Stage 2: check list has docs
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 4f24eb21242..4607d041577 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -158,14 +158,14 @@ pub fn check(
         .collect::<Vec<_>>();
 
     for &(name, _) in gate_untested.iter() {
-        println!("Expected a gate test for the feature '{name}'.");
-        println!(
+        eprintln!("Expected a gate test for the feature '{name}'.");
+        eprintln!(
             "Hint: create a failing test file named 'tests/ui/feature-gates/feature-gate-{}.rs',\
                 \n      with its failures due to missing usage of `#![feature({})]`.",
             name.replace("_", "-"),
             name
         );
-        println!(
+        eprintln!(
             "Hint: If you already have such a test and don't want to rename it,\
                 \n      you can also add a // gate-test-{} line to the test file.",
             name
@@ -218,7 +218,7 @@ pub fn check(
 
         lines.sort();
         for line in lines {
-            println!("* {line}");
+            eprintln!("* {line}");
         }
     }
 
diff --git a/src/tools/tidy/src/fluent_period.rs b/src/tools/tidy/src/fluent_period.rs
index 8bc404dc858..6a136e5aec6 100644
--- a/src/tools/tidy/src/fluent_period.rs
+++ b/src/tools/tidy/src/fluent_period.rs
@@ -18,7 +18,6 @@ const ALLOWLIST: &[&str] = &[
     "const_eval_validation_failure_note",
     "driver_impl_ice",
     "incremental_corrupt_file",
-    "mir_build_pointer_pattern",
 ];
 
 fn check_period(filename: &str, contents: &str, bad: &mut bool) {
diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs
index 8be25b98df0..06d238ef5e4 100644
--- a/src/tools/tidy/src/unstable_book.rs
+++ b/src/tools/tidy/src/unstable_book.rs
@@ -118,16 +118,16 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
     // List unstable features that don't have Unstable Book sections.
     // Remove the comment marker if you want the list printed.
     /*
-    println!("Lib features without unstable book sections:");
+    eprintln!("Lib features without unstable book sections:");
     for feature_name in &unstable_lang_feature_names -
                         &unstable_book_lang_features_section_file_names {
-        println!("    * {} {:?}", feature_name, lib_features[&feature_name].tracking_issue);
+        eprintln!("    * {} {:?}", feature_name, lib_features[&feature_name].tracking_issue);
     }
 
-    println!("Lang features without unstable book sections:");
+    eprintln!("Lang features without unstable book sections:");
     for feature_name in &unstable_lib_feature_names-
                         &unstable_book_lib_features_section_file_names {
-        println!("    * {} {:?}", feature_name, lang_features[&feature_name].tracking_issue);
+        eprintln!("    * {} {:?}", feature_name, lang_features[&feature_name].tracking_issue);
     }
     // */
 }
diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs
index 489343561e1..b43d56202c9 100644
--- a/src/tools/tidy/src/x_version.rs
+++ b/src/tools/tidy/src/x_version.rs
@@ -42,7 +42,7 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
 
         if let Some(expected) = get_x_wrapper_version(root, cargo) {
             if installed < expected {
-                return println!(
+                return eprintln!(
                     "Current version of x is {installed}, but the latest version is {expected}\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`"
                 );
             }
diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml
index acdb1aa1ab7..965e9b01a44 100644
--- a/src/tools/wasm-component-ld/Cargo.toml
+++ b/src/tools/wasm-component-ld/Cargo.toml
@@ -10,4 +10,4 @@ name = "wasm-component-ld"
 path = "src/main.rs"
 
 [dependencies]
-wasm-component-ld = "0.5.10"
+wasm-component-ld = "0.5.11"
diff --git a/tests/assembly/breakpoint.rs b/tests/assembly/breakpoint.rs
new file mode 100644
index 00000000000..e0cc2d1eebb
--- /dev/null
+++ b/tests/assembly/breakpoint.rs
@@ -0,0 +1,14 @@
+//@ revisions: aarch64 x86_64
+//@ assembly-output: emit-asm
+//@[aarch64] only-aarch64
+//@[x86_64] only-x86_64
+
+#![feature(breakpoint)]
+#![crate_type = "lib"]
+
+// CHECK-LABEL: use_bp
+// aarch64: brk #0xf000
+// x86_64: int3
+pub fn use_bp() {
+    core::arch::breakpoint();
+}
diff --git a/tests/assembly/x86_64-bigint-add.rs b/tests/assembly/x86_64-bigint-helpers.rs
index 4bcb9732c64..198e5543539 100644
--- a/tests/assembly/x86_64-bigint-add.rs
+++ b/tests/assembly/x86_64-bigint-helpers.rs
@@ -6,8 +6,8 @@
 #![no_std]
 #![feature(bigint_helper_methods)]
 
-// This checks that the `carrying_add` implementation successfully chains, to catch
-// issues like <https://github.com/rust-lang/rust/issues/85532#issuecomment-2495119815>
+// This checks that the `carrying_add` and `borrowing_sub` implementation successfully chain,
+// to catch issues like <https://github.com/rust-lang/rust/issues/85532#issuecomment-2495119815>
 
 // This forces the ABI to avoid the windows-vs-linux ABI differences.
 
@@ -31,3 +31,24 @@ pub unsafe extern "sysv64" fn bigint_chain_carrying_add(
     }
     carry
 }
+
+// CHECK-LABEL: bigint_chain_borrowing_sub:
+#[no_mangle]
+pub unsafe extern "sysv64" fn bigint_chain_borrowing_sub(
+    dest: *mut u64,
+    src1: *const u64,
+    src2: *const u64,
+    n: usize,
+    mut carry: bool,
+) -> bool {
+    // CHECK: mov [[TEMP:r..]], qword ptr [rsi + 8*[[IND:r..]] + 8]
+    // CHECK: sbb [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8]
+    // CHECK: mov qword ptr [rdi + 8*[[IND]] + 8], [[TEMP]]
+    // CHECK: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 16]
+    // CHECK: sbb [[TEMP]], qword ptr [rdx + 8*[[IND]] + 16]
+    // CHECK: mov qword ptr [rdi + 8*[[IND]] + 16], [[TEMP]]
+    for i in 0..n {
+        (*dest.add(i), carry) = u64::borrowing_sub(*src1.add(i), *src2.add(i), carry);
+    }
+    carry
+}
diff --git a/tests/codegen/async-closure-debug.rs b/tests/codegen/async-closure-debug.rs
index 9cb1e623295..644df169a36 100644
--- a/tests/codegen/async-closure-debug.rs
+++ b/tests/codegen/async-closure-debug.rs
@@ -9,7 +9,7 @@
 
 #![feature(async_closure)]
 
-fn async_closure_test(upvar: &str) -> impl async Fn() + '_ {
+fn async_closure_test(upvar: &str) -> impl AsyncFn() + '_ {
     async move || {
         let hello = String::from("hello");
         println!("{hello}, {upvar}");
diff --git a/tests/codegen/issues/issue-98678-async.rs b/tests/codegen/issues/issue-98678-async.rs
new file mode 100644
index 00000000000..75f5d82eee5
--- /dev/null
+++ b/tests/codegen/issues/issue-98678-async.rs
@@ -0,0 +1,25 @@
+// This test verifies the accuracy of emitted file and line debuginfo metadata for async blocks and
+// async functions.
+//
+//@ edition:2021
+//@ compile-flags: --crate-type=lib -Copt-level=0 -Cdebuginfo=2 -Zdebug-info-type-line-numbers=true
+
+// ignore-tidy-linelength
+
+// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*[/\\]}}issue-98678-async.rs{{".*}})
+// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-async.rs{{".*}})
+
+// NONMSVC-DAG: !DISubprogram(name: "foo",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]],
+// MSVC-DAG: !DISubprogram(name: "foo",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+pub async fn foo() -> u8 {
+    5
+}
+
+pub fn bar() -> impl std::future::Future<Output = u8> {
+    // NONMSVC: !DICompositeType({{.*"}}{async_block_env#0}{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]],
+    // MSVC-DAG: !DICompositeType({{.*"}}enum2$<issue_98678_async::bar::async_block_env$0>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+    async {
+        let x: u8 = foo().await;
+        x + 5
+    }
+}
diff --git a/tests/codegen/issues/issue-98678-closure-coroutine.rs b/tests/codegen/issues/issue-98678-closure-coroutine.rs
new file mode 100644
index 00000000000..0730e56bf31
--- /dev/null
+++ b/tests/codegen/issues/issue-98678-closure-coroutine.rs
@@ -0,0 +1,22 @@
+// This test verifies the accuracy of emitted file and line debuginfo metadata for closures and
+// coroutines.
+//
+//@ compile-flags: --crate-type=lib -Copt-level=0 -Cdebuginfo=2 -Zdebug-info-type-line-numbers=true
+#![feature(coroutines, stmt_expr_attributes)]
+
+// ignore-tidy-linelength
+
+// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*[/\\]}}issue-98678-closure-coroutine.rs{{".*}})
+// MSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-closure-coroutine.rs{{".*}})
+
+pub fn foo() {
+    // NONMSVC-DAG: !DICompositeType({{.*"}}{closure_env#0}{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]],
+    // MSVC-DAG: !DICompositeType({{.*"}}closure_env$0{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+    let closure = |x| x;
+    closure(0);
+
+    // NONMSVC-DAG: !DICompositeType({{.*"[{]}}coroutine_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 3]],
+    // MSVC-DAG: !DICompositeType({{.*".*foo::}}coroutine_env$1>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]],
+    let _coroutine = #[coroutine]
+    || yield 1;
+}
diff --git a/tests/codegen/issues/issue-98678-enum.rs b/tests/codegen/issues/issue-98678-enum.rs
new file mode 100644
index 00000000000..62c6cded866
--- /dev/null
+++ b/tests/codegen/issues/issue-98678-enum.rs
@@ -0,0 +1,40 @@
+// This test verifies the accuracy of emitted file and line debuginfo metadata enums.
+//
+//@ compile-flags: --crate-type=lib -Copt-level=0 -Cdebuginfo=2 -Zdebug-info-type-line-numbers=true
+
+// ignore-tidy-linelength
+
+// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*[/\\]}}issue-98678-enum.rs{{".*}})
+// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-enum.rs{{".*}})
+
+// NONMSVC: !DICompositeType({{.*"}}SingleCase{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]],
+// MSVC: !DICompositeType({{.*"}}enum2$<issue_98678_enum::SingleCase>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+pub enum SingleCase {
+    // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "One",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]],
+    // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "One",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+    One,
+}
+
+// NONMSVC: !DICompositeType({{.*"}}MultipleDataCases{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]],
+// MSVC: !DICompositeType({{.*"}}enum2$<issue_98678_enum::MultipleDataCases>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+pub enum MultipleDataCases {
+    // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "Case1",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]],
+    // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Case1",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+    Case1(u32),
+    // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "Case2",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]],
+    // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Case2",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+    Case2(i64),
+}
+
+// NONMSVC: !DICompositeType({{.*"}}NicheLayout{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]],
+// MSVC: !DICompositeType({{.*"}}enum2$<issue_98678_enum::NicheLayout>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+pub enum NicheLayout {
+    // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "Something",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]],
+    // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Something",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+    Something(&'static u32),
+    // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "Nothing",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]],
+    // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Nothing",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+    Nothing,
+}
+
+pub fn foo(_: SingleCase, _: MultipleDataCases, _: NicheLayout) {}
diff --git a/tests/codegen/issues/issue-98678-struct-union.rs b/tests/codegen/issues/issue-98678-struct-union.rs
new file mode 100644
index 00000000000..bf2d6e731aa
--- /dev/null
+++ b/tests/codegen/issues/issue-98678-struct-union.rs
@@ -0,0 +1,25 @@
+// This test verifies the accuracy of emitted file and line debuginfo metadata for structs and
+// unions.
+//
+//@ compile-flags: --crate-type=lib -Copt-level=0 -Cdebuginfo=2 -Zdebug-info-type-line-numbers=true
+
+// ignore-tidy-linelength
+
+// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*[/\\]}}issue-98678-struct-union.rs{{".*}})
+// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-struct-union.rs{{".*}})
+
+// CHECK: !DICompositeType({{.*"}}MyType{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+pub struct MyType {
+    // CHECK: !DIDerivedType({{.*"}}i{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+    i: i32,
+}
+
+// CHECK: !DICompositeType({{.*"}}MyUnion{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+pub union MyUnion {
+    // CHECK: !DIDerivedType({{.*"}}i{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+    i: i32,
+    // CHECK: !DIDerivedType({{.*"}}f{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]],
+    f: f32,
+}
+
+pub fn foo(_: MyType, _: MyUnion) {}
diff --git a/tests/coverage/abort.cov-map b/tests/coverage/abort.cov-map
index c121fa551dc..396edec275d 100644
--- a/tests/coverage/abort.cov-map
+++ b/tests/coverage/abort.cov-map
@@ -1,34 +1,34 @@
 Function name: abort::main
-Raw bytes (89): 0x[01, 01, 0a, 01, 27, 05, 09, 03, 0d, 22, 11, 03, 0d, 03, 0d, 22, 15, 03, 0d, 03, 0d, 05, 09, 0d, 01, 0d, 01, 01, 1b, 03, 02, 0b, 00, 18, 22, 01, 0c, 00, 19, 11, 00, 1a, 02, 0a, 0e, 02, 09, 00, 0a, 22, 02, 0c, 00, 19, 15, 00, 1a, 00, 31, 1a, 00, 30, 00, 31, 22, 04, 0c, 00, 19, 05, 00, 1a, 00, 31, 09, 00, 30, 00, 31, 27, 01, 09, 00, 17, 0d, 02, 05, 01, 02]
+Raw bytes (89): 0x[01, 01, 0a, 07, 09, 01, 05, 03, 0d, 03, 13, 0d, 11, 03, 0d, 03, 1f, 0d, 15, 03, 0d, 05, 09, 0d, 01, 0d, 01, 01, 1b, 03, 02, 0b, 00, 18, 22, 01, 0c, 00, 19, 11, 00, 1a, 02, 0a, 0e, 02, 09, 00, 0a, 22, 02, 0c, 00, 19, 15, 00, 1a, 00, 31, 1a, 00, 30, 00, 31, 22, 04, 0c, 00, 19, 05, 00, 1a, 00, 31, 09, 00, 30, 00, 31, 27, 01, 09, 00, 17, 0d, 02, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 10
-- expression 0 operands: lhs = Counter(0), rhs = Expression(9, Add)
-- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(2)
+- expression 1 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 3 operands: lhs = Expression(8, Sub), rhs = Counter(4)
-- expression 4 operands: lhs = Expression(0, Add), rhs = Counter(3)
+- expression 3 operands: lhs = Expression(0, Add), rhs = Expression(4, Add)
+- expression 4 operands: lhs = Counter(3), rhs = Counter(4)
 - expression 5 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 6 operands: lhs = Expression(8, Sub), rhs = Counter(5)
-- expression 7 operands: lhs = Expression(0, Add), rhs = Counter(3)
+- expression 6 operands: lhs = Expression(0, Add), rhs = Expression(7, Add)
+- expression 7 operands: lhs = Counter(3), rhs = Counter(5)
 - expression 8 operands: lhs = Expression(0, Add), rhs = Counter(3)
 - expression 9 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 13
 - Code(Counter(0)) at (prev + 13, 1) to (start + 1, 27)
 - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24)
-    = (c0 + (c1 + c2))
+    = ((c0 + c1) + c2)
 - Code(Expression(8, Sub)) at (prev + 1, 12) to (start + 0, 25)
-    = ((c0 + (c1 + c2)) - c3)
+    = (((c0 + c1) + c2) - c3)
 - Code(Counter(4)) at (prev + 0, 26) to (start + 2, 10)
 - Code(Expression(3, Sub)) at (prev + 2, 9) to (start + 0, 10)
-    = (((c0 + (c1 + c2)) - c3) - c4)
+    = (((c0 + c1) + c2) - (c3 + c4))
 - Code(Expression(8, Sub)) at (prev + 2, 12) to (start + 0, 25)
-    = ((c0 + (c1 + c2)) - c3)
+    = (((c0 + c1) + c2) - c3)
 - Code(Counter(5)) at (prev + 0, 26) to (start + 0, 49)
 - Code(Expression(6, Sub)) at (prev + 0, 48) to (start + 0, 49)
-    = (((c0 + (c1 + c2)) - c3) - c5)
+    = (((c0 + c1) + c2) - (c3 + c5))
 - Code(Expression(8, Sub)) at (prev + 4, 12) to (start + 0, 25)
-    = ((c0 + (c1 + c2)) - c3)
+    = (((c0 + c1) + c2) - c3)
 - Code(Counter(1)) at (prev + 0, 26) to (start + 0, 49)
 - Code(Counter(2)) at (prev + 0, 48) to (start + 0, 49)
 - Code(Expression(9, Add)) at (prev + 1, 9) to (start + 0, 23)
diff --git a/tests/coverage/assert.cov-map b/tests/coverage/assert.cov-map
index b3cec390119..3bbf7a43e6d 100644
--- a/tests/coverage/assert.cov-map
+++ b/tests/coverage/assert.cov-map
@@ -1,29 +1,30 @@
 Function name: assert::main
-Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 09, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 02, 0a, 12, 02, 13, 00, 20, 09, 00, 21, 02, 0a, 0d, 02, 09, 00, 0a, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02]
+Raw bytes (67): 0x[01, 01, 09, 07, 0d, 0b, 09, 01, 05, 03, 11, 17, 11, 1b, 0d, 01, 09, 23, 0d, 05, 09, 09, 01, 09, 01, 01, 1b, 03, 02, 0b, 00, 18, 0e, 01, 0c, 00, 1a, 05, 00, 1b, 02, 0a, 12, 02, 13, 00, 20, 09, 00, 21, 02, 0a, 0d, 02, 09, 00, 0a, 1f, 01, 09, 00, 17, 11, 02, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 8
-- expression 0 operands: lhs = Counter(0), rhs = Expression(6, Add)
-- expression 1 operands: lhs = Counter(1), rhs = Expression(7, Add)
-- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
+Number of expressions: 9
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 3 operands: lhs = Expression(0, Add), rhs = Counter(4)
-- expression 4 operands: lhs = Expression(5, Sub), rhs = Counter(1)
-- expression 5 operands: lhs = Expression(0, Add), rhs = Counter(4)
-- expression 6 operands: lhs = Counter(1), rhs = Expression(7, Add)
-- expression 7 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(4)
+- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(3)
+- expression 6 operands: lhs = Counter(0), rhs = Counter(2)
+- expression 7 operands: lhs = Expression(8, Add), rhs = Counter(3)
+- expression 8 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 9
 - Code(Counter(0)) at (prev + 9, 1) to (start + 1, 27)
 - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24)
-    = (c0 + (c1 + (c2 + c3)))
-- Code(Expression(5, Sub)) at (prev + 1, 12) to (start + 0, 26)
-    = ((c0 + (c1 + (c2 + c3))) - c4)
+    = (((c0 + c1) + c2) + c3)
+- Code(Expression(3, Sub)) at (prev + 1, 12) to (start + 0, 26)
+    = ((((c0 + c1) + c2) + c3) - c4)
 - Code(Counter(1)) at (prev + 0, 27) to (start + 2, 10)
 - Code(Expression(4, Sub)) at (prev + 2, 19) to (start + 0, 32)
-    = (((c0 + (c1 + (c2 + c3))) - c4) - c1)
+    = (((c0 + c2) + c3) - c4)
 - Code(Counter(2)) at (prev + 0, 33) to (start + 2, 10)
 - Code(Counter(3)) at (prev + 2, 9) to (start + 0, 10)
-- Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23)
-    = (c1 + (c2 + c3))
+- Code(Expression(7, Add)) at (prev + 1, 9) to (start + 0, 23)
+    = ((c1 + c2) + c3)
 - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2)
 Highest counter ID seen: c4
 
diff --git a/tests/coverage/async.cov-map b/tests/coverage/async.cov-map
index 9a67cefcf98..c51bc6eb621 100644
--- a/tests/coverage/async.cov-map
+++ b/tests/coverage/async.cov-map
@@ -155,25 +155,25 @@ Number of file 0 mappings: 1
 Highest counter ID seen: c0
 
 Function name: async::i::{closure#0}
-Raw bytes (63): 0x[01, 01, 02, 07, 19, 11, 15, 0b, 01, 2d, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 15, 01, 09, 00, 0a, 0d, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 15, 00, 24, 00, 26, 19, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
+Raw bytes (63): 0x[01, 01, 02, 07, 15, 0d, 11, 0b, 01, 2d, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 11, 01, 09, 00, 0a, 19, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 11, 00, 24, 00, 26, 15, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
-- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(6)
-- expression 1 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(5)
+- expression 1 operands: lhs = Counter(3), rhs = Counter(4)
 Number of file 0 mappings: 11
 - Code(Counter(0)) at (prev + 45, 19) to (start + 4, 12)
 - Code(Counter(2)) at (prev + 5, 9) to (start + 0, 10)
 - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 24)
 - Code(Counter(1)) at (prev + 0, 28) to (start + 0, 33)
 - Code(Counter(2)) at (prev + 0, 39) to (start + 0, 48)
-- Code(Counter(5)) at (prev + 1, 9) to (start + 0, 10)
-- Code(Counter(3)) at (prev + 0, 14) to (start + 0, 23)
+- Code(Counter(4)) at (prev + 1, 9) to (start + 0, 10)
+- Code(Counter(6)) at (prev + 0, 14) to (start + 0, 23)
 - Code(Counter(7)) at (prev + 0, 27) to (start + 0, 32)
-- Code(Counter(5)) at (prev + 0, 36) to (start + 0, 38)
-- Code(Counter(6)) at (prev + 1, 14) to (start + 0, 16)
+- Code(Counter(4)) at (prev + 0, 36) to (start + 0, 38)
+- Code(Counter(5)) at (prev + 1, 14) to (start + 0, 16)
 - Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2)
-    = ((c4 + c5) + c6)
+    = ((c3 + c4) + c5)
 Highest counter ID seen: c7
 
 Function name: async::j
@@ -243,22 +243,19 @@ Number of file 0 mappings: 5
 Highest counter ID seen: (none)
 
 Function name: async::l
-Raw bytes (37): 0x[01, 01, 04, 01, 07, 05, 09, 0f, 02, 09, 05, 05, 01, 52, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02]
+Raw bytes (33): 0x[01, 01, 02, 01, 07, 05, 09, 05, 01, 52, 01, 01, 0c, 02, 02, 0e, 00, 10, 09, 01, 0e, 00, 10, 05, 01, 0e, 00, 10, 01, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 4
+Number of expressions: 2
 - expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add)
 - expression 1 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 2 operands: lhs = Expression(3, Add), rhs = Expression(0, Sub)
-- expression 3 operands: lhs = Counter(2), rhs = Counter(1)
 Number of file 0 mappings: 5
 - Code(Counter(0)) at (prev + 82, 1) to (start + 1, 12)
 - Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 16)
     = (c0 - (c1 + c2))
-- Code(Counter(1)) at (prev + 1, 14) to (start + 0, 16)
 - Code(Counter(2)) at (prev + 1, 14) to (start + 0, 16)
-- Code(Expression(2, Add)) at (prev + 2, 1) to (start + 0, 2)
-    = ((c2 + c1) + (c0 - (c1 + c2)))
+- Code(Counter(1)) at (prev + 1, 14) to (start + 0, 16)
+- Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2)
 Highest counter ID seen: c2
 
 Function name: async::m
diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map
index 4d00f0d9b33..9ff29af8e8e 100644
--- a/tests/coverage/async_closure.cov-map
+++ b/tests/coverage/async_closure.cov-map
@@ -1,19 +1,19 @@
 Function name: async_closure::call_once::<async_closure::main::{closure#0}>
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2c]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2b]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 44)
+- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 43)
 Highest counter ID seen: c0
 
 Function name: async_closure::call_once::<async_closure::main::{closure#0}>::{closure#0}
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2c, 01, 0e, 05, 02, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2b, 01, 0e, 05, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 7, 44) to (start + 1, 14)
+- Code(Counter(0)) at (prev + 7, 43) to (start + 1, 14)
 - Code(Counter(1)) at (prev + 2, 1) to (start + 0, 2)
 Highest counter ID seen: c1
 
diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage
index fd6edf7c29e..75da1a01fc1 100644
--- a/tests/coverage/async_closure.coverage
+++ b/tests/coverage/async_closure.coverage
@@ -4,7 +4,7 @@
    LL|       |//@ aux-build: executor.rs
    LL|       |extern crate executor;
    LL|       |
-   LL|      1|async fn call_once(f: impl async FnOnce()) {
+   LL|      1|async fn call_once(f: impl AsyncFnOnce()) {
    LL|      1|    f().await;
    LL|      1|}
    LL|       |
diff --git a/tests/coverage/async_closure.rs b/tests/coverage/async_closure.rs
index c076d03eef4..cbac592d957 100644
--- a/tests/coverage/async_closure.rs
+++ b/tests/coverage/async_closure.rs
@@ -4,7 +4,7 @@
 //@ aux-build: executor.rs
 extern crate executor;
 
-async fn call_once(f: impl async FnOnce()) {
+async fn call_once(f: impl AsyncFnOnce()) {
     f().await;
 }
 
diff --git a/tests/coverage/branch/guard.cov-map b/tests/coverage/branch/guard.cov-map
index 0f33ed17a0a..1ba1c6e1228 100644
--- a/tests/coverage/branch/guard.cov-map
+++ b/tests/coverage/branch/guard.cov-map
@@ -1,5 +1,5 @@
 Function name: guard::branch_match_guard
-Raw bytes (85): 0x[01, 01, 06, 19, 0d, 05, 09, 0f, 15, 13, 11, 17, 0d, 05, 09, 0d, 01, 0c, 01, 01, 10, 1d, 03, 0b, 00, 0c, 15, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 19, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 1d, 00, 14, 00, 19, 20, 11, 09, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 17, 03, 0e, 02, 0a, 0b, 04, 01, 00, 02]
+Raw bytes (85): 0x[01, 01, 06, 19, 0d, 05, 09, 0f, 15, 13, 11, 17, 0d, 05, 09, 0d, 01, 0c, 01, 01, 10, 02, 03, 0b, 00, 0c, 15, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 19, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 19, 20, 11, 05, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 17, 03, 0e, 02, 0a, 0b, 04, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 6
@@ -11,7 +11,8 @@ Number of expressions: 6
 - expression 5 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 13
 - Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16)
-- Code(Counter(7)) at (prev + 3, 11) to (start + 0, 12)
+- Code(Expression(0, Sub)) at (prev + 3, 11) to (start + 0, 12)
+    = (c6 - c3)
 - Code(Counter(5)) at (prev + 1, 20) to (start + 2, 10)
 - Code(Counter(3)) at (prev + 3, 14) to (start + 0, 15)
 - Code(Counter(6)) at (prev + 0, 20) to (start + 0, 25)
@@ -20,14 +21,15 @@ Number of file 0 mappings: 13
     false = (c6 - c3)
 - Code(Counter(3)) at (prev + 0, 29) to (start + 2, 10)
 - Code(Counter(4)) at (prev + 3, 14) to (start + 0, 15)
-- Code(Counter(7)) at (prev + 0, 20) to (start + 0, 25)
-- Branch { true: Counter(4), false: Counter(2) } at (prev + 0, 20) to (start + 0, 30)
+- Code(Expression(0, Sub)) at (prev + 0, 20) to (start + 0, 25)
+    = (c6 - c3)
+- Branch { true: Counter(4), false: Counter(1) } at (prev + 0, 20) to (start + 0, 30)
     true  = c4
-    false = c2
+    false = c1
 - Code(Counter(4)) at (prev + 0, 29) to (start + 2, 10)
 - Code(Expression(5, Add)) at (prev + 3, 14) to (start + 2, 10)
     = (c1 + c2)
 - Code(Expression(2, Add)) at (prev + 4, 1) to (start + 0, 2)
     = ((((c1 + c2) + c3) + c4) + c5)
-Highest counter ID seen: c7
+Highest counter ID seen: c6
 
diff --git a/tests/coverage/branch/if.cov-map b/tests/coverage/branch/if.cov-map
index 0ad78a720a7..bab982dd44c 100644
--- a/tests/coverage/branch/if.cov-map
+++ b/tests/coverage/branch/if.cov-map
@@ -1,12 +1,14 @@
 Function name: if::branch_and
-Raw bytes (56): 0x[01, 01, 04, 05, 09, 0d, 02, 11, 0f, 0d, 02, 08, 01, 2b, 01, 01, 10, 05, 03, 08, 00, 09, 20, 09, 02, 00, 08, 00, 09, 09, 00, 0d, 00, 0e, 20, 11, 0d, 00, 0d, 00, 0e, 11, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (60): 0x[01, 01, 06, 05, 09, 0b, 09, 05, 11, 13, 09, 17, 11, 05, 0d, 08, 01, 2b, 01, 01, 10, 05, 03, 08, 00, 09, 20, 09, 02, 00, 08, 00, 09, 09, 00, 0d, 00, 0e, 20, 0d, 11, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 06, 02, 0c, 02, 06, 0e, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 4
+Number of expressions: 6
 - expression 0 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 1 operands: lhs = Counter(3), rhs = Expression(0, Sub)
-- expression 2 operands: lhs = Counter(4), rhs = Expression(3, Add)
-- expression 3 operands: lhs = Counter(3), rhs = Expression(0, Sub)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(4)
+- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(2)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(4)
+- expression 5 operands: lhs = Counter(1), rhs = Counter(3)
 Number of file 0 mappings: 8
 - Code(Counter(0)) at (prev + 43, 1) to (start + 1, 16)
 - Code(Counter(1)) at (prev + 3, 8) to (start + 0, 9)
@@ -14,14 +16,14 @@ Number of file 0 mappings: 8
     true  = c2
     false = (c1 - c2)
 - Code(Counter(2)) at (prev + 0, 13) to (start + 0, 14)
-- Branch { true: Counter(4), false: Counter(3) } at (prev + 0, 13) to (start + 0, 14)
-    true  = c4
-    false = c3
-- Code(Counter(4)) at (prev + 0, 15) to (start + 2, 6)
-- Code(Expression(3, Add)) at (prev + 2, 12) to (start + 2, 6)
-    = (c3 + (c1 - c2))
-- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2)
-    = (c4 + (c3 + (c1 - c2)))
+- Branch { true: Counter(3), false: Counter(4) } at (prev + 0, 13) to (start + 0, 14)
+    true  = c3
+    false = c4
+- Code(Counter(3)) at (prev + 0, 15) to (start + 2, 6)
+- Code(Expression(1, Sub)) at (prev + 2, 12) to (start + 2, 6)
+    = ((c1 + c4) - c2)
+- Code(Expression(3, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = (((c1 + c3) + c4) - c2)
 Highest counter ID seen: c4
 
 Function name: if::branch_not
diff --git a/tests/coverage/branch/lazy-boolean.cov-map b/tests/coverage/branch/lazy-boolean.cov-map
index c2b6a5b8df2..decb847f60e 100644
--- a/tests/coverage/branch/lazy-boolean.cov-map
+++ b/tests/coverage/branch/lazy-boolean.cov-map
@@ -34,39 +34,49 @@ Number of file 0 mappings: 6
 Highest counter ID seen: c2
 
 Function name: lazy_boolean::chain
-Raw bytes (149): 0x[01, 01, 13, 11, 07, 0b, 16, 15, 1a, 09, 0d, 05, 09, 05, 09, 09, 0d, 47, 25, 4b, 21, 19, 1d, 03, 19, 03, 19, 3e, 1d, 03, 19, 3e, 1d, 03, 19, 47, 25, 4b, 21, 19, 1d, 13, 01, 24, 01, 01, 10, 03, 04, 09, 00, 0a, 05, 00, 0d, 00, 12, 20, 09, 16, 00, 0d, 00, 12, 09, 00, 16, 00, 1b, 20, 0d, 1a, 00, 16, 00, 1b, 0d, 00, 1f, 00, 24, 20, 11, 15, 00, 1f, 00, 24, 11, 00, 28, 00, 2d, 03, 01, 05, 00, 11, 43, 03, 09, 00, 0a, 03, 00, 0d, 00, 12, 20, 19, 3e, 00, 0d, 00, 12, 3e, 00, 16, 00, 1b, 20, 1d, 3a, 00, 16, 00, 1b, 3a, 00, 1f, 00, 24, 20, 21, 25, 00, 1f, 00, 24, 25, 00, 28, 00, 2d, 43, 01, 05, 01, 02]
+Raw bytes (169): 0x[01, 01, 1d, 5b, 0d, 5f, 15, 05, 11, 05, 09, 09, 0d, 6f, 25, 73, 21, 19, 1d, 5b, 67, 5f, 15, 05, 11, 0d, 19, 5b, 67, 5f, 15, 05, 11, 0d, 19, 5b, 63, 5f, 15, 05, 11, 67, 1d, 0d, 19, 5b, 63, 5f, 15, 05, 11, 67, 1d, 0d, 19, 6f, 25, 73, 21, 19, 1d, 13, 01, 24, 01, 01, 10, 02, 04, 09, 00, 0a, 05, 00, 0d, 00, 12, 20, 09, 0e, 00, 0d, 00, 12, 09, 00, 16, 00, 1b, 20, 0d, 12, 00, 16, 00, 1b, 0d, 00, 1f, 00, 24, 20, 11, 15, 00, 1f, 00, 24, 11, 00, 28, 00, 2d, 02, 01, 05, 00, 11, 6b, 03, 09, 00, 0a, 02, 00, 0d, 00, 12, 20, 19, 32, 00, 0d, 00, 12, 32, 00, 16, 00, 1b, 20, 1d, 56, 00, 16, 00, 1b, 56, 00, 1f, 00, 24, 20, 21, 25, 00, 1f, 00, 24, 25, 00, 28, 00, 2d, 6b, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 19
-- expression 0 operands: lhs = Counter(4), rhs = Expression(1, Add)
-- expression 1 operands: lhs = Expression(2, Add), rhs = Expression(5, Sub)
-- expression 2 operands: lhs = Counter(5), rhs = Expression(6, Sub)
-- expression 3 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 4 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 5 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 6 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 7 operands: lhs = Expression(17, Add), rhs = Counter(9)
-- expression 8 operands: lhs = Expression(18, Add), rhs = Counter(8)
-- expression 9 operands: lhs = Counter(6), rhs = Counter(7)
-- expression 10 operands: lhs = Expression(0, Add), rhs = Counter(6)
-- expression 11 operands: lhs = Expression(0, Add), rhs = Counter(6)
-- expression 12 operands: lhs = Expression(15, Sub), rhs = Counter(7)
-- expression 13 operands: lhs = Expression(0, Add), rhs = Counter(6)
-- expression 14 operands: lhs = Expression(15, Sub), rhs = Counter(7)
-- expression 15 operands: lhs = Expression(0, Add), rhs = Counter(6)
-- expression 16 operands: lhs = Expression(17, Add), rhs = Counter(9)
-- expression 17 operands: lhs = Expression(18, Add), rhs = Counter(8)
-- expression 18 operands: lhs = Counter(6), rhs = Counter(7)
+Number of expressions: 29
+- expression 0 operands: lhs = Expression(22, Add), rhs = Counter(3)
+- expression 1 operands: lhs = Expression(23, Add), rhs = Counter(5)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(4)
+- expression 3 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 4 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 5 operands: lhs = Expression(27, Add), rhs = Counter(9)
+- expression 6 operands: lhs = Expression(28, Add), rhs = Counter(8)
+- expression 7 operands: lhs = Counter(6), rhs = Counter(7)
+- expression 8 operands: lhs = Expression(22, Add), rhs = Expression(25, Add)
+- expression 9 operands: lhs = Expression(23, Add), rhs = Counter(5)
+- expression 10 operands: lhs = Counter(1), rhs = Counter(4)
+- expression 11 operands: lhs = Counter(3), rhs = Counter(6)
+- expression 12 operands: lhs = Expression(22, Add), rhs = Expression(25, Add)
+- expression 13 operands: lhs = Expression(23, Add), rhs = Counter(5)
+- expression 14 operands: lhs = Counter(1), rhs = Counter(4)
+- expression 15 operands: lhs = Counter(3), rhs = Counter(6)
+- expression 16 operands: lhs = Expression(22, Add), rhs = Expression(24, Add)
+- expression 17 operands: lhs = Expression(23, Add), rhs = Counter(5)
+- expression 18 operands: lhs = Counter(1), rhs = Counter(4)
+- expression 19 operands: lhs = Expression(25, Add), rhs = Counter(7)
+- expression 20 operands: lhs = Counter(3), rhs = Counter(6)
+- expression 21 operands: lhs = Expression(22, Add), rhs = Expression(24, Add)
+- expression 22 operands: lhs = Expression(23, Add), rhs = Counter(5)
+- expression 23 operands: lhs = Counter(1), rhs = Counter(4)
+- expression 24 operands: lhs = Expression(25, Add), rhs = Counter(7)
+- expression 25 operands: lhs = Counter(3), rhs = Counter(6)
+- expression 26 operands: lhs = Expression(27, Add), rhs = Counter(9)
+- expression 27 operands: lhs = Expression(28, Add), rhs = Counter(8)
+- expression 28 operands: lhs = Counter(6), rhs = Counter(7)
 Number of file 0 mappings: 19
 - Code(Counter(0)) at (prev + 36, 1) to (start + 1, 16)
-- Code(Expression(0, Add)) at (prev + 4, 9) to (start + 0, 10)
-    = (c4 + ((c5 + (c2 - c3)) + (c1 - c2)))
+- Code(Expression(0, Sub)) at (prev + 4, 9) to (start + 0, 10)
+    = (((c1 + c4) + c5) - c3)
 - Code(Counter(1)) at (prev + 0, 13) to (start + 0, 18)
-- Branch { true: Counter(2), false: Expression(5, Sub) } at (prev + 0, 13) to (start + 0, 18)
+- Branch { true: Counter(2), false: Expression(3, Sub) } at (prev + 0, 13) to (start + 0, 18)
     true  = c2
     false = (c1 - c2)
 - Code(Counter(2)) at (prev + 0, 22) to (start + 0, 27)
-- Branch { true: Counter(3), false: Expression(6, Sub) } at (prev + 0, 22) to (start + 0, 27)
+- Branch { true: Counter(3), false: Expression(4, Sub) } at (prev + 0, 22) to (start + 0, 27)
     true  = c3
     false = (c2 - c3)
 - Code(Counter(3)) at (prev + 0, 31) to (start + 0, 36)
@@ -74,97 +84,87 @@ Number of file 0 mappings: 19
     true  = c4
     false = c5
 - Code(Counter(4)) at (prev + 0, 40) to (start + 0, 45)
-- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 0, 17)
-    = (c4 + ((c5 + (c2 - c3)) + (c1 - c2)))
-- Code(Expression(16, Add)) at (prev + 3, 9) to (start + 0, 10)
+- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 17)
+    = (((c1 + c4) + c5) - c3)
+- Code(Expression(26, Add)) at (prev + 3, 9) to (start + 0, 10)
     = (((c6 + c7) + c8) + c9)
-- Code(Expression(0, Add)) at (prev + 0, 13) to (start + 0, 18)
-    = (c4 + ((c5 + (c2 - c3)) + (c1 - c2)))
-- Branch { true: Counter(6), false: Expression(15, Sub) } at (prev + 0, 13) to (start + 0, 18)
+- Code(Expression(0, Sub)) at (prev + 0, 13) to (start + 0, 18)
+    = (((c1 + c4) + c5) - c3)
+- Branch { true: Counter(6), false: Expression(12, Sub) } at (prev + 0, 13) to (start + 0, 18)
     true  = c6
-    false = ((c4 + ((c5 + (c2 - c3)) + (c1 - c2))) - c6)
-- Code(Expression(15, Sub)) at (prev + 0, 22) to (start + 0, 27)
-    = ((c4 + ((c5 + (c2 - c3)) + (c1 - c2))) - c6)
-- Branch { true: Counter(7), false: Expression(14, Sub) } at (prev + 0, 22) to (start + 0, 27)
+    false = (((c1 + c4) + c5) - (c3 + c6))
+- Code(Expression(12, Sub)) at (prev + 0, 22) to (start + 0, 27)
+    = (((c1 + c4) + c5) - (c3 + c6))
+- Branch { true: Counter(7), false: Expression(21, Sub) } at (prev + 0, 22) to (start + 0, 27)
     true  = c7
-    false = (((c4 + ((c5 + (c2 - c3)) + (c1 - c2))) - c6) - c7)
-- Code(Expression(14, Sub)) at (prev + 0, 31) to (start + 0, 36)
-    = (((c4 + ((c5 + (c2 - c3)) + (c1 - c2))) - c6) - c7)
+    false = (((c1 + c4) + c5) - ((c3 + c6) + c7))
+- Code(Expression(21, Sub)) at (prev + 0, 31) to (start + 0, 36)
+    = (((c1 + c4) + c5) - ((c3 + c6) + c7))
 - Branch { true: Counter(8), false: Counter(9) } at (prev + 0, 31) to (start + 0, 36)
     true  = c8
     false = c9
 - Code(Counter(9)) at (prev + 0, 40) to (start + 0, 45)
-- Code(Expression(16, Add)) at (prev + 1, 5) to (start + 1, 2)
+- Code(Expression(26, Add)) at (prev + 1, 5) to (start + 1, 2)
     = (((c6 + c7) + c8) + c9)
 Highest counter ID seen: c9
 
 Function name: lazy_boolean::nested_mixed
-Raw bytes (155): 0x[01, 01, 16, 33, 1a, 09, 0d, 1e, 0d, 05, 09, 05, 09, 05, 09, 1e, 0d, 05, 09, 09, 0d, 33, 11, 09, 0d, 33, 11, 09, 0d, 19, 57, 1d, 21, 03, 15, 15, 19, 4a, 4e, 15, 19, 03, 15, 19, 57, 1d, 21, 13, 01, 31, 01, 01, 10, 03, 04, 09, 00, 0a, 05, 00, 0e, 00, 13, 20, 09, 1e, 00, 0e, 00, 13, 1e, 00, 17, 00, 1d, 20, 0d, 1a, 00, 17, 00, 1d, 33, 00, 23, 00, 28, 20, 11, 2e, 00, 23, 00, 28, 2e, 00, 2c, 00, 33, 03, 01, 05, 00, 11, 53, 03, 09, 00, 0a, 03, 00, 0e, 00, 13, 20, 15, 4e, 00, 0e, 00, 13, 15, 00, 17, 00, 1c, 20, 19, 4a, 00, 17, 00, 1c, 47, 00, 22, 00, 28, 20, 1d, 21, 00, 22, 00, 28, 1d, 00, 2c, 00, 33, 53, 01, 05, 01, 02]
+Raw bytes (141): 0x[01, 01, 0f, 05, 09, 05, 1f, 09, 0d, 09, 0d, 1f, 11, 09, 0d, 1f, 11, 09, 0d, 3b, 21, 19, 1d, 05, 15, 15, 19, 05, 19, 3b, 21, 19, 1d, 13, 01, 31, 01, 01, 10, 05, 04, 09, 00, 0a, 05, 00, 0e, 00, 13, 20, 09, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 0d, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 11, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 05, 01, 05, 00, 11, 37, 03, 09, 00, 0a, 05, 00, 0e, 00, 13, 20, 15, 2a, 00, 0e, 00, 13, 15, 00, 17, 00, 1c, 20, 19, 2e, 00, 17, 00, 1c, 32, 00, 22, 00, 28, 20, 1d, 21, 00, 22, 00, 28, 1d, 00, 2c, 00, 33, 37, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 22
-- expression 0 operands: lhs = Expression(12, Add), rhs = Expression(6, Sub)
-- expression 1 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 2 operands: lhs = Expression(7, Sub), rhs = Counter(3)
-- expression 3 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 4 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 5 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 6 operands: lhs = Expression(7, Sub), rhs = Counter(3)
-- expression 7 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 8 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 9 operands: lhs = Expression(12, Add), rhs = Counter(4)
-- expression 10 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(4)
-- expression 12 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 13 operands: lhs = Counter(6), rhs = Expression(21, Add)
-- expression 14 operands: lhs = Counter(7), rhs = Counter(8)
-- expression 15 operands: lhs = Expression(0, Add), rhs = Counter(5)
-- expression 16 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 17 operands: lhs = Expression(18, Sub), rhs = Expression(19, Sub)
-- expression 18 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 19 operands: lhs = Expression(0, Add), rhs = Counter(5)
-- expression 20 operands: lhs = Counter(6), rhs = Expression(21, Add)
-- expression 21 operands: lhs = Counter(7), rhs = Counter(8)
+Number of expressions: 15
+- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(7, Add)
+- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 3 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 4 operands: lhs = Expression(7, Add), rhs = Counter(4)
+- expression 5 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(4)
+- expression 7 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 8 operands: lhs = Expression(14, Add), rhs = Counter(8)
+- expression 9 operands: lhs = Counter(6), rhs = Counter(7)
+- expression 10 operands: lhs = Counter(1), rhs = Counter(5)
+- expression 11 operands: lhs = Counter(5), rhs = Counter(6)
+- expression 12 operands: lhs = Counter(1), rhs = Counter(6)
+- expression 13 operands: lhs = Expression(14, Add), rhs = Counter(8)
+- expression 14 operands: lhs = Counter(6), rhs = Counter(7)
 Number of file 0 mappings: 19
 - Code(Counter(0)) at (prev + 49, 1) to (start + 1, 16)
-- Code(Expression(0, Add)) at (prev + 4, 9) to (start + 0, 10)
-    = ((c2 + c3) + ((c1 - c2) - c3))
+- Code(Counter(1)) at (prev + 4, 9) to (start + 0, 10)
 - Code(Counter(1)) at (prev + 0, 14) to (start + 0, 19)
-- Branch { true: Counter(2), false: Expression(7, Sub) } at (prev + 0, 14) to (start + 0, 19)
+- Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 14) to (start + 0, 19)
     true  = c2
     false = (c1 - c2)
-- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 29)
+- Code(Expression(0, Sub)) at (prev + 0, 23) to (start + 0, 29)
     = (c1 - c2)
-- Branch { true: Counter(3), false: Expression(6, Sub) } at (prev + 0, 23) to (start + 0, 29)
+- Branch { true: Counter(3), false: Expression(1, Sub) } at (prev + 0, 23) to (start + 0, 29)
     true  = c3
-    false = ((c1 - c2) - c3)
-- Code(Expression(12, Add)) at (prev + 0, 35) to (start + 0, 40)
+    false = (c1 - (c2 + c3))
+- Code(Expression(7, Add)) at (prev + 0, 35) to (start + 0, 40)
     = (c2 + c3)
-- Branch { true: Counter(4), false: Expression(11, Sub) } at (prev + 0, 35) to (start + 0, 40)
+- Branch { true: Counter(4), false: Expression(6, Sub) } at (prev + 0, 35) to (start + 0, 40)
     true  = c4
     false = ((c2 + c3) - c4)
-- Code(Expression(11, Sub)) at (prev + 0, 44) to (start + 0, 51)
+- Code(Expression(6, Sub)) at (prev + 0, 44) to (start + 0, 51)
     = ((c2 + c3) - c4)
-- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 0, 17)
-    = ((c2 + c3) + ((c1 - c2) - c3))
-- Code(Expression(20, Add)) at (prev + 3, 9) to (start + 0, 10)
-    = (c6 + (c7 + c8))
-- Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 19)
-    = ((c2 + c3) + ((c1 - c2) - c3))
-- Branch { true: Counter(5), false: Expression(19, Sub) } at (prev + 0, 14) to (start + 0, 19)
+- Code(Counter(1)) at (prev + 1, 5) to (start + 0, 17)
+- Code(Expression(13, Add)) at (prev + 3, 9) to (start + 0, 10)
+    = ((c6 + c7) + c8)
+- Code(Counter(1)) at (prev + 0, 14) to (start + 0, 19)
+- Branch { true: Counter(5), false: Expression(10, Sub) } at (prev + 0, 14) to (start + 0, 19)
     true  = c5
-    false = (((c2 + c3) + ((c1 - c2) - c3)) - c5)
+    false = (c1 - c5)
 - Code(Counter(5)) at (prev + 0, 23) to (start + 0, 28)
-- Branch { true: Counter(6), false: Expression(18, Sub) } at (prev + 0, 23) to (start + 0, 28)
+- Branch { true: Counter(6), false: Expression(11, Sub) } at (prev + 0, 23) to (start + 0, 28)
     true  = c6
     false = (c5 - c6)
-- Code(Expression(17, Add)) at (prev + 0, 34) to (start + 0, 40)
-    = ((c5 - c6) + (((c2 + c3) + ((c1 - c2) - c3)) - c5))
+- Code(Expression(12, Sub)) at (prev + 0, 34) to (start + 0, 40)
+    = (c1 - c6)
 - Branch { true: Counter(7), false: Counter(8) } at (prev + 0, 34) to (start + 0, 40)
     true  = c7
     false = c8
 - Code(Counter(7)) at (prev + 0, 44) to (start + 0, 51)
-- Code(Expression(20, Add)) at (prev + 1, 5) to (start + 1, 2)
-    = (c6 + (c7 + c8))
+- Code(Expression(13, Add)) at (prev + 1, 5) to (start + 1, 2)
+    = ((c6 + c7) + c8)
 Highest counter ID seen: c8
 
diff --git a/tests/coverage/branch/match-arms.cov-map b/tests/coverage/branch/match-arms.cov-map
index fd0366ee818..a93df9814ee 100644
--- a/tests/coverage/branch/match-arms.cov-map
+++ b/tests/coverage/branch/match-arms.cov-map
@@ -1,12 +1,12 @@
 Function name: match_arms::guards
-Raw bytes (88): 0x[01, 01, 08, 07, 15, 0b, 11, 0f, 0d, 00, 09, 17, 25, 1b, 21, 1f, 1d, 03, 19, 0c, 01, 30, 01, 01, 10, 29, 03, 0b, 00, 10, 19, 01, 11, 00, 29, 20, 19, 09, 00, 17, 00, 1b, 1d, 01, 11, 00, 29, 20, 1d, 0d, 00, 17, 00, 1b, 21, 01, 11, 00, 29, 20, 21, 11, 00, 17, 00, 1b, 25, 01, 11, 00, 29, 20, 25, 15, 00, 17, 00, 1b, 03, 01, 0e, 00, 18, 13, 03, 05, 01, 02]
+Raw bytes (88): 0x[01, 01, 08, 07, 00, 0b, 11, 0f, 0d, 05, 09, 17, 25, 1b, 21, 1f, 1d, 03, 19, 0c, 01, 30, 01, 01, 10, 29, 03, 0b, 00, 10, 19, 01, 11, 00, 29, 20, 19, 05, 00, 17, 00, 1b, 1d, 01, 11, 00, 29, 20, 1d, 09, 00, 17, 00, 1b, 21, 01, 11, 00, 29, 20, 21, 0d, 00, 17, 00, 1b, 25, 01, 11, 00, 29, 20, 25, 11, 00, 17, 00, 1b, 03, 01, 0e, 00, 18, 13, 03, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 8
-- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(5)
+- expression 0 operands: lhs = Expression(1, Add), rhs = Zero
 - expression 1 operands: lhs = Expression(2, Add), rhs = Counter(4)
 - expression 2 operands: lhs = Expression(3, Add), rhs = Counter(3)
-- expression 3 operands: lhs = Zero, rhs = Counter(2)
+- expression 3 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 4 operands: lhs = Expression(5, Add), rhs = Counter(9)
 - expression 5 operands: lhs = Expression(6, Add), rhs = Counter(8)
 - expression 6 operands: lhs = Expression(7, Add), rhs = Counter(7)
@@ -15,81 +15,67 @@ Number of file 0 mappings: 12
 - Code(Counter(0)) at (prev + 48, 1) to (start + 1, 16)
 - Code(Counter(10)) at (prev + 3, 11) to (start + 0, 16)
 - Code(Counter(6)) at (prev + 1, 17) to (start + 0, 41)
-- Branch { true: Counter(6), false: Counter(2) } at (prev + 0, 23) to (start + 0, 27)
+- Branch { true: Counter(6), false: Counter(1) } at (prev + 0, 23) to (start + 0, 27)
     true  = c6
-    false = c2
+    false = c1
 - Code(Counter(7)) at (prev + 1, 17) to (start + 0, 41)
-- Branch { true: Counter(7), false: Counter(3) } at (prev + 0, 23) to (start + 0, 27)
+- Branch { true: Counter(7), false: Counter(2) } at (prev + 0, 23) to (start + 0, 27)
     true  = c7
-    false = c3
+    false = c2
 - Code(Counter(8)) at (prev + 1, 17) to (start + 0, 41)
-- Branch { true: Counter(8), false: Counter(4) } at (prev + 0, 23) to (start + 0, 27)
+- Branch { true: Counter(8), false: Counter(3) } at (prev + 0, 23) to (start + 0, 27)
     true  = c8
-    false = c4
+    false = c3
 - Code(Counter(9)) at (prev + 1, 17) to (start + 0, 41)
-- Branch { true: Counter(9), false: Counter(5) } at (prev + 0, 23) to (start + 0, 27)
+- Branch { true: Counter(9), false: Counter(4) } at (prev + 0, 23) to (start + 0, 27)
     true  = c9
-    false = c5
+    false = c4
 - Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 24)
-    = ((((Zero + c2) + c3) + c4) + c5)
+    = ((((c1 + c2) + c3) + c4) + Zero)
 - Code(Expression(4, Add)) at (prev + 3, 5) to (start + 1, 2)
-    = ((((((((Zero + c2) + c3) + c4) + c5) + c6) + c7) + c8) + c9)
+    = ((((((((c1 + c2) + c3) + c4) + Zero) + c6) + c7) + c8) + c9)
 Highest counter ID seen: c10
 
 Function name: match_arms::match_arms
-Raw bytes (51): 0x[01, 01, 06, 05, 07, 0b, 11, 09, 0d, 13, 02, 17, 09, 11, 0d, 07, 01, 18, 01, 01, 10, 05, 03, 0b, 00, 10, 11, 01, 11, 00, 21, 0d, 01, 11, 00, 21, 09, 01, 11, 00, 21, 02, 01, 11, 00, 21, 0f, 03, 05, 01, 02]
+Raw bytes (45): 0x[01, 01, 03, 05, 07, 0b, 11, 09, 0d, 07, 01, 18, 01, 01, 10, 05, 03, 0b, 00, 10, 09, 01, 11, 00, 21, 0d, 01, 11, 00, 21, 11, 01, 11, 00, 21, 02, 01, 11, 00, 21, 05, 03, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 6
+Number of expressions: 3
 - expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add)
 - expression 1 operands: lhs = Expression(2, Add), rhs = Counter(4)
 - expression 2 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 3 operands: lhs = Expression(4, Add), rhs = Expression(0, Sub)
-- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(2)
-- expression 5 operands: lhs = Counter(4), rhs = Counter(3)
 Number of file 0 mappings: 7
 - Code(Counter(0)) at (prev + 24, 1) to (start + 1, 16)
 - Code(Counter(1)) at (prev + 3, 11) to (start + 0, 16)
-- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 33)
-- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 33)
 - Code(Counter(2)) at (prev + 1, 17) to (start + 0, 33)
+- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 33)
+- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 33)
 - Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 33)
     = (c1 - ((c2 + c3) + c4))
-- Code(Expression(3, Add)) at (prev + 3, 5) to (start + 1, 2)
-    = (((c4 + c3) + c2) + (c1 - ((c2 + c3) + c4)))
+- Code(Counter(1)) at (prev + 3, 5) to (start + 1, 2)
 Highest counter ID seen: c4
 
 Function name: match_arms::or_patterns
-Raw bytes (75): 0x[01, 01, 0d, 11, 0d, 05, 2f, 33, 11, 09, 0d, 09, 2a, 05, 2f, 33, 11, 09, 0d, 03, 27, 09, 2a, 05, 2f, 33, 11, 09, 0d, 09, 01, 25, 01, 01, 10, 05, 03, 0b, 00, 10, 11, 01, 11, 00, 12, 0d, 00, 1e, 00, 1f, 03, 00, 24, 00, 2e, 09, 01, 11, 00, 12, 2a, 00, 1e, 00, 1f, 27, 00, 24, 00, 2e, 23, 03, 05, 01, 02]
+Raw bytes (57): 0x[01, 01, 04, 09, 0d, 05, 0b, 03, 11, 05, 03, 09, 01, 25, 01, 01, 10, 05, 03, 0b, 00, 10, 09, 01, 11, 00, 12, 0d, 00, 1e, 00, 1f, 03, 00, 24, 00, 2e, 11, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2e, 05, 03, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 13
-- expression 0 operands: lhs = Counter(4), rhs = Counter(3)
-- expression 1 operands: lhs = Counter(1), rhs = Expression(11, Add)
-- expression 2 operands: lhs = Expression(12, Add), rhs = Counter(4)
-- expression 3 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 4 operands: lhs = Counter(2), rhs = Expression(10, Sub)
-- expression 5 operands: lhs = Counter(1), rhs = Expression(11, Add)
-- expression 6 operands: lhs = Expression(12, Add), rhs = Counter(4)
-- expression 7 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 8 operands: lhs = Expression(0, Add), rhs = Expression(9, Add)
-- expression 9 operands: lhs = Counter(2), rhs = Expression(10, Sub)
-- expression 10 operands: lhs = Counter(1), rhs = Expression(11, Add)
-- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(4)
-- expression 12 operands: lhs = Counter(2), rhs = Counter(3)
+Number of expressions: 4
+- expression 0 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add)
+- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(4)
+- expression 3 operands: lhs = Counter(1), rhs = Expression(0, Add)
 Number of file 0 mappings: 9
 - Code(Counter(0)) at (prev + 37, 1) to (start + 1, 16)
 - Code(Counter(1)) at (prev + 3, 11) to (start + 0, 16)
-- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 18)
+- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18)
 - Code(Counter(3)) at (prev + 0, 30) to (start + 0, 31)
 - Code(Expression(0, Add)) at (prev + 0, 36) to (start + 0, 46)
-    = (c4 + c3)
-- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18)
-- Code(Expression(10, Sub)) at (prev + 0, 30) to (start + 0, 31)
+    = (c2 + c3)
+- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 18)
+- Code(Expression(1, Sub)) at (prev + 0, 30) to (start + 0, 31)
     = (c1 - ((c2 + c3) + c4))
-- Code(Expression(9, Add)) at (prev + 0, 36) to (start + 0, 46)
-    = (c2 + (c1 - ((c2 + c3) + c4)))
-- Code(Expression(8, Add)) at (prev + 3, 5) to (start + 1, 2)
-    = ((c4 + c3) + (c2 + (c1 - ((c2 + c3) + c4))))
+- Code(Expression(3, Sub)) at (prev + 0, 36) to (start + 0, 46)
+    = (c1 - (c2 + c3))
+- Code(Counter(1)) at (prev + 3, 5) to (start + 1, 2)
 Highest counter ID seen: c4
 
diff --git a/tests/coverage/branch/no-mir-spans.cov-map b/tests/coverage/branch/no-mir-spans.cov-map
index ab12732b1ed..6003efc36ca 100644
--- a/tests/coverage/branch/no-mir-spans.cov-map
+++ b/tests/coverage/branch/no-mir-spans.cov-map
@@ -23,19 +23,19 @@ Number of file 0 mappings: 2
 Highest counter ID seen: c2
 
 Function name: no_mir_spans::while_op_and
-Raw bytes (25): 0x[01, 01, 01, 09, 0d, 03, 01, 22, 01, 00, 13, 20, 09, 05, 05, 0b, 00, 10, 20, 02, 0d, 00, 14, 00, 19]
+Raw bytes (25): 0x[01, 01, 01, 05, 09, 03, 01, 22, 01, 00, 13, 20, 05, 0d, 05, 0b, 00, 10, 20, 02, 09, 00, 14, 00, 19]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
-- expression 0 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 3
 - Code(Counter(0)) at (prev + 34, 1) to (start + 0, 19)
-- Branch { true: Counter(2), false: Counter(1) } at (prev + 5, 11) to (start + 0, 16)
-    true  = c2
-    false = c1
-- Branch { true: Expression(0, Sub), false: Counter(3) } at (prev + 0, 20) to (start + 0, 25)
-    true  = (c2 - c3)
+- Branch { true: Counter(1), false: Counter(3) } at (prev + 5, 11) to (start + 0, 16)
+    true  = c1
     false = c3
+- Branch { true: Expression(0, Sub), false: Counter(2) } at (prev + 0, 20) to (start + 0, 25)
+    true  = (c1 - c2)
+    false = c2
 Highest counter ID seen: c3
 
 Function name: no_mir_spans::while_op_or
diff --git a/tests/coverage/branch/while.cov-map b/tests/coverage/branch/while.cov-map
index d5840a2c320..305f6bc74d8 100644
--- a/tests/coverage/branch/while.cov-map
+++ b/tests/coverage/branch/while.cov-map
@@ -35,14 +35,14 @@ Number of file 0 mappings: 6
 Highest counter ID seen: c2
 
 Function name: while::while_op_and
-Raw bytes (56): 0x[01, 01, 04, 05, 09, 03, 0d, 03, 0d, 11, 0d, 08, 01, 1e, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 20, 0a, 0d, 00, 0b, 00, 10, 0a, 00, 14, 00, 19, 20, 09, 11, 00, 14, 00, 19, 09, 00, 1a, 03, 06, 0f, 04, 01, 00, 02]
+Raw bytes (56): 0x[01, 01, 04, 05, 09, 03, 0d, 03, 0d, 0d, 11, 08, 01, 1e, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 20, 0a, 0d, 00, 0b, 00, 10, 0a, 00, 14, 00, 19, 20, 09, 11, 00, 14, 00, 19, 09, 00, 1a, 03, 06, 0f, 04, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
 - expression 0 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 1 operands: lhs = Expression(0, Add), rhs = Counter(3)
 - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 3 operands: lhs = Counter(4), rhs = Counter(3)
+- expression 3 operands: lhs = Counter(3), rhs = Counter(4)
 Number of file 0 mappings: 8
 - Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16)
 - Code(Counter(1)) at (prev + 3, 9) to (start + 1, 18)
@@ -58,39 +58,34 @@ Number of file 0 mappings: 8
     false = c4
 - Code(Counter(2)) at (prev + 0, 26) to (start + 3, 6)
 - Code(Expression(3, Add)) at (prev + 4, 1) to (start + 0, 2)
-    = (c4 + c3)
+    = (c3 + c4)
 Highest counter ID seen: c4
 
 Function name: while::while_op_or
-Raw bytes (66): 0x[01, 01, 09, 05, 1b, 09, 0d, 03, 09, 03, 09, 22, 0d, 03, 09, 09, 0d, 22, 0d, 03, 09, 08, 01, 29, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 20, 09, 22, 00, 0b, 00, 10, 22, 00, 14, 00, 19, 20, 0d, 1e, 00, 14, 00, 19, 1b, 00, 1a, 03, 06, 1e, 04, 01, 00, 02]
+Raw bytes (58): 0x[01, 01, 05, 07, 0d, 05, 09, 05, 0d, 05, 0d, 09, 0d, 08, 01, 29, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 20, 09, 0f, 00, 0b, 00, 10, 0f, 00, 14, 00, 19, 20, 0d, 05, 00, 14, 00, 19, 13, 00, 1a, 03, 06, 05, 04, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 9
-- expression 0 operands: lhs = Counter(1), rhs = Expression(6, Add)
-- expression 1 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(2)
-- expression 3 operands: lhs = Expression(0, Add), rhs = Counter(2)
-- expression 4 operands: lhs = Expression(8, Sub), rhs = Counter(3)
-- expression 5 operands: lhs = Expression(0, Add), rhs = Counter(2)
-- expression 6 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(3)
-- expression 8 operands: lhs = Expression(0, Add), rhs = Counter(2)
+Number of expressions: 5
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3)
+- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(3)
+- expression 3 operands: lhs = Counter(1), rhs = Counter(3)
+- expression 4 operands: lhs = Counter(2), rhs = Counter(3)
 Number of file 0 mappings: 8
 - Code(Counter(0)) at (prev + 41, 1) to (start + 1, 16)
 - Code(Counter(1)) at (prev + 3, 9) to (start + 1, 18)
 - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 16)
-    = (c1 + (c2 + c3))
-- Branch { true: Counter(2), false: Expression(8, Sub) } at (prev + 0, 11) to (start + 0, 16)
+    = ((c1 + c2) + c3)
+- Branch { true: Counter(2), false: Expression(3, Add) } at (prev + 0, 11) to (start + 0, 16)
     true  = c2
-    false = ((c1 + (c2 + c3)) - c2)
-- Code(Expression(8, Sub)) at (prev + 0, 20) to (start + 0, 25)
-    = ((c1 + (c2 + c3)) - c2)
-- Branch { true: Counter(3), false: Expression(7, Sub) } at (prev + 0, 20) to (start + 0, 25)
+    false = (c1 + c3)
+- Code(Expression(3, Add)) at (prev + 0, 20) to (start + 0, 25)
+    = (c1 + c3)
+- Branch { true: Counter(3), false: Counter(1) } at (prev + 0, 20) to (start + 0, 25)
     true  = c3
-    false = (((c1 + (c2 + c3)) - c2) - c3)
-- Code(Expression(6, Add)) at (prev + 0, 26) to (start + 3, 6)
+    false = c1
+- Code(Expression(4, Add)) at (prev + 0, 26) to (start + 3, 6)
     = (c2 + c3)
-- Code(Expression(7, Sub)) at (prev + 4, 1) to (start + 0, 2)
-    = (((c1 + (c2 + c3)) - c2) - c3)
+- Code(Counter(1)) at (prev + 4, 1) to (start + 0, 2)
 Highest counter ID seen: c3
 
diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map
index 7c9d3292f98..aedb924eca8 100644
--- a/tests/coverage/closure_macro.cov-map
+++ b/tests/coverage/closure_macro.cov-map
@@ -25,13 +25,13 @@ Number of file 0 mappings: 6
 Highest counter ID seen: c1
 
 Function name: closure_macro::main::{closure#0}
-Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 0d, 05, 01, 10, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a]
+Raw bytes (35): 0x[01, 01, 03, 01, 05, 0b, 0d, 05, 09, 05, 01, 10, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 3
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add)
-- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 5
 - Code(Counter(0)) at (prev + 16, 28) to (start + 3, 33)
 - Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39)
@@ -39,6 +39,6 @@ Number of file 0 mappings: 5
     = (c0 - c1)
 - Code(Counter(3)) at (prev + 0, 23) to (start + 0, 30)
 - Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10)
-    = (c1 + (c2 + c3))
+    = ((c1 + c2) + c3)
 Highest counter ID seen: c3
 
diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map
index e2a52e57015..5b99889514c 100644
--- a/tests/coverage/closure_macro_async.cov-map
+++ b/tests/coverage/closure_macro_async.cov-map
@@ -34,13 +34,13 @@ Number of file 0 mappings: 6
 Highest counter ID seen: c1
 
 Function name: closure_macro_async::test::{closure#0}::{closure#0}
-Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 0d, 05, 01, 15, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a]
+Raw bytes (35): 0x[01, 01, 03, 01, 05, 0b, 0d, 05, 09, 05, 01, 15, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 3
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add)
-- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 5
 - Code(Counter(0)) at (prev + 21, 28) to (start + 3, 33)
 - Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39)
@@ -48,6 +48,6 @@ Number of file 0 mappings: 5
     = (c0 - c1)
 - Code(Counter(3)) at (prev + 0, 23) to (start + 0, 30)
 - Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10)
-    = (c1 + (c2 + c3))
+    = ((c1 + c2) + c3)
 Highest counter ID seen: c3
 
diff --git a/tests/coverage/condition/conditions.cov-map b/tests/coverage/condition/conditions.cov-map
index 208d671919c..72f39b88c6a 100644
--- a/tests/coverage/condition/conditions.cov-map
+++ b/tests/coverage/condition/conditions.cov-map
@@ -1,29 +1,27 @@
 Function name: conditions::assign_3_and_or
-Raw bytes (69): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 09, 01, 1c, 01, 00, 2f, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 1a, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 16, 00, 12, 00, 13, 13, 00, 17, 00, 18, 20, 0d, 11, 00, 17, 00, 18, 03, 01, 05, 01, 02]
+Raw bytes (65): 0x[01, 01, 05, 07, 11, 09, 0d, 01, 05, 05, 09, 01, 09, 09, 01, 1c, 01, 00, 2f, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0a, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 0e, 00, 12, 00, 13, 12, 00, 17, 00, 18, 20, 0d, 11, 00, 17, 00, 18, 03, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 7
+Number of expressions: 5
 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(4)
 - expression 1 operands: lhs = Counter(2), rhs = Counter(3)
 - expression 2 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 3 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 4 operands: lhs = Expression(5, Sub), rhs = Expression(6, Sub)
-- expression 5 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 6 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 4 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 9
 - Code(Counter(0)) at (prev + 28, 1) to (start + 0, 47)
 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
     = ((c2 + c3) + c4)
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
-- Branch { true: Counter(1), false: Expression(6, Sub) } at (prev + 0, 13) to (start + 0, 14)
+- Branch { true: Counter(1), false: Expression(2, Sub) } at (prev + 0, 13) to (start + 0, 14)
     true  = c1
     false = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19)
-- Branch { true: Counter(2), false: Expression(5, Sub) } at (prev + 0, 18) to (start + 0, 19)
+- Branch { true: Counter(2), false: Expression(3, Sub) } at (prev + 0, 18) to (start + 0, 19)
     true  = c2
     false = (c1 - c2)
-- Code(Expression(4, Add)) at (prev + 0, 23) to (start + 0, 24)
-    = ((c1 - c2) + (c0 - c1))
+- Code(Expression(4, Sub)) at (prev + 0, 23) to (start + 0, 24)
+    = (c0 - c2)
 - Branch { true: Counter(3), false: Counter(4) } at (prev + 0, 23) to (start + 0, 24)
     true  = c3
     false = c4
@@ -32,54 +30,54 @@ Number of file 0 mappings: 9
 Highest counter ID seen: c4
 
 Function name: conditions::assign_3_or_and
-Raw bytes (73): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 09, 01, 17, 01, 00, 2f, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 22, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 20, 1e, 11, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 20, 09, 0d, 00, 17, 00, 18, 03, 01, 05, 01, 02]
+Raw bytes (73): 0x[01, 01, 09, 07, 11, 0b, 0d, 05, 09, 01, 05, 01, 05, 01, 23, 05, 11, 01, 23, 05, 11, 09, 01, 17, 01, 00, 2f, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 12, 00, 0d, 00, 0e, 12, 00, 12, 00, 13, 20, 1e, 11, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 20, 09, 0d, 00, 17, 00, 18, 03, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 9
-- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add)
-- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(4)
-- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(4)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 3 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 4 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 5 operands: lhs = Expression(8, Sub), rhs = Counter(4)
-- expression 6 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(4)
-- expression 8 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 5 operands: lhs = Counter(0), rhs = Expression(8, Add)
+- expression 6 operands: lhs = Counter(1), rhs = Counter(4)
+- expression 7 operands: lhs = Counter(0), rhs = Expression(8, Add)
+- expression 8 operands: lhs = Counter(1), rhs = Counter(4)
 Number of file 0 mappings: 9
 - Code(Counter(0)) at (prev + 23, 1) to (start + 0, 47)
 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
-    = (c1 + ((c2 + c3) + c4))
+    = (((c1 + c2) + c3) + c4)
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
-- Branch { true: Counter(1), false: Expression(8, Sub) } at (prev + 0, 13) to (start + 0, 14)
+- Branch { true: Counter(1), false: Expression(4, Sub) } at (prev + 0, 13) to (start + 0, 14)
     true  = c1
     false = (c0 - c1)
-- Code(Expression(8, Sub)) at (prev + 0, 18) to (start + 0, 19)
+- Code(Expression(4, Sub)) at (prev + 0, 18) to (start + 0, 19)
     = (c0 - c1)
 - Branch { true: Expression(7, Sub), false: Counter(4) } at (prev + 0, 18) to (start + 0, 19)
-    true  = ((c0 - c1) - c4)
+    true  = (c0 - (c1 + c4))
     false = c4
 - Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 24)
-    = ((c0 - c1) - c4)
+    = (c0 - (c1 + c4))
 - Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 23) to (start + 0, 24)
     true  = c2
     false = c3
 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2)
-    = (c1 + ((c2 + c3) + c4))
+    = (((c1 + c2) + c3) + c4)
 Highest counter ID seen: c4
 
 Function name: conditions::assign_and
-Raw bytes (51): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 07, 01, 0d, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02]
+Raw bytes (51): 0x[01, 01, 04, 07, 05, 0b, 0d, 01, 09, 01, 05, 07, 01, 0d, 01, 00, 21, 02, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 02, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
-- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(3, Sub)
-- expression 1 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 2 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(1)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3)
+- expression 2 operands: lhs = Counter(0), rhs = Counter(2)
 - expression 3 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 7
 - Code(Counter(0)) at (prev + 13, 1) to (start + 0, 33)
-- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
-    = ((c2 + c3) + (c0 - c1))
+- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10)
+    = (((c0 + c2) + c3) - c1)
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
 - Branch { true: Counter(1), false: Expression(3, Sub) } at (prev + 0, 13) to (start + 0, 14)
     true  = c1
@@ -88,8 +86,8 @@ Number of file 0 mappings: 7
 - Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 18) to (start + 0, 19)
     true  = c2
     false = c3
-- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2)
-    = ((c2 + c3) + (c0 - c1))
+- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 1, 2)
+    = (((c0 + c2) + c3) - c1)
 Highest counter ID seen: c3
 
 Function name: conditions::assign_or
@@ -128,13 +126,14 @@ Number of file 0 mappings: 1
 Highest counter ID seen: c0
 
 Function name: conditions::func_call
-Raw bytes (39): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 05, 01, 25, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 0d, 00, 0e, 00, 0f, 07, 01, 01, 00, 02]
+Raw bytes (41): 0x[01, 01, 04, 01, 05, 0b, 05, 0f, 0d, 01, 09, 05, 01, 25, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 0d, 00, 0e, 00, 0f, 06, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 3
+Number of expressions: 4
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub)
-- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(1)
+- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(3)
+- expression 3 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 5
 - Code(Counter(0)) at (prev + 37, 1) to (start + 1, 10)
 - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 9) to (start + 0, 10)
@@ -144,8 +143,8 @@ Number of file 0 mappings: 5
 - Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 14) to (start + 0, 15)
     true  = c2
     false = c3
-- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2)
-    = ((c2 + c3) + (c0 - c1))
+- Code(Expression(1, Sub)) at (prev + 1, 1) to (start + 0, 2)
+    = (((c0 + c2) + c3) - c1)
 Highest counter ID seen: c3
 
 Function name: conditions::simple_assign
diff --git a/tests/coverage/conditions.cov-map b/tests/coverage/conditions.cov-map
index 938e4404013..21b2ec9a19e 100644
--- a/tests/coverage/conditions.cov-map
+++ b/tests/coverage/conditions.cov-map
@@ -1,264 +1,294 @@
 Function name: conditions::main
-Raw bytes (799): 0x[01, 01, 94, 01, 09, 2b, 2f, 41, 33, 3d, 35, 39, 01, 09, 0d, 35, 1e, 39, 0d, 35, 33, 3d, 35, 39, 2f, 41, 33, 3d, 35, 39, ce, 04, 0d, 01, 09, 03, 49, 62, 31, 03, 49, 5e, 4d, 62, 31, 03, 49, 5a, 51, 5e, 4d, 62, 31, 03, 49, 87, 01, 55, 4d, 51, 83, 01, 59, 87, 01, 55, 4d, 51, 49, 7f, 83, 01, 59, 87, 01, 55, 4d, 51, 5d, 65, ae, 01, 2d, 5d, 65, aa, 01, 69, ae, 01, 2d, 5d, 65, a6, 01, 6d, aa, 01, 69, ae, 01, 2d, 5d, 65, f3, 02, 71, 69, 6d, ef, 02, 75, f3, 02, 71, 69, 6d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, e3, 02, 7d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, de, 02, 29, e3, 02, 7d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, da, 02, 81, 01, de, 02, 29, e3, 02, 7d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, d6, 02, 85, 01, da, 02, 81, 01, de, 02, 29, e3, 02, 7d, e7, 02, 00, 65, eb, 02, ef, 02, 75, f3, 02, 71, 69, 6d, 8f, 04, 89, 01, 81, 01, 85, 01, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, 11, af, 04, b3, 04, 21, b7, 04, 1d, 15, 19, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, 83, 04, 11, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, fe, 03, 25, 83, 04, 11, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, fa, 03, 15, fe, 03, 25, 83, 04, 11, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, f6, 03, 19, fa, 03, 15, fe, 03, 25, 83, 04, 11, 7d, 87, 04, 8b, 04, 8d, 01, 8f, 04, 89, 01, 81, 01, 85, 01, b7, 04, 1d, 15, 19, b3, 04, 21, b7, 04, 1d, 15, 19, ab, 04, bb, 04, 11, af, 04, b3, 04, 21, b7, 04, 1d, 15, 19, bf, 04, ca, 04, c3, 04, 31, c7, 04, 2d, 25, 29, ce, 04, 0d, 01, 09, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 05, 00, 06, 03, 03, 09, 00, 0a, 01, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, ce, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 1e, 00, 1d, 00, 2a, 1a, 00, 2e, 00, 3c, 2f, 00, 3d, 02, 0a, 41, 02, 09, 00, 0a, 2b, 01, 09, 01, 12, ca, 04, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 05, 00, 06, 03, 02, 08, 00, 15, 49, 00, 16, 02, 06, 62, 02, 0f, 00, 1c, 5e, 01, 0c, 00, 19, 5a, 00, 1d, 00, 2a, 56, 00, 2e, 00, 3c, 83, 01, 00, 3d, 02, 0a, 59, 02, 09, 00, 0a, 7f, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 7b, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 09, 00, 0a, 5d, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, ae, 01, 04, 11, 00, 1e, aa, 01, 01, 10, 00, 1d, a6, 01, 00, 21, 00, 2e, a2, 01, 00, 32, 00, 40, ef, 02, 00, 41, 02, 0e, 75, 02, 0d, 00, 0e, eb, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 05, 00, 06, e3, 02, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 05, 00, 06, 83, 04, 02, 09, 00, 0a, e3, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, de, 02, 02, 0f, 00, 1c, da, 02, 01, 0c, 00, 19, d6, 02, 00, 1d, 00, 2a, d2, 02, 00, 2e, 00, 3c, 8b, 04, 00, 3d, 02, 0a, 8d, 01, 02, 09, 00, 0a, 87, 04, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, ab, 04, 05, 09, 00, 0a, 83, 04, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, fe, 03, 02, 0f, 00, 1c, fa, 03, 01, 0c, 00, 19, f6, 03, 00, 1d, 00, 2a, f2, 03, 00, 2e, 00, 3c, b3, 04, 00, 3d, 02, 0a, 21, 02, 09, 00, 0a, af, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, a7, 04, 02, 01, 00, 02]
+Raw bytes (873): 0x[01, 01, b2, 01, 07, 19, 0b, 15, 0f, 11, 09, 0d, 01, 09, 8d, 01, 0d, 8d, 01, 33, 0d, 11, 33, 15, 0d, 11, 2f, 19, 33, 15, 0d, 11, 01, c7, 05, 09, 8d, 01, 03, 21, 03, 47, 21, 89, 01, 03, 4f, db, 03, 89, 01, 21, 25, 03, 5b, d7, 03, 89, 01, db, 03, 29, 21, 25, 77, 2d, 25, 29, 73, 31, 77, 2d, 25, 29, d3, 03, 31, d7, 03, 2d, db, 03, 29, 21, 25, 35, 3d, 35, 93, 01, 3d, 85, 01, 35, 9b, 01, af, 01, 85, 01, 3d, 41, 35, a7, 01, ab, 01, 85, 01, af, 01, 45, 3d, 41, c3, 01, 49, 41, 45, bf, 01, 4d, c3, 01, 49, 41, 45, bb, 03, 35, bf, 03, 4d, c3, 03, 49, c7, 03, 45, cb, 03, 41, cf, 03, 3d, d3, 03, 31, d7, 03, 2d, db, 03, 29, 21, 25, f3, 04, 65, f7, 04, 61, fb, 04, 5d, 55, 59, bb, 03, 35, bf, 03, 4d, c3, 03, 49, c7, 03, 45, cb, 03, 41, cf, 03, 3d, d3, 03, 31, d7, 03, 2d, db, 03, 29, 21, 25, bb, 03, eb, 03, bf, 03, 4d, c3, 03, 49, c7, 03, 45, cb, 03, 41, cf, 03, 3d, d3, 03, 31, d7, 03, 2d, db, 03, 29, 21, 25, 35, 55, bb, 03, fb, 02, bf, 03, 4d, c3, 03, 49, c7, 03, 45, cb, 03, 41, cf, 03, 3d, d3, 03, 31, d7, 03, 2d, db, 03, 29, 21, 25, eb, 03, 81, 01, 35, 55, bb, 03, ab, 03, bf, 03, 4d, c3, 03, 49, c7, 03, 45, cb, 03, 41, cf, 03, 3d, d3, 03, 31, d7, 03, 2d, db, 03, 29, 21, 25, e7, 03, 81, 01, eb, 03, 59, 35, 55, bb, 03, df, 03, bf, 03, 4d, c3, 03, 49, c7, 03, 45, cb, 03, 41, cf, 03, 3d, d3, 03, 31, d7, 03, 2d, db, 03, 29, 21, 25, e3, 03, 81, 01, e7, 03, 5d, eb, 03, 59, 35, 55, ff, 03, 61, 59, 5d, fb, 03, 65, ff, 03, 61, 59, 5d, 87, 04, 79, 83, 05, 75, 87, 05, 71, 69, 6d, f3, 04, 65, f7, 04, 61, fb, 04, 5d, 55, 59, ef, 04, 69, f3, 04, 65, f7, 04, 61, fb, 04, 5d, 55, 59, ef, 04, cb, 04, f3, 04, 65, f7, 04, 61, fb, 04, 5d, 55, 59, 69, 7d, ef, 04, e3, 04, f3, 04, 65, f7, 04, 61, fb, 04, 5d, 55, 59, 87, 05, 7d, 69, 6d, ef, 04, ff, 04, f3, 04, 65, f7, 04, 61, fb, 04, 5d, 55, 59, 83, 05, 7d, 87, 05, 71, 69, 6d, 9b, 05, 75, 6d, 71, 97, 05, 79, 9b, 05, 75, 6d, 71, a3, 05, c7, 05, a7, 05, 89, 01, ab, 05, 85, 01, af, 05, 81, 01, b3, 05, 7d, b7, 05, 79, bb, 05, 75, bf, 05, 71, c3, 05, 6d, 01, 69, 09, 8d, 01, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 05, 00, 06, 03, 03, 09, 00, 0a, 01, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, 12, 02, 0f, 00, 1c, 8d, 01, 01, 0c, 00, 19, 16, 00, 1d, 00, 2a, 1a, 00, 2e, 00, 3c, 2f, 00, 3d, 02, 0a, 19, 02, 09, 00, 0a, 2b, 01, 09, 01, 12, 36, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 1d, 01, 0d, 02, 06, 00, 02, 05, 00, 06, 03, 02, 08, 00, 15, 21, 00, 16, 02, 06, 3e, 02, 0f, 00, 1c, 42, 01, 0c, 00, 19, 4a, 00, 1d, 00, 2a, 56, 00, 2e, 00, 3c, 73, 00, 3d, 02, 0a, 31, 02, 09, 00, 0a, 6f, 01, 09, 00, 17, 89, 01, 02, 09, 00, 0f, cf, 03, 03, 08, 00, 0c, 35, 01, 0d, 01, 10, 39, 01, 11, 02, 0a, 00, 02, 09, 00, 0a, 35, 02, 0c, 00, 19, 3d, 00, 1a, 02, 0a, 8a, 01, 04, 11, 00, 1e, 8e, 01, 01, 10, 00, 1d, 96, 01, 00, 21, 00, 2e, a2, 01, 00, 32, 00, 40, bf, 01, 00, 41, 02, 0e, 4d, 02, 0d, 00, 0e, bb, 01, 01, 0d, 00, 1b, 85, 01, 02, 0d, 00, 13, 00, 02, 05, 00, 06, fe, 01, 02, 09, 01, 0c, 51, 01, 0d, 02, 06, 00, 02, 05, 00, 06, ef, 04, 02, 09, 00, 0a, fe, 01, 00, 10, 00, 1d, 55, 00, 1e, 02, 06, a6, 02, 02, 0f, 00, 1c, d2, 02, 01, 0c, 00, 19, 82, 03, 00, 1d, 00, 2a, b6, 03, 00, 2e, 00, 3c, fb, 03, 00, 3d, 02, 0a, 65, 02, 09, 00, 0a, f7, 03, 01, 09, 00, 17, 81, 01, 02, 0d, 02, 0f, 83, 04, 05, 09, 00, 0a, ef, 04, 00, 10, 00, 1d, 69, 00, 1e, 02, 06, a2, 04, 02, 0f, 00, 1c, b6, 04, 01, 0c, 00, 19, ce, 04, 00, 1d, 00, 2a, ea, 04, 00, 2e, 00, 3c, 97, 05, 00, 3d, 02, 0a, 79, 02, 09, 00, 0a, 93, 05, 01, 09, 00, 17, 7d, 02, 09, 00, 0f, 9e, 05, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 148
-- expression 0 operands: lhs = Counter(2), rhs = Expression(10, Add)
-- expression 1 operands: lhs = Expression(11, Add), rhs = Counter(16)
-- expression 2 operands: lhs = Expression(12, Add), rhs = Counter(15)
-- expression 3 operands: lhs = Counter(13), rhs = Counter(14)
+Number of expressions: 178
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(6)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(5)
+- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(4)
+- expression 3 operands: lhs = Counter(2), rhs = Counter(3)
 - expression 4 operands: lhs = Counter(0), rhs = Counter(2)
-- expression 5 operands: lhs = Counter(3), rhs = Counter(13)
-- expression 6 operands: lhs = Expression(7, Sub), rhs = Counter(14)
-- expression 7 operands: lhs = Counter(3), rhs = Counter(13)
-- expression 8 operands: lhs = Expression(12, Add), rhs = Counter(15)
-- expression 9 operands: lhs = Counter(13), rhs = Counter(14)
-- expression 10 operands: lhs = Expression(11, Add), rhs = Counter(16)
-- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(15)
-- expression 12 operands: lhs = Counter(13), rhs = Counter(14)
-- expression 13 operands: lhs = Expression(147, Sub), rhs = Counter(3)
-- expression 14 operands: lhs = Counter(0), rhs = Counter(2)
-- expression 15 operands: lhs = Expression(0, Add), rhs = Counter(18)
-- expression 16 operands: lhs = Expression(24, Sub), rhs = Counter(12)
-- expression 17 operands: lhs = Expression(0, Add), rhs = Counter(18)
-- expression 18 operands: lhs = Expression(23, Sub), rhs = Counter(19)
-- expression 19 operands: lhs = Expression(24, Sub), rhs = Counter(12)
-- expression 20 operands: lhs = Expression(0, Add), rhs = Counter(18)
-- expression 21 operands: lhs = Expression(22, Sub), rhs = Counter(20)
-- expression 22 operands: lhs = Expression(23, Sub), rhs = Counter(19)
-- expression 23 operands: lhs = Expression(24, Sub), rhs = Counter(12)
-- expression 24 operands: lhs = Expression(0, Add), rhs = Counter(18)
-- expression 25 operands: lhs = Expression(33, Add), rhs = Counter(21)
-- expression 26 operands: lhs = Counter(19), rhs = Counter(20)
-- expression 27 operands: lhs = Expression(32, Add), rhs = Counter(22)
-- expression 28 operands: lhs = Expression(33, Add), rhs = Counter(21)
-- expression 29 operands: lhs = Counter(19), rhs = Counter(20)
-- expression 30 operands: lhs = Counter(18), rhs = Expression(31, Add)
-- expression 31 operands: lhs = Expression(32, Add), rhs = Counter(22)
-- expression 32 operands: lhs = Expression(33, Add), rhs = Counter(21)
-- expression 33 operands: lhs = Counter(19), rhs = Counter(20)
-- expression 34 operands: lhs = Counter(23), rhs = Counter(25)
-- expression 35 operands: lhs = Expression(43, Sub), rhs = Counter(11)
-- expression 36 operands: lhs = Counter(23), rhs = Counter(25)
-- expression 37 operands: lhs = Expression(42, Sub), rhs = Counter(26)
-- expression 38 operands: lhs = Expression(43, Sub), rhs = Counter(11)
-- expression 39 operands: lhs = Counter(23), rhs = Counter(25)
-- expression 40 operands: lhs = Expression(41, Sub), rhs = Counter(27)
-- expression 41 operands: lhs = Expression(42, Sub), rhs = Counter(26)
-- expression 42 operands: lhs = Expression(43, Sub), rhs = Counter(11)
-- expression 43 operands: lhs = Counter(23), rhs = Counter(25)
-- expression 44 operands: lhs = Expression(92, Add), rhs = Counter(28)
-- expression 45 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 46 operands: lhs = Expression(91, Add), rhs = Counter(29)
-- expression 47 operands: lhs = Expression(92, Add), rhs = Counter(28)
-- expression 48 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 49 operands: lhs = Expression(89, Add), rhs = Zero
-- expression 50 operands: lhs = Counter(25), rhs = Expression(90, Add)
-- expression 51 operands: lhs = Expression(91, Add), rhs = Counter(29)
-- expression 52 operands: lhs = Expression(92, Add), rhs = Counter(28)
-- expression 53 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 54 operands: lhs = Counter(31), rhs = Expression(129, Add)
-- expression 55 operands: lhs = Expression(130, Add), rhs = Counter(35)
-- expression 56 operands: lhs = Expression(131, Add), rhs = Counter(34)
-- expression 57 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 58 operands: lhs = Expression(89, Add), rhs = Zero
-- expression 59 operands: lhs = Counter(25), rhs = Expression(90, Add)
-- expression 60 operands: lhs = Expression(91, Add), rhs = Counter(29)
-- expression 61 operands: lhs = Expression(92, Add), rhs = Counter(28)
-- expression 62 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 63 operands: lhs = Expression(88, Add), rhs = Counter(31)
-- expression 64 operands: lhs = Expression(89, Add), rhs = Zero
-- expression 65 operands: lhs = Counter(25), rhs = Expression(90, Add)
-- expression 66 operands: lhs = Expression(91, Add), rhs = Counter(29)
-- expression 67 operands: lhs = Expression(92, Add), rhs = Counter(28)
-- expression 68 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 69 operands: lhs = Expression(87, Sub), rhs = Counter(10)
-- expression 70 operands: lhs = Expression(88, Add), rhs = Counter(31)
-- expression 71 operands: lhs = Expression(89, Add), rhs = Zero
-- expression 72 operands: lhs = Counter(25), rhs = Expression(90, Add)
-- expression 73 operands: lhs = Expression(91, Add), rhs = Counter(29)
-- expression 74 operands: lhs = Expression(92, Add), rhs = Counter(28)
-- expression 75 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 76 operands: lhs = Expression(86, Sub), rhs = Counter(32)
-- expression 77 operands: lhs = Expression(87, Sub), rhs = Counter(10)
-- expression 78 operands: lhs = Expression(88, Add), rhs = Counter(31)
-- expression 79 operands: lhs = Expression(89, Add), rhs = Zero
-- expression 80 operands: lhs = Counter(25), rhs = Expression(90, Add)
-- expression 81 operands: lhs = Expression(91, Add), rhs = Counter(29)
-- expression 82 operands: lhs = Expression(92, Add), rhs = Counter(28)
-- expression 83 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 84 operands: lhs = Expression(85, Sub), rhs = Counter(33)
-- expression 85 operands: lhs = Expression(86, Sub), rhs = Counter(32)
-- expression 86 operands: lhs = Expression(87, Sub), rhs = Counter(10)
-- expression 87 operands: lhs = Expression(88, Add), rhs = Counter(31)
-- expression 88 operands: lhs = Expression(89, Add), rhs = Zero
-- expression 89 operands: lhs = Counter(25), rhs = Expression(90, Add)
-- expression 90 operands: lhs = Expression(91, Add), rhs = Counter(29)
-- expression 91 operands: lhs = Expression(92, Add), rhs = Counter(28)
-- expression 92 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 93 operands: lhs = Expression(131, Add), rhs = Counter(34)
-- expression 94 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 95 operands: lhs = Expression(130, Add), rhs = Counter(35)
-- expression 96 operands: lhs = Expression(131, Add), rhs = Counter(34)
-- expression 97 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 98 operands: lhs = Counter(4), rhs = Expression(139, Add)
-- expression 99 operands: lhs = Expression(140, Add), rhs = Counter(8)
-- expression 100 operands: lhs = Expression(141, Add), rhs = Counter(7)
-- expression 101 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 102 operands: lhs = Counter(31), rhs = Expression(129, Add)
-- expression 103 operands: lhs = Expression(130, Add), rhs = Counter(35)
-- expression 104 operands: lhs = Expression(131, Add), rhs = Counter(34)
-- expression 105 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 106 operands: lhs = Expression(128, Add), rhs = Counter(4)
-- expression 107 operands: lhs = Counter(31), rhs = Expression(129, Add)
-- expression 108 operands: lhs = Expression(130, Add), rhs = Counter(35)
-- expression 109 operands: lhs = Expression(131, Add), rhs = Counter(34)
-- expression 110 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 111 operands: lhs = Expression(127, Sub), rhs = Counter(9)
-- expression 112 operands: lhs = Expression(128, Add), rhs = Counter(4)
-- expression 113 operands: lhs = Counter(31), rhs = Expression(129, Add)
-- expression 114 operands: lhs = Expression(130, Add), rhs = Counter(35)
-- expression 115 operands: lhs = Expression(131, Add), rhs = Counter(34)
-- expression 116 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 117 operands: lhs = Expression(126, Sub), rhs = Counter(5)
-- expression 118 operands: lhs = Expression(127, Sub), rhs = Counter(9)
-- expression 119 operands: lhs = Expression(128, Add), rhs = Counter(4)
-- expression 120 operands: lhs = Counter(31), rhs = Expression(129, Add)
-- expression 121 operands: lhs = Expression(130, Add), rhs = Counter(35)
-- expression 122 operands: lhs = Expression(131, Add), rhs = Counter(34)
-- expression 123 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 124 operands: lhs = Expression(125, Sub), rhs = Counter(6)
-- expression 125 operands: lhs = Expression(126, Sub), rhs = Counter(5)
-- expression 126 operands: lhs = Expression(127, Sub), rhs = Counter(9)
-- expression 127 operands: lhs = Expression(128, Add), rhs = Counter(4)
-- expression 128 operands: lhs = Counter(31), rhs = Expression(129, Add)
-- expression 129 operands: lhs = Expression(130, Add), rhs = Counter(35)
-- expression 130 operands: lhs = Expression(131, Add), rhs = Counter(34)
-- expression 131 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 132 operands: lhs = Expression(141, Add), rhs = Counter(7)
-- expression 133 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 134 operands: lhs = Expression(140, Add), rhs = Counter(8)
-- expression 135 operands: lhs = Expression(141, Add), rhs = Counter(7)
-- expression 136 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 137 operands: lhs = Expression(138, Add), rhs = Expression(142, Add)
-- expression 138 operands: lhs = Counter(4), rhs = Expression(139, Add)
-- expression 139 operands: lhs = Expression(140, Add), rhs = Counter(8)
-- expression 140 operands: lhs = Expression(141, Add), rhs = Counter(7)
-- expression 141 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 142 operands: lhs = Expression(143, Add), rhs = Expression(146, Sub)
-- expression 143 operands: lhs = Expression(144, Add), rhs = Counter(12)
-- expression 144 operands: lhs = Expression(145, Add), rhs = Counter(11)
-- expression 145 operands: lhs = Counter(9), rhs = Counter(10)
-- expression 146 operands: lhs = Expression(147, Sub), rhs = Counter(3)
-- expression 147 operands: lhs = Counter(0), rhs = Counter(2)
+- expression 5 operands: lhs = Counter(35), rhs = Counter(3)
+- expression 6 operands: lhs = Counter(35), rhs = Expression(12, Add)
+- expression 7 operands: lhs = Counter(3), rhs = Counter(4)
+- expression 8 operands: lhs = Expression(12, Add), rhs = Counter(5)
+- expression 9 operands: lhs = Counter(3), rhs = Counter(4)
+- expression 10 operands: lhs = Expression(11, Add), rhs = Counter(6)
+- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(5)
+- expression 12 operands: lhs = Counter(3), rhs = Counter(4)
+- expression 13 operands: lhs = Counter(0), rhs = Expression(177, Add)
+- expression 14 operands: lhs = Counter(2), rhs = Counter(35)
+- expression 15 operands: lhs = Expression(0, Add), rhs = Counter(8)
+- expression 16 operands: lhs = Expression(0, Add), rhs = Expression(17, Add)
+- expression 17 operands: lhs = Counter(8), rhs = Counter(34)
+- expression 18 operands: lhs = Expression(0, Add), rhs = Expression(19, Add)
+- expression 19 operands: lhs = Expression(118, Add), rhs = Counter(34)
+- expression 20 operands: lhs = Counter(8), rhs = Counter(9)
+- expression 21 operands: lhs = Expression(0, Add), rhs = Expression(22, Add)
+- expression 22 operands: lhs = Expression(117, Add), rhs = Counter(34)
+- expression 23 operands: lhs = Expression(118, Add), rhs = Counter(10)
+- expression 24 operands: lhs = Counter(8), rhs = Counter(9)
+- expression 25 operands: lhs = Expression(29, Add), rhs = Counter(11)
+- expression 26 operands: lhs = Counter(9), rhs = Counter(10)
+- expression 27 operands: lhs = Expression(28, Add), rhs = Counter(12)
+- expression 28 operands: lhs = Expression(29, Add), rhs = Counter(11)
+- expression 29 operands: lhs = Counter(9), rhs = Counter(10)
+- expression 30 operands: lhs = Expression(116, Add), rhs = Counter(12)
+- expression 31 operands: lhs = Expression(117, Add), rhs = Counter(11)
+- expression 32 operands: lhs = Expression(118, Add), rhs = Counter(10)
+- expression 33 operands: lhs = Counter(8), rhs = Counter(9)
+- expression 34 operands: lhs = Counter(13), rhs = Counter(15)
+- expression 35 operands: lhs = Counter(13), rhs = Expression(36, Add)
+- expression 36 operands: lhs = Counter(15), rhs = Counter(33)
+- expression 37 operands: lhs = Counter(13), rhs = Expression(38, Add)
+- expression 38 operands: lhs = Expression(43, Add), rhs = Counter(33)
+- expression 39 operands: lhs = Counter(15), rhs = Counter(16)
+- expression 40 operands: lhs = Counter(13), rhs = Expression(41, Add)
+- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(33)
+- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(17)
+- expression 43 operands: lhs = Counter(15), rhs = Counter(16)
+- expression 44 operands: lhs = Expression(48, Add), rhs = Counter(18)
+- expression 45 operands: lhs = Counter(16), rhs = Counter(17)
+- expression 46 operands: lhs = Expression(47, Add), rhs = Counter(19)
+- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(18)
+- expression 48 operands: lhs = Counter(16), rhs = Counter(17)
+- expression 49 operands: lhs = Expression(110, Add), rhs = Counter(13)
+- expression 50 operands: lhs = Expression(111, Add), rhs = Counter(19)
+- expression 51 operands: lhs = Expression(112, Add), rhs = Counter(18)
+- expression 52 operands: lhs = Expression(113, Add), rhs = Counter(17)
+- expression 53 operands: lhs = Expression(114, Add), rhs = Counter(16)
+- expression 54 operands: lhs = Expression(115, Add), rhs = Counter(15)
+- expression 55 operands: lhs = Expression(116, Add), rhs = Counter(12)
+- expression 56 operands: lhs = Expression(117, Add), rhs = Counter(11)
+- expression 57 operands: lhs = Expression(118, Add), rhs = Counter(10)
+- expression 58 operands: lhs = Counter(8), rhs = Counter(9)
+- expression 59 operands: lhs = Expression(156, Add), rhs = Counter(25)
+- expression 60 operands: lhs = Expression(157, Add), rhs = Counter(24)
+- expression 61 operands: lhs = Expression(158, Add), rhs = Counter(23)
+- expression 62 operands: lhs = Counter(21), rhs = Counter(22)
+- expression 63 operands: lhs = Expression(110, Add), rhs = Counter(13)
+- expression 64 operands: lhs = Expression(111, Add), rhs = Counter(19)
+- expression 65 operands: lhs = Expression(112, Add), rhs = Counter(18)
+- expression 66 operands: lhs = Expression(113, Add), rhs = Counter(17)
+- expression 67 operands: lhs = Expression(114, Add), rhs = Counter(16)
+- expression 68 operands: lhs = Expression(115, Add), rhs = Counter(15)
+- expression 69 operands: lhs = Expression(116, Add), rhs = Counter(12)
+- expression 70 operands: lhs = Expression(117, Add), rhs = Counter(11)
+- expression 71 operands: lhs = Expression(118, Add), rhs = Counter(10)
+- expression 72 operands: lhs = Counter(8), rhs = Counter(9)
+- expression 73 operands: lhs = Expression(110, Add), rhs = Expression(122, Add)
+- expression 74 operands: lhs = Expression(111, Add), rhs = Counter(19)
+- expression 75 operands: lhs = Expression(112, Add), rhs = Counter(18)
+- expression 76 operands: lhs = Expression(113, Add), rhs = Counter(17)
+- expression 77 operands: lhs = Expression(114, Add), rhs = Counter(16)
+- expression 78 operands: lhs = Expression(115, Add), rhs = Counter(15)
+- expression 79 operands: lhs = Expression(116, Add), rhs = Counter(12)
+- expression 80 operands: lhs = Expression(117, Add), rhs = Counter(11)
+- expression 81 operands: lhs = Expression(118, Add), rhs = Counter(10)
+- expression 82 operands: lhs = Counter(8), rhs = Counter(9)
+- expression 83 operands: lhs = Counter(13), rhs = Counter(21)
+- expression 84 operands: lhs = Expression(110, Add), rhs = Expression(94, Add)
+- expression 85 operands: lhs = Expression(111, Add), rhs = Counter(19)
+- expression 86 operands: lhs = Expression(112, Add), rhs = Counter(18)
+- expression 87 operands: lhs = Expression(113, Add), rhs = Counter(17)
+- expression 88 operands: lhs = Expression(114, Add), rhs = Counter(16)
+- expression 89 operands: lhs = Expression(115, Add), rhs = Counter(15)
+- expression 90 operands: lhs = Expression(116, Add), rhs = Counter(12)
+- expression 91 operands: lhs = Expression(117, Add), rhs = Counter(11)
+- expression 92 operands: lhs = Expression(118, Add), rhs = Counter(10)
+- expression 93 operands: lhs = Counter(8), rhs = Counter(9)
+- expression 94 operands: lhs = Expression(122, Add), rhs = Counter(32)
+- expression 95 operands: lhs = Counter(13), rhs = Counter(21)
+- expression 96 operands: lhs = Expression(110, Add), rhs = Expression(106, Add)
+- expression 97 operands: lhs = Expression(111, Add), rhs = Counter(19)
+- expression 98 operands: lhs = Expression(112, Add), rhs = Counter(18)
+- expression 99 operands: lhs = Expression(113, Add), rhs = Counter(17)
+- expression 100 operands: lhs = Expression(114, Add), rhs = Counter(16)
+- expression 101 operands: lhs = Expression(115, Add), rhs = Counter(15)
+- expression 102 operands: lhs = Expression(116, Add), rhs = Counter(12)
+- expression 103 operands: lhs = Expression(117, Add), rhs = Counter(11)
+- expression 104 operands: lhs = Expression(118, Add), rhs = Counter(10)
+- expression 105 operands: lhs = Counter(8), rhs = Counter(9)
+- expression 106 operands: lhs = Expression(121, Add), rhs = Counter(32)
+- expression 107 operands: lhs = Expression(122, Add), rhs = Counter(22)
+- expression 108 operands: lhs = Counter(13), rhs = Counter(21)
+- expression 109 operands: lhs = Expression(110, Add), rhs = Expression(119, Add)
+- expression 110 operands: lhs = Expression(111, Add), rhs = Counter(19)
+- expression 111 operands: lhs = Expression(112, Add), rhs = Counter(18)
+- expression 112 operands: lhs = Expression(113, Add), rhs = Counter(17)
+- expression 113 operands: lhs = Expression(114, Add), rhs = Counter(16)
+- expression 114 operands: lhs = Expression(115, Add), rhs = Counter(15)
+- expression 115 operands: lhs = Expression(116, Add), rhs = Counter(12)
+- expression 116 operands: lhs = Expression(117, Add), rhs = Counter(11)
+- expression 117 operands: lhs = Expression(118, Add), rhs = Counter(10)
+- expression 118 operands: lhs = Counter(8), rhs = Counter(9)
+- expression 119 operands: lhs = Expression(120, Add), rhs = Counter(32)
+- expression 120 operands: lhs = Expression(121, Add), rhs = Counter(23)
+- expression 121 operands: lhs = Expression(122, Add), rhs = Counter(22)
+- expression 122 operands: lhs = Counter(13), rhs = Counter(21)
+- expression 123 operands: lhs = Expression(127, Add), rhs = Counter(24)
+- expression 124 operands: lhs = Counter(22), rhs = Counter(23)
+- expression 125 operands: lhs = Expression(126, Add), rhs = Counter(25)
+- expression 126 operands: lhs = Expression(127, Add), rhs = Counter(24)
+- expression 127 operands: lhs = Counter(22), rhs = Counter(23)
+- expression 128 operands: lhs = Expression(129, Add), rhs = Counter(30)
+- expression 129 operands: lhs = Expression(160, Add), rhs = Counter(29)
+- expression 130 operands: lhs = Expression(161, Add), rhs = Counter(28)
+- expression 131 operands: lhs = Counter(26), rhs = Counter(27)
+- expression 132 operands: lhs = Expression(156, Add), rhs = Counter(25)
+- expression 133 operands: lhs = Expression(157, Add), rhs = Counter(24)
+- expression 134 operands: lhs = Expression(158, Add), rhs = Counter(23)
+- expression 135 operands: lhs = Counter(21), rhs = Counter(22)
+- expression 136 operands: lhs = Expression(155, Add), rhs = Counter(26)
+- expression 137 operands: lhs = Expression(156, Add), rhs = Counter(25)
+- expression 138 operands: lhs = Expression(157, Add), rhs = Counter(24)
+- expression 139 operands: lhs = Expression(158, Add), rhs = Counter(23)
+- expression 140 operands: lhs = Counter(21), rhs = Counter(22)
+- expression 141 operands: lhs = Expression(155, Add), rhs = Expression(146, Add)
+- expression 142 operands: lhs = Expression(156, Add), rhs = Counter(25)
+- expression 143 operands: lhs = Expression(157, Add), rhs = Counter(24)
+- expression 144 operands: lhs = Expression(158, Add), rhs = Counter(23)
+- expression 145 operands: lhs = Counter(21), rhs = Counter(22)
+- expression 146 operands: lhs = Counter(26), rhs = Counter(31)
+- expression 147 operands: lhs = Expression(155, Add), rhs = Expression(152, Add)
+- expression 148 operands: lhs = Expression(156, Add), rhs = Counter(25)
+- expression 149 operands: lhs = Expression(157, Add), rhs = Counter(24)
+- expression 150 operands: lhs = Expression(158, Add), rhs = Counter(23)
+- expression 151 operands: lhs = Counter(21), rhs = Counter(22)
+- expression 152 operands: lhs = Expression(161, Add), rhs = Counter(31)
+- expression 153 operands: lhs = Counter(26), rhs = Counter(27)
+- expression 154 operands: lhs = Expression(155, Add), rhs = Expression(159, Add)
+- expression 155 operands: lhs = Expression(156, Add), rhs = Counter(25)
+- expression 156 operands: lhs = Expression(157, Add), rhs = Counter(24)
+- expression 157 operands: lhs = Expression(158, Add), rhs = Counter(23)
+- expression 158 operands: lhs = Counter(21), rhs = Counter(22)
+- expression 159 operands: lhs = Expression(160, Add), rhs = Counter(31)
+- expression 160 operands: lhs = Expression(161, Add), rhs = Counter(28)
+- expression 161 operands: lhs = Counter(26), rhs = Counter(27)
+- expression 162 operands: lhs = Expression(166, Add), rhs = Counter(29)
+- expression 163 operands: lhs = Counter(27), rhs = Counter(28)
+- expression 164 operands: lhs = Expression(165, Add), rhs = Counter(30)
+- expression 165 operands: lhs = Expression(166, Add), rhs = Counter(29)
+- expression 166 operands: lhs = Counter(27), rhs = Counter(28)
+- expression 167 operands: lhs = Expression(168, Add), rhs = Expression(177, Add)
+- expression 168 operands: lhs = Expression(169, Add), rhs = Counter(34)
+- expression 169 operands: lhs = Expression(170, Add), rhs = Counter(33)
+- expression 170 operands: lhs = Expression(171, Add), rhs = Counter(32)
+- expression 171 operands: lhs = Expression(172, Add), rhs = Counter(31)
+- expression 172 operands: lhs = Expression(173, Add), rhs = Counter(30)
+- expression 173 operands: lhs = Expression(174, Add), rhs = Counter(29)
+- expression 174 operands: lhs = Expression(175, Add), rhs = Counter(28)
+- expression 175 operands: lhs = Expression(176, Add), rhs = Counter(27)
+- expression 176 operands: lhs = Counter(0), rhs = Counter(26)
+- expression 177 operands: lhs = Counter(2), rhs = Counter(35)
 Number of file 0 mappings: 68
 - Code(Counter(0)) at (prev + 3, 1) to (start + 2, 12)
 - Code(Counter(1)) at (prev + 2, 13) to (start + 2, 6)
 - Code(Zero) at (prev + 2, 5) to (start + 0, 6)
 - Code(Expression(0, Add)) at (prev + 3, 9) to (start + 0, 10)
-    = (c2 + (((c13 + c14) + c15) + c16))
+    = ((((c2 + c3) + c4) + c5) + c6)
 - Code(Counter(0)) at (prev + 0, 16) to (start + 0, 29)
 - Code(Counter(2)) at (prev + 1, 9) to (start + 1, 10)
-- Code(Expression(147, Sub)) at (prev + 2, 15) to (start + 0, 28)
+- Code(Expression(4, Sub)) at (prev + 2, 15) to (start + 0, 28)
     = (c0 - c2)
-- Code(Counter(3)) at (prev + 1, 12) to (start + 0, 25)
-- Code(Expression(7, Sub)) at (prev + 0, 29) to (start + 0, 42)
-    = (c3 - c13)
+- Code(Counter(35)) at (prev + 1, 12) to (start + 0, 25)
+- Code(Expression(5, Sub)) at (prev + 0, 29) to (start + 0, 42)
+    = (c35 - c3)
 - Code(Expression(6, Sub)) at (prev + 0, 46) to (start + 0, 60)
-    = ((c3 - c13) - c14)
+    = (c35 - (c3 + c4))
 - Code(Expression(11, Add)) at (prev + 0, 61) to (start + 2, 10)
-    = ((c13 + c14) + c15)
-- Code(Counter(16)) at (prev + 2, 9) to (start + 0, 10)
+    = ((c3 + c4) + c5)
+- Code(Counter(6)) at (prev + 2, 9) to (start + 0, 10)
 - Code(Expression(10, Add)) at (prev + 1, 9) to (start + 1, 18)
-    = (((c13 + c14) + c15) + c16)
-- Code(Expression(146, Sub)) at (prev + 3, 9) to (start + 0, 15)
-    = ((c0 - c2) - c3)
+    = (((c3 + c4) + c5) + c6)
+- Code(Expression(13, Sub)) at (prev + 3, 9) to (start + 0, 15)
+    = (c0 - (c2 + c35))
 - Code(Expression(0, Add)) at (prev + 3, 9) to (start + 1, 12)
-    = (c2 + (((c13 + c14) + c15) + c16))
-- Code(Counter(17)) at (prev + 1, 13) to (start + 2, 6)
+    = ((((c2 + c3) + c4) + c5) + c6)
+- Code(Counter(7)) at (prev + 1, 13) to (start + 2, 6)
 - Code(Zero) at (prev + 2, 5) to (start + 0, 6)
 - Code(Expression(0, Add)) at (prev + 2, 8) to (start + 0, 21)
-    = (c2 + (((c13 + c14) + c15) + c16))
-- Code(Counter(18)) at (prev + 0, 22) to (start + 2, 6)
-- Code(Expression(24, Sub)) at (prev + 2, 15) to (start + 0, 28)
-    = ((c2 + (((c13 + c14) + c15) + c16)) - c18)
-- Code(Expression(23, Sub)) at (prev + 1, 12) to (start + 0, 25)
-    = (((c2 + (((c13 + c14) + c15) + c16)) - c18) - c12)
-- Code(Expression(22, Sub)) at (prev + 0, 29) to (start + 0, 42)
-    = ((((c2 + (((c13 + c14) + c15) + c16)) - c18) - c12) - c19)
+    = ((((c2 + c3) + c4) + c5) + c6)
+- Code(Counter(8)) at (prev + 0, 22) to (start + 2, 6)
+- Code(Expression(15, Sub)) at (prev + 2, 15) to (start + 0, 28)
+    = (((((c2 + c3) + c4) + c5) + c6) - c8)
+- Code(Expression(16, Sub)) at (prev + 1, 12) to (start + 0, 25)
+    = (((((c2 + c3) + c4) + c5) + c6) - (c8 + c34))
+- Code(Expression(18, Sub)) at (prev + 0, 29) to (start + 0, 42)
+    = (((((c2 + c3) + c4) + c5) + c6) - ((c8 + c9) + c34))
 - Code(Expression(21, Sub)) at (prev + 0, 46) to (start + 0, 60)
-    = (((((c2 + (((c13 + c14) + c15) + c16)) - c18) - c12) - c19) - c20)
-- Code(Expression(32, Add)) at (prev + 0, 61) to (start + 2, 10)
-    = ((c19 + c20) + c21)
-- Code(Counter(22)) at (prev + 2, 9) to (start + 0, 10)
-- Code(Expression(31, Add)) at (prev + 1, 9) to (start + 0, 23)
-    = (((c19 + c20) + c21) + c22)
-- Code(Counter(12)) at (prev + 2, 9) to (start + 0, 15)
-- Code(Expression(30, Add)) at (prev + 3, 8) to (start + 0, 12)
-    = (c18 + (((c19 + c20) + c21) + c22))
-- Code(Counter(23)) at (prev + 1, 13) to (start + 1, 16)
-- Code(Counter(24)) at (prev + 1, 17) to (start + 2, 10)
+    = (((((c2 + c3) + c4) + c5) + c6) - (((c8 + c9) + c10) + c34))
+- Code(Expression(28, Add)) at (prev + 0, 61) to (start + 2, 10)
+    = ((c9 + c10) + c11)
+- Code(Counter(12)) at (prev + 2, 9) to (start + 0, 10)
+- Code(Expression(27, Add)) at (prev + 1, 9) to (start + 0, 23)
+    = (((c9 + c10) + c11) + c12)
+- Code(Counter(34)) at (prev + 2, 9) to (start + 0, 15)
+- Code(Expression(115, Add)) at (prev + 3, 8) to (start + 0, 12)
+    = ((((c8 + c9) + c10) + c11) + c12)
+- Code(Counter(13)) at (prev + 1, 13) to (start + 1, 16)
+- Code(Counter(14)) at (prev + 1, 17) to (start + 2, 10)
 - Code(Zero) at (prev + 2, 9) to (start + 0, 10)
-- Code(Counter(23)) at (prev + 2, 12) to (start + 0, 25)
-- Code(Counter(25)) at (prev + 0, 26) to (start + 2, 10)
-- Code(Expression(43, Sub)) at (prev + 4, 17) to (start + 0, 30)
-    = (c23 - c25)
-- Code(Expression(42, Sub)) at (prev + 1, 16) to (start + 0, 29)
-    = ((c23 - c25) - c11)
-- Code(Expression(41, Sub)) at (prev + 0, 33) to (start + 0, 46)
-    = (((c23 - c25) - c11) - c26)
+- Code(Counter(13)) at (prev + 2, 12) to (start + 0, 25)
+- Code(Counter(15)) at (prev + 0, 26) to (start + 2, 10)
+- Code(Expression(34, Sub)) at (prev + 4, 17) to (start + 0, 30)
+    = (c13 - c15)
+- Code(Expression(35, Sub)) at (prev + 1, 16) to (start + 0, 29)
+    = (c13 - (c15 + c33))
+- Code(Expression(37, Sub)) at (prev + 0, 33) to (start + 0, 46)
+    = (c13 - ((c15 + c16) + c33))
 - Code(Expression(40, Sub)) at (prev + 0, 50) to (start + 0, 64)
-    = ((((c23 - c25) - c11) - c26) - c27)
-- Code(Expression(91, Add)) at (prev + 0, 65) to (start + 2, 14)
-    = ((c26 + c27) + c28)
-- Code(Counter(29)) at (prev + 2, 13) to (start + 0, 14)
-- Code(Expression(90, Add)) at (prev + 1, 13) to (start + 0, 27)
-    = (((c26 + c27) + c28) + c29)
-- Code(Counter(11)) at (prev + 2, 13) to (start + 0, 19)
+    = (c13 - (((c15 + c16) + c17) + c33))
+- Code(Expression(47, Add)) at (prev + 0, 65) to (start + 2, 14)
+    = ((c16 + c17) + c18)
+- Code(Counter(19)) at (prev + 2, 13) to (start + 0, 14)
+- Code(Expression(46, Add)) at (prev + 1, 13) to (start + 0, 27)
+    = (((c16 + c17) + c18) + c19)
+- Code(Counter(33)) at (prev + 2, 13) to (start + 0, 19)
 - Code(Zero) at (prev + 2, 5) to (start + 0, 6)
-- Code(Expression(88, Add)) at (prev + 2, 9) to (start + 1, 12)
-    = ((c25 + (((c26 + c27) + c28) + c29)) + Zero)
-- Code(Counter(30)) at (prev + 1, 13) to (start + 2, 6)
+- Code(Expression(63, Sub)) at (prev + 2, 9) to (start + 1, 12)
+    = ((((((((((c8 + c9) + c10) + c11) + c12) + c15) + c16) + c17) + c18) + c19) - c13)
+- Code(Counter(20)) at (prev + 1, 13) to (start + 2, 6)
 - Code(Zero) at (prev + 2, 5) to (start + 0, 6)
-- Code(Expression(128, Add)) at (prev + 2, 9) to (start + 0, 10)
-    = (c31 + (((c32 + c33) + c34) + c35))
-- Code(Expression(88, Add)) at (prev + 0, 16) to (start + 0, 29)
-    = ((c25 + (((c26 + c27) + c28) + c29)) + Zero)
-- Code(Counter(31)) at (prev + 0, 30) to (start + 2, 6)
-- Code(Expression(87, Sub)) at (prev + 2, 15) to (start + 0, 28)
-    = (((c25 + (((c26 + c27) + c28) + c29)) + Zero) - c31)
-- Code(Expression(86, Sub)) at (prev + 1, 12) to (start + 0, 25)
-    = ((((c25 + (((c26 + c27) + c28) + c29)) + Zero) - c31) - c10)
-- Code(Expression(85, Sub)) at (prev + 0, 29) to (start + 0, 42)
-    = (((((c25 + (((c26 + c27) + c28) + c29)) + Zero) - c31) - c10) - c32)
-- Code(Expression(84, Sub)) at (prev + 0, 46) to (start + 0, 60)
-    = ((((((c25 + (((c26 + c27) + c28) + c29)) + Zero) - c31) - c10) - c32) - c33)
-- Code(Expression(130, Add)) at (prev + 0, 61) to (start + 2, 10)
-    = ((c32 + c33) + c34)
-- Code(Counter(35)) at (prev + 2, 9) to (start + 0, 10)
-- Code(Expression(129, Add)) at (prev + 1, 9) to (start + 0, 23)
-    = (((c32 + c33) + c34) + c35)
-- Code(Counter(10)) at (prev + 2, 13) to (start + 2, 15)
-- Code(Expression(138, Add)) at (prev + 5, 9) to (start + 0, 10)
-    = (c4 + (((c5 + c6) + c7) + c8))
-- Code(Expression(128, Add)) at (prev + 0, 16) to (start + 0, 29)
-    = (c31 + (((c32 + c33) + c34) + c35))
-- Code(Counter(4)) at (prev + 0, 30) to (start + 2, 6)
-- Code(Expression(127, Sub)) at (prev + 2, 15) to (start + 0, 28)
-    = ((c31 + (((c32 + c33) + c34) + c35)) - c4)
-- Code(Expression(126, Sub)) at (prev + 1, 12) to (start + 0, 25)
-    = (((c31 + (((c32 + c33) + c34) + c35)) - c4) - c9)
-- Code(Expression(125, Sub)) at (prev + 0, 29) to (start + 0, 42)
-    = ((((c31 + (((c32 + c33) + c34) + c35)) - c4) - c9) - c5)
-- Code(Expression(124, Sub)) at (prev + 0, 46) to (start + 0, 60)
-    = (((((c31 + (((c32 + c33) + c34) + c35)) - c4) - c9) - c5) - c6)
-- Code(Expression(140, Add)) at (prev + 0, 61) to (start + 2, 10)
-    = ((c5 + c6) + c7)
-- Code(Counter(8)) at (prev + 2, 9) to (start + 0, 10)
-- Code(Expression(139, Add)) at (prev + 1, 9) to (start + 0, 23)
-    = (((c5 + c6) + c7) + c8)
-- Code(Counter(9)) at (prev + 2, 9) to (start + 0, 15)
-- Code(Expression(137, Add)) at (prev + 2, 1) to (start + 0, 2)
-    = ((c4 + (((c5 + c6) + c7) + c8)) + ((((c9 + c10) + c11) + c12) + ((c0 - c2) - c3)))
+- Code(Expression(155, Add)) at (prev + 2, 9) to (start + 0, 10)
+    = ((((c21 + c22) + c23) + c24) + c25)
+- Code(Expression(63, Sub)) at (prev + 0, 16) to (start + 0, 29)
+    = ((((((((((c8 + c9) + c10) + c11) + c12) + c15) + c16) + c17) + c18) + c19) - c13)
+- Code(Counter(21)) at (prev + 0, 30) to (start + 2, 6)
+- Code(Expression(73, Sub)) at (prev + 2, 15) to (start + 0, 28)
+    = ((((((((((c8 + c9) + c10) + c11) + c12) + c15) + c16) + c17) + c18) + c19) - (c13 + c21))
+- Code(Expression(84, Sub)) at (prev + 1, 12) to (start + 0, 25)
+    = ((((((((((c8 + c9) + c10) + c11) + c12) + c15) + c16) + c17) + c18) + c19) - ((c13 + c21) + c32))
+- Code(Expression(96, Sub)) at (prev + 0, 29) to (start + 0, 42)
+    = ((((((((((c8 + c9) + c10) + c11) + c12) + c15) + c16) + c17) + c18) + c19) - (((c13 + c21) + c22) + c32))
+- Code(Expression(109, Sub)) at (prev + 0, 46) to (start + 0, 60)
+    = ((((((((((c8 + c9) + c10) + c11) + c12) + c15) + c16) + c17) + c18) + c19) - ((((c13 + c21) + c22) + c23) + c32))
+- Code(Expression(126, Add)) at (prev + 0, 61) to (start + 2, 10)
+    = ((c22 + c23) + c24)
+- Code(Counter(25)) at (prev + 2, 9) to (start + 0, 10)
+- Code(Expression(125, Add)) at (prev + 1, 9) to (start + 0, 23)
+    = (((c22 + c23) + c24) + c25)
+- Code(Counter(32)) at (prev + 2, 13) to (start + 2, 15)
+- Code(Expression(128, Add)) at (prev + 5, 9) to (start + 0, 10)
+    = ((((c26 + c27) + c28) + c29) + c30)
+- Code(Expression(155, Add)) at (prev + 0, 16) to (start + 0, 29)
+    = ((((c21 + c22) + c23) + c24) + c25)
+- Code(Counter(26)) at (prev + 0, 30) to (start + 2, 6)
+- Code(Expression(136, Sub)) at (prev + 2, 15) to (start + 0, 28)
+    = (((((c21 + c22) + c23) + c24) + c25) - c26)
+- Code(Expression(141, Sub)) at (prev + 1, 12) to (start + 0, 25)
+    = (((((c21 + c22) + c23) + c24) + c25) - (c26 + c31))
+- Code(Expression(147, Sub)) at (prev + 0, 29) to (start + 0, 42)
+    = (((((c21 + c22) + c23) + c24) + c25) - ((c26 + c27) + c31))
+- Code(Expression(154, Sub)) at (prev + 0, 46) to (start + 0, 60)
+    = (((((c21 + c22) + c23) + c24) + c25) - (((c26 + c27) + c28) + c31))
+- Code(Expression(165, Add)) at (prev + 0, 61) to (start + 2, 10)
+    = ((c27 + c28) + c29)
+- Code(Counter(30)) at (prev + 2, 9) to (start + 0, 10)
+- Code(Expression(164, Add)) at (prev + 1, 9) to (start + 0, 23)
+    = (((c27 + c28) + c29) + c30)
+- Code(Counter(31)) at (prev + 2, 9) to (start + 0, 15)
+- Code(Expression(167, Sub)) at (prev + 2, 1) to (start + 0, 2)
+    = ((((((((((c0 + c26) + c27) + c28) + c29) + c30) + c31) + c32) + c33) + c34) - (c2 + c35))
 Highest counter ID seen: c35
 
diff --git a/tests/coverage/continue.cov-map b/tests/coverage/continue.cov-map
index 7781d2d2544..55313d7db49 100644
--- a/tests/coverage/continue.cov-map
+++ b/tests/coverage/continue.cov-map
@@ -1,5 +1,5 @@
 Function name: continue::main
-Raw bytes (210): 0x[01, 01, 1c, 07, 09, 01, 05, 03, 0d, 1f, 15, 0d, 11, 1b, 19, 1f, 15, 0d, 11, 33, 21, 19, 1d, 2f, 25, 33, 21, 19, 1d, 47, 2d, 25, 29, 43, 31, 47, 2d, 25, 29, 31, 5f, 35, 39, 57, 3d, 31, 5f, 35, 39, 35, 39, 3d, 41, 6b, 45, 3d, 41, 49, 45, 1e, 01, 03, 01, 03, 12, 03, 04, 0e, 00, 13, 0a, 01, 0f, 00, 16, 05, 02, 11, 00, 19, 09, 02, 12, 04, 0e, 1b, 06, 0e, 00, 13, 16, 01, 0f, 00, 16, 15, 01, 16, 02, 0e, 11, 04, 11, 00, 19, 15, 03, 09, 00, 0e, 2f, 02, 0e, 00, 13, 2a, 01, 0f, 00, 16, 1d, 01, 15, 02, 0e, 21, 04, 11, 00, 19, 1d, 03, 09, 00, 0e, 43, 02, 0e, 00, 13, 3e, 01, 0c, 00, 13, 29, 01, 0d, 00, 15, 2d, 01, 0a, 01, 0e, 57, 03, 0e, 00, 13, 52, 01, 0f, 00, 16, 39, 01, 16, 02, 0e, 35, 03, 12, 02, 0e, 5f, 04, 09, 00, 0e, 6b, 02, 0e, 00, 13, 66, 01, 0f, 00, 16, 41, 01, 16, 02, 0e, 49, 04, 11, 00, 16, 41, 03, 09, 00, 0e, 6f, 02, 0d, 01, 02]
+Raw bytes (210): 0x[01, 01, 1c, 07, 09, 01, 05, 03, 0d, 1f, 15, 0d, 11, 1b, 19, 1f, 15, 0d, 11, 33, 21, 19, 1d, 2f, 25, 33, 21, 19, 1d, 47, 2d, 25, 29, 43, 31, 47, 2d, 25, 29, 5b, 39, 31, 35, 57, 3d, 5b, 39, 31, 35, 35, 39, 3d, 41, 6b, 45, 3d, 41, 45, 49, 1e, 01, 03, 01, 03, 12, 03, 04, 0e, 00, 13, 0a, 01, 0f, 00, 16, 05, 02, 11, 00, 19, 09, 02, 12, 04, 0e, 1b, 06, 0e, 00, 13, 16, 01, 0f, 00, 16, 15, 01, 16, 02, 0e, 11, 04, 11, 00, 19, 15, 03, 09, 00, 0e, 2f, 02, 0e, 00, 13, 2a, 01, 0f, 00, 16, 1d, 01, 15, 02, 0e, 21, 04, 11, 00, 19, 1d, 03, 09, 00, 0e, 43, 02, 0e, 00, 13, 3e, 01, 0c, 00, 13, 29, 01, 0d, 00, 15, 2d, 01, 0a, 01, 0e, 57, 03, 0e, 00, 13, 52, 01, 0f, 00, 16, 39, 01, 16, 02, 0e, 35, 03, 12, 02, 0e, 5f, 04, 09, 00, 0e, 6b, 02, 0e, 00, 13, 66, 01, 0f, 00, 16, 41, 01, 16, 02, 0e, 49, 04, 11, 00, 16, 41, 03, 09, 00, 0e, 6f, 02, 0d, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 28
@@ -21,16 +21,16 @@ Number of expressions: 28
 - expression 15 operands: lhs = Expression(16, Add), rhs = Counter(12)
 - expression 16 operands: lhs = Expression(17, Add), rhs = Counter(11)
 - expression 17 operands: lhs = Counter(9), rhs = Counter(10)
-- expression 18 operands: lhs = Counter(12), rhs = Expression(23, Add)
-- expression 19 operands: lhs = Counter(13), rhs = Counter(14)
+- expression 18 operands: lhs = Expression(22, Add), rhs = Counter(14)
+- expression 19 operands: lhs = Counter(12), rhs = Counter(13)
 - expression 20 operands: lhs = Expression(21, Add), rhs = Counter(15)
-- expression 21 operands: lhs = Counter(12), rhs = Expression(23, Add)
-- expression 22 operands: lhs = Counter(13), rhs = Counter(14)
+- expression 21 operands: lhs = Expression(22, Add), rhs = Counter(14)
+- expression 22 operands: lhs = Counter(12), rhs = Counter(13)
 - expression 23 operands: lhs = Counter(13), rhs = Counter(14)
 - expression 24 operands: lhs = Counter(15), rhs = Counter(16)
 - expression 25 operands: lhs = Expression(26, Add), rhs = Counter(17)
 - expression 26 operands: lhs = Counter(15), rhs = Counter(16)
-- expression 27 operands: lhs = Counter(18), rhs = Counter(17)
+- expression 27 operands: lhs = Counter(17), rhs = Counter(18)
 Number of file 0 mappings: 30
 - Code(Counter(0)) at (prev + 3, 1) to (start + 3, 18)
 - Code(Expression(0, Add)) at (prev + 4, 14) to (start + 0, 19)
@@ -60,9 +60,9 @@ Number of file 0 mappings: 30
 - Code(Counter(10)) at (prev + 1, 13) to (start + 0, 21)
 - Code(Counter(11)) at (prev + 1, 10) to (start + 1, 14)
 - Code(Expression(21, Add)) at (prev + 3, 14) to (start + 0, 19)
-    = (c12 + (c13 + c14))
+    = ((c12 + c13) + c14)
 - Code(Expression(20, Sub)) at (prev + 1, 15) to (start + 0, 22)
-    = ((c12 + (c13 + c14)) - c15)
+    = (((c12 + c13) + c14) - c15)
 - Code(Counter(14)) at (prev + 1, 22) to (start + 2, 14)
 - Code(Counter(13)) at (prev + 3, 18) to (start + 2, 14)
 - Code(Expression(23, Add)) at (prev + 4, 9) to (start + 0, 14)
@@ -75,6 +75,6 @@ Number of file 0 mappings: 30
 - Code(Counter(18)) at (prev + 4, 17) to (start + 0, 22)
 - Code(Counter(16)) at (prev + 3, 9) to (start + 0, 14)
 - Code(Expression(27, Add)) at (prev + 2, 13) to (start + 1, 2)
-    = (c18 + c17)
+    = (c17 + c18)
 Highest counter ID seen: c18
 
diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map
index 2fdc3220c19..21f6787e9f2 100644
--- a/tests/coverage/coroutine.cov-map
+++ b/tests/coverage/coroutine.cov-map
@@ -13,18 +13,18 @@ Number of file 0 mappings: 4
 Highest counter ID seen: c1
 
 Function name: coroutine::main
-Raw bytes (65): 0x[01, 01, 08, 07, 0d, 05, 09, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02]
+Raw bytes (65): 0x[01, 01, 08, 07, 0d, 05, 09, 11, 15, 11, 1f, 15, 19, 15, 19, 11, 1f, 15, 19, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 0a, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 1f, 01, 0e, 00, 35, 1a, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 8
 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3)
 - expression 1 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 2 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 3 operands: lhs = Expression(7, Sub), rhs = Counter(6)
-- expression 4 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 3 operands: lhs = Counter(4), rhs = Expression(7, Add)
+- expression 4 operands: lhs = Counter(5), rhs = Counter(6)
 - expression 5 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 6 operands: lhs = Expression(7, Sub), rhs = Counter(6)
-- expression 7 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 6 operands: lhs = Counter(4), rhs = Expression(7, Add)
+- expression 7 operands: lhs = Counter(5), rhs = Counter(6)
 Number of file 0 mappings: 9
 - Code(Counter(0)) at (prev + 19, 1) to (start + 2, 22)
 - Code(Counter(0)) at (prev + 8, 11) to (start + 0, 46)
@@ -32,14 +32,14 @@ Number of file 0 mappings: 9
 - Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 53)
     = ((c1 + c2) + c3)
 - Code(Counter(4)) at (prev + 2, 11) to (start + 0, 46)
-- Code(Expression(7, Sub)) at (prev + 1, 34) to (start + 0, 39)
+- Code(Expression(2, Sub)) at (prev + 1, 34) to (start + 0, 39)
     = (c4 - c5)
 - Code(Expression(6, Sub)) at (prev + 0, 44) to (start + 0, 46)
-    = ((c4 - c5) - c6)
-- Code(Expression(5, Add)) at (prev + 1, 14) to (start + 0, 53)
+    = (c4 - (c5 + c6))
+- Code(Expression(7, Add)) at (prev + 1, 14) to (start + 0, 53)
     = (c5 + c6)
 - Code(Expression(6, Sub)) at (prev + 2, 1) to (start + 0, 2)
-    = ((c4 - c5) - c6)
+    = (c4 - (c5 + c6))
 Highest counter ID seen: c4
 
 Function name: coroutine::main::{closure#0}
diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map
index 5a20de3d4d4..3e2ca2bc992 100644
--- a/tests/coverage/inline-dead.cov-map
+++ b/tests/coverage/inline-dead.cov-map
@@ -32,16 +32,16 @@ Number of file 0 mappings: 2
 Highest counter ID seen: c0
 
 Function name: inline_dead::main::{closure#0}
-Raw bytes (23): 0x[01, 01, 02, 00, 06, 01, 00, 03, 01, 07, 17, 01, 16, 00, 01, 17, 00, 18, 03, 01, 05, 00, 06]
+Raw bytes (23): 0x[01, 01, 02, 07, 00, 01, 00, 03, 01, 07, 17, 01, 16, 00, 01, 17, 00, 18, 02, 01, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
-- expression 0 operands: lhs = Zero, rhs = Expression(1, Sub)
+- expression 0 operands: lhs = Expression(1, Add), rhs = Zero
 - expression 1 operands: lhs = Counter(0), rhs = Zero
 Number of file 0 mappings: 3
 - Code(Counter(0)) at (prev + 7, 23) to (start + 1, 22)
 - Code(Zero) at (prev + 1, 23) to (start + 0, 24)
-- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 0, 6)
-    = (Zero + (c0 - Zero))
+- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 6)
+    = ((c0 + Zero) - Zero)
 Highest counter ID seen: c0
 
diff --git a/tests/coverage/inline.cov-map b/tests/coverage/inline.cov-map
index ab3a505e925..1b5b45695dc 100644
--- a/tests/coverage/inline.cov-map
+++ b/tests/coverage/inline.cov-map
@@ -41,14 +41,15 @@ Number of file 0 mappings: 1
 Highest counter ID seen: c0
 
 Function name: inline::permutate::<char>
-Raw bytes (52): 0x[01, 01, 04, 01, 05, 02, 0d, 05, 0f, 09, 0d, 08, 01, 0f, 01, 02, 0e, 05, 02, 0f, 02, 06, 02, 02, 0f, 00, 14, 11, 01, 0d, 00, 0e, 06, 00, 12, 00, 16, 11, 00, 17, 04, 0a, 0d, 05, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (54): 0x[01, 01, 05, 01, 05, 01, 0b, 05, 0d, 13, 0d, 05, 09, 08, 01, 0f, 01, 02, 0e, 05, 02, 0f, 02, 06, 02, 02, 0f, 00, 14, 11, 01, 0d, 00, 0e, 06, 00, 12, 00, 16, 11, 00, 17, 04, 0a, 0d, 05, 0c, 02, 06, 0f, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 4
+Number of expressions: 5
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(3)
-- expression 2 operands: lhs = Counter(1), rhs = Expression(3, Add)
-- expression 3 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 1 operands: lhs = Counter(0), rhs = Expression(2, Add)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(3)
+- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(3)
+- expression 4 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 8
 - Code(Counter(0)) at (prev + 15, 1) to (start + 2, 14)
 - Code(Counter(1)) at (prev + 2, 15) to (start + 2, 6)
@@ -56,11 +57,11 @@ Number of file 0 mappings: 8
     = (c0 - c1)
 - Code(Counter(4)) at (prev + 1, 13) to (start + 0, 14)
 - Code(Expression(1, Sub)) at (prev + 0, 18) to (start + 0, 22)
-    = ((c0 - c1) - c3)
+    = (c0 - (c1 + c3))
 - Code(Counter(4)) at (prev + 0, 23) to (start + 4, 10)
 - Code(Counter(3)) at (prev + 5, 12) to (start + 2, 6)
-- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2)
-    = (c1 + (c2 + c3))
+- Code(Expression(3, Add)) at (prev + 3, 1) to (start + 0, 2)
+    = ((c1 + c2) + c3)
 Highest counter ID seen: c4
 
 Function name: inline::permutations::<char>
diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map
index 64870c434b3..a2ab558f960 100644
--- a/tests/coverage/issue-84561.cov-map
+++ b/tests/coverage/issue-84561.cov-map
@@ -59,69 +59,69 @@ Number of file 0 mappings: 1
 Highest counter ID seen: c0
 
 Function name: issue_84561::test3
-Raw bytes (414): 0x[01, 01, 3b, 05, 09, 0d, 11, 15, 19, 1e, 1d, 15, 19, 1a, 21, 1e, 1d, 15, 19, 25, 2d, 21, 25, 29, 35, 32, 29, 21, 25, 31, 39, 3d, 41, 42, 45, 3d, 41, 66, 49, 45, 4d, 63, 51, 66, 49, 45, 4d, 5e, 55, 63, 51, 66, 49, 45, 4d, 9e, 01, 55, 51, 59, 9e, 01, 55, 51, 59, 9b, 01, 5d, 9e, 01, 55, 51, 59, 9b, 01, 61, 9e, 01, 55, 51, 59, 96, 01, 65, 9b, 01, 61, 9e, 01, 55, 51, 59, 75, e2, 01, e6, 01, 79, 69, 6d, 69, 6d, 69, 6d, e6, 01, 00, 69, 6d, e6, 01, 79, 69, 6d, df, 01, 7d, 75, e2, 01, e6, 01, 79, 69, 6d, da, 01, 81, 01, df, 01, 7d, 75, e2, 01, e6, 01, 79, 69, 6d, 81, 01, 85, 01, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 1e, 02, 05, 00, 1f, 1a, 01, 05, 00, 0f, 16, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 2d, 00, 33, 00, 41, 22, 00, 4b, 00, 5a, 32, 01, 05, 00, 0f, 29, 05, 09, 03, 10, 35, 05, 0d, 00, 1b, 2a, 02, 0d, 00, 1c, 2e, 04, 09, 05, 06, 31, 06, 05, 03, 06, 36, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 42, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 3e, 05, 09, 03, 0a, 63, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 59, 03, 0d, 00, 1d, 5e, 03, 09, 00, 13, 5a, 03, 0d, 00, 1d, 9b, 01, 03, 05, 00, 0f, 9b, 01, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 7a, 02, 0d, 00, 13, 96, 01, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 92, 01, 02, 0d, 00, 13, df, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, e6, 01, 02, 0d, 00, 17, e6, 01, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, b6, 01, 02, 15, 00, 1b, e2, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, da, 01, 02, 05, 00, 0f, d6, 01, 03, 09, 00, 22, 81, 01, 02, 05, 00, 0f, ea, 01, 03, 09, 00, 2c, 85, 01, 02, 01, 00, 02]
+Raw bytes (409): 0x[01, 01, 3b, 05, 09, 0d, 11, 15, 19, 15, 1f, 19, 1d, 15, 1b, 1f, 21, 19, 1d, 25, 29, 21, 25, 2d, 31, 21, 33, 25, 2d, 35, 39, 3d, 41, 3d, 43, 41, 45, 5f, 4d, 45, 49, 5f, 67, 45, 49, 4d, 51, 5f, 63, 45, 49, 67, 59, 4d, 51, 97, 01, 55, 51, 59, 97, 01, 55, 51, 59, 97, 01, 83, 01, 51, 59, 55, 5d, 97, 01, 9f, 01, 51, 59, 55, 61, 97, 01, 9b, 01, 51, 59, 9f, 01, 65, 55, 61, db, 01, e7, 01, 69, 71, 6d, 75, 69, 6d, 69, 6d, 69, bb, 01, 6d, 00, 69, e7, 01, 6d, 75, db, 01, e3, 01, 69, 71, e7, 01, 79, 6d, 75, db, 01, df, 01, 69, 71, e3, 01, 7d, e7, 01, 79, 6d, 75, 7d, 81, 01, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 0a, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 16, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 29, 00, 33, 00, 41, 22, 00, 4b, 00, 5a, 26, 01, 05, 00, 0f, 2d, 05, 09, 03, 10, 31, 05, 0d, 00, 1b, 2a, 02, 0d, 00, 1c, 2e, 04, 09, 05, 06, 35, 06, 05, 03, 06, 36, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 3a, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 3e, 05, 09, 03, 0a, 46, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 55, 03, 0d, 00, 1d, 4e, 03, 09, 00, 13, 5a, 03, 0d, 00, 1d, 72, 03, 05, 00, 0f, 72, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 7a, 02, 0d, 00, 13, 86, 01, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 92, 01, 02, 0d, 00, 13, a2, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 71, 04, 0d, 00, 13, b2, 01, 02, 0d, 00, 17, b2, 01, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, b6, 01, 02, 15, 00, 1b, be, 01, 04, 0d, 00, 13, 79, 03, 09, 00, 19, c6, 01, 02, 05, 00, 0f, d6, 01, 03, 09, 00, 22, 7d, 02, 05, 00, 0f, ea, 01, 03, 09, 00, 2c, 81, 01, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 59
 - expression 0 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 1 operands: lhs = Counter(3), rhs = Counter(4)
 - expression 2 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 3 operands: lhs = Expression(7, Sub), rhs = Counter(7)
-- expression 4 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 5 operands: lhs = Expression(6, Sub), rhs = Counter(8)
-- expression 6 operands: lhs = Expression(7, Sub), rhs = Counter(7)
-- expression 7 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 8 operands: lhs = Counter(9), rhs = Counter(11)
+- expression 3 operands: lhs = Counter(5), rhs = Expression(7, Add)
+- expression 4 operands: lhs = Counter(6), rhs = Counter(7)
+- expression 5 operands: lhs = Counter(5), rhs = Expression(6, Add)
+- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(8)
+- expression 7 operands: lhs = Counter(6), rhs = Counter(7)
+- expression 8 operands: lhs = Counter(9), rhs = Counter(10)
 - expression 9 operands: lhs = Counter(8), rhs = Counter(9)
-- expression 10 operands: lhs = Counter(10), rhs = Counter(13)
-- expression 11 operands: lhs = Expression(12, Sub), rhs = Counter(10)
-- expression 12 operands: lhs = Counter(8), rhs = Counter(9)
-- expression 13 operands: lhs = Counter(12), rhs = Counter(14)
+- expression 10 operands: lhs = Counter(11), rhs = Counter(12)
+- expression 11 operands: lhs = Counter(8), rhs = Expression(12, Add)
+- expression 12 operands: lhs = Counter(9), rhs = Counter(11)
+- expression 13 operands: lhs = Counter(13), rhs = Counter(14)
 - expression 14 operands: lhs = Counter(15), rhs = Counter(16)
-- expression 15 operands: lhs = Expression(16, Sub), rhs = Counter(17)
-- expression 16 operands: lhs = Counter(15), rhs = Counter(16)
-- expression 17 operands: lhs = Expression(25, Sub), rhs = Counter(18)
-- expression 18 operands: lhs = Counter(17), rhs = Counter(19)
-- expression 19 operands: lhs = Expression(24, Add), rhs = Counter(20)
-- expression 20 operands: lhs = Expression(25, Sub), rhs = Counter(18)
-- expression 21 operands: lhs = Counter(17), rhs = Counter(19)
-- expression 22 operands: lhs = Expression(23, Sub), rhs = Counter(21)
-- expression 23 operands: lhs = Expression(24, Add), rhs = Counter(20)
-- expression 24 operands: lhs = Expression(25, Sub), rhs = Counter(18)
-- expression 25 operands: lhs = Counter(17), rhs = Counter(19)
-- expression 26 operands: lhs = Expression(39, Sub), rhs = Counter(21)
+- expression 15 operands: lhs = Counter(15), rhs = Expression(16, Add)
+- expression 16 operands: lhs = Counter(16), rhs = Counter(17)
+- expression 17 operands: lhs = Expression(23, Add), rhs = Counter(19)
+- expression 18 operands: lhs = Counter(17), rhs = Counter(18)
+- expression 19 operands: lhs = Expression(23, Add), rhs = Expression(25, Add)
+- expression 20 operands: lhs = Counter(17), rhs = Counter(18)
+- expression 21 operands: lhs = Counter(19), rhs = Counter(20)
+- expression 22 operands: lhs = Expression(23, Add), rhs = Expression(24, Add)
+- expression 23 operands: lhs = Counter(17), rhs = Counter(18)
+- expression 24 operands: lhs = Expression(25, Add), rhs = Counter(22)
+- expression 25 operands: lhs = Counter(19), rhs = Counter(20)
+- expression 26 operands: lhs = Expression(37, Add), rhs = Counter(21)
 - expression 27 operands: lhs = Counter(20), rhs = Counter(22)
-- expression 28 operands: lhs = Expression(39, Sub), rhs = Counter(21)
+- expression 28 operands: lhs = Expression(37, Add), rhs = Counter(21)
 - expression 29 operands: lhs = Counter(20), rhs = Counter(22)
-- expression 30 operands: lhs = Expression(38, Add), rhs = Counter(23)
-- expression 31 operands: lhs = Expression(39, Sub), rhs = Counter(21)
-- expression 32 operands: lhs = Counter(20), rhs = Counter(22)
-- expression 33 operands: lhs = Expression(38, Add), rhs = Counter(24)
-- expression 34 operands: lhs = Expression(39, Sub), rhs = Counter(21)
-- expression 35 operands: lhs = Counter(20), rhs = Counter(22)
-- expression 36 operands: lhs = Expression(37, Sub), rhs = Counter(25)
-- expression 37 operands: lhs = Expression(38, Add), rhs = Counter(24)
-- expression 38 operands: lhs = Expression(39, Sub), rhs = Counter(21)
-- expression 39 operands: lhs = Counter(20), rhs = Counter(22)
-- expression 40 operands: lhs = Counter(29), rhs = Expression(56, Sub)
-- expression 41 operands: lhs = Expression(57, Sub), rhs = Counter(30)
-- expression 42 operands: lhs = Counter(26), rhs = Counter(27)
+- expression 30 operands: lhs = Expression(37, Add), rhs = Expression(32, Add)
+- expression 31 operands: lhs = Counter(20), rhs = Counter(22)
+- expression 32 operands: lhs = Counter(21), rhs = Counter(23)
+- expression 33 operands: lhs = Expression(37, Add), rhs = Expression(39, Add)
+- expression 34 operands: lhs = Counter(20), rhs = Counter(22)
+- expression 35 operands: lhs = Counter(21), rhs = Counter(24)
+- expression 36 operands: lhs = Expression(37, Add), rhs = Expression(38, Add)
+- expression 37 operands: lhs = Counter(20), rhs = Counter(22)
+- expression 38 operands: lhs = Expression(39, Add), rhs = Counter(25)
+- expression 39 operands: lhs = Counter(21), rhs = Counter(24)
+- expression 40 operands: lhs = Expression(54, Add), rhs = Expression(57, Add)
+- expression 41 operands: lhs = Counter(26), rhs = Counter(28)
+- expression 42 operands: lhs = Counter(27), rhs = Counter(29)
 - expression 43 operands: lhs = Counter(26), rhs = Counter(27)
 - expression 44 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 45 operands: lhs = Expression(57, Sub), rhs = Zero
-- expression 46 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 47 operands: lhs = Expression(57, Sub), rhs = Counter(30)
-- expression 48 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 49 operands: lhs = Expression(55, Add), rhs = Counter(31)
-- expression 50 operands: lhs = Counter(29), rhs = Expression(56, Sub)
-- expression 51 operands: lhs = Expression(57, Sub), rhs = Counter(30)
-- expression 52 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 53 operands: lhs = Expression(54, Sub), rhs = Counter(32)
-- expression 54 operands: lhs = Expression(55, Add), rhs = Counter(31)
-- expression 55 operands: lhs = Counter(29), rhs = Expression(56, Sub)
-- expression 56 operands: lhs = Expression(57, Sub), rhs = Counter(30)
-- expression 57 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 58 operands: lhs = Counter(32), rhs = Counter(33)
+- expression 45 operands: lhs = Counter(26), rhs = Expression(46, Add)
+- expression 46 operands: lhs = Counter(27), rhs = Zero
+- expression 47 operands: lhs = Counter(26), rhs = Expression(57, Add)
+- expression 48 operands: lhs = Counter(27), rhs = Counter(29)
+- expression 49 operands: lhs = Expression(54, Add), rhs = Expression(56, Add)
+- expression 50 operands: lhs = Counter(26), rhs = Counter(28)
+- expression 51 operands: lhs = Expression(57, Add), rhs = Counter(30)
+- expression 52 operands: lhs = Counter(27), rhs = Counter(29)
+- expression 53 operands: lhs = Expression(54, Add), rhs = Expression(55, Add)
+- expression 54 operands: lhs = Counter(26), rhs = Counter(28)
+- expression 55 operands: lhs = Expression(56, Add), rhs = Counter(31)
+- expression 56 operands: lhs = Expression(57, Add), rhs = Counter(30)
+- expression 57 operands: lhs = Counter(27), rhs = Counter(29)
+- expression 58 operands: lhs = Counter(31), rhs = Counter(32)
 Number of file 0 mappings: 51
 - Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28)
 - Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28)
@@ -131,76 +131,76 @@ Number of file 0 mappings: 51
 - Code(Expression(1, Sub)) at (prev + 1, 5) to (start + 0, 31)
     = (c3 - c4)
 - Code(Counter(5)) at (prev + 1, 9) to (start + 1, 28)
-- Code(Expression(7, Sub)) at (prev + 2, 5) to (start + 0, 31)
+- Code(Expression(2, Sub)) at (prev + 2, 5) to (start + 0, 31)
     = (c5 - c6)
-- Code(Expression(6, Sub)) at (prev + 1, 5) to (start + 0, 15)
-    = ((c5 - c6) - c7)
+- Code(Expression(3, Sub)) at (prev + 1, 5) to (start + 0, 15)
+    = (c5 - (c6 + c7))
 - Code(Expression(5, Sub)) at (prev + 0, 32) to (start + 0, 48)
-    = (((c5 - c6) - c7) - c8)
+    = (c5 - ((c6 + c7) + c8))
 - Code(Counter(8)) at (prev + 1, 5) to (start + 3, 15)
 - Code(Counter(9)) at (prev + 3, 32) to (start + 0, 48)
-- Code(Counter(11)) at (prev + 0, 51) to (start + 0, 65)
+- Code(Counter(10)) at (prev + 0, 51) to (start + 0, 65)
 - Code(Expression(8, Sub)) at (prev + 0, 75) to (start + 0, 90)
-    = (c9 - c11)
-- Code(Expression(12, Sub)) at (prev + 1, 5) to (start + 0, 15)
+    = (c9 - c10)
+- Code(Expression(9, Sub)) at (prev + 1, 5) to (start + 0, 15)
     = (c8 - c9)
-- Code(Counter(10)) at (prev + 5, 9) to (start + 3, 16)
-- Code(Counter(13)) at (prev + 5, 13) to (start + 0, 27)
+- Code(Counter(11)) at (prev + 5, 9) to (start + 3, 16)
+- Code(Counter(12)) at (prev + 5, 13) to (start + 0, 27)
 - Code(Expression(10, Sub)) at (prev + 2, 13) to (start + 0, 28)
-    = (c10 - c13)
+    = (c11 - c12)
 - Code(Expression(11, Sub)) at (prev + 4, 9) to (start + 5, 6)
-    = ((c8 - c9) - c10)
-- Code(Counter(12)) at (prev + 6, 5) to (start + 3, 6)
+    = (c8 - (c9 + c11))
+- Code(Counter(13)) at (prev + 6, 5) to (start + 3, 6)
 - Code(Expression(13, Sub)) at (prev + 4, 5) to (start + 3, 6)
-    = (c12 - c14)
+    = (c13 - c14)
 - Code(Counter(15)) at (prev + 4, 9) to (start + 4, 6)
-- Code(Expression(16, Sub)) at (prev + 5, 8) to (start + 0, 15)
+- Code(Expression(14, Sub)) at (prev + 5, 8) to (start + 0, 15)
     = (c15 - c16)
 - Code(Counter(17)) at (prev + 1, 9) to (start + 3, 10)
 - Code(Expression(15, Sub)) at (prev + 5, 9) to (start + 3, 10)
-    = ((c15 - c16) - c17)
-- Code(Expression(24, Add)) at (prev + 5, 8) to (start + 0, 15)
-    = ((c17 - c19) + c18)
+    = (c15 - (c16 + c17))
+- Code(Expression(17, Sub)) at (prev + 5, 8) to (start + 0, 15)
+    = ((c17 + c18) - c19)
 - Code(Counter(20)) at (prev + 1, 9) to (start + 0, 19)
-- Code(Counter(22)) at (prev + 3, 13) to (start + 0, 29)
-- Code(Expression(23, Sub)) at (prev + 3, 9) to (start + 0, 19)
-    = (((c17 - c19) + c18) - c20)
+- Code(Counter(21)) at (prev + 3, 13) to (start + 0, 29)
+- Code(Expression(19, Sub)) at (prev + 3, 9) to (start + 0, 19)
+    = ((c17 + c18) - (c19 + c20))
 - Code(Expression(22, Sub)) at (prev + 3, 13) to (start + 0, 29)
-    = ((((c17 - c19) + c18) - c20) - c21)
-- Code(Expression(38, Add)) at (prev + 3, 5) to (start + 0, 15)
-    = ((c20 - c22) + c21)
-- Code(Expression(38, Add)) at (prev + 1, 12) to (start + 0, 19)
-    = ((c20 - c22) + c21)
+    = ((c17 + c18) - ((c19 + c20) + c22))
+- Code(Expression(28, Sub)) at (prev + 3, 5) to (start + 0, 15)
+    = ((c20 + c22) - c21)
+- Code(Expression(28, Sub)) at (prev + 1, 12) to (start + 0, 19)
+    = ((c20 + c22) - c21)
 - Code(Counter(23)) at (prev + 1, 13) to (start + 0, 19)
 - Code(Expression(30, Sub)) at (prev + 2, 13) to (start + 0, 19)
-    = (((c20 - c22) + c21) - c23)
-- Code(Expression(37, Sub)) at (prev + 4, 5) to (start + 2, 19)
-    = (((c20 - c22) + c21) - c24)
+    = ((c20 + c22) - (c21 + c23))
+- Code(Expression(33, Sub)) at (prev + 4, 5) to (start + 2, 19)
+    = ((c20 + c22) - (c21 + c24))
 - Code(Counter(25)) at (prev + 3, 13) to (start + 0, 19)
 - Code(Expression(36, Sub)) at (prev + 2, 13) to (start + 0, 19)
-    = ((((c20 - c22) + c21) - c24) - c25)
-- Code(Expression(55, Add)) at (prev + 3, 5) to (start + 0, 15)
-    = (c29 + ((c26 - c27) - c30))
+    = ((c20 + c22) - ((c21 + c24) + c25))
+- Code(Expression(40, Sub)) at (prev + 3, 5) to (start + 0, 15)
+    = ((c26 + c28) - (c27 + c29))
 - Code(Counter(26)) at (prev + 1, 12) to (start + 0, 19)
 - Code(Counter(27)) at (prev + 1, 13) to (start + 3, 14)
-- Code(Counter(29)) at (prev + 4, 13) to (start + 0, 19)
-- Code(Expression(57, Sub)) at (prev + 2, 13) to (start + 0, 23)
+- Code(Counter(28)) at (prev + 4, 13) to (start + 0, 19)
+- Code(Expression(44, Sub)) at (prev + 2, 13) to (start + 0, 23)
     = (c26 - c27)
-- Code(Expression(57, Sub)) at (prev + 1, 20) to (start + 0, 27)
+- Code(Expression(44, Sub)) at (prev + 1, 20) to (start + 0, 27)
     = (c26 - c27)
 - Code(Zero) at (prev + 1, 21) to (start + 0, 27)
 - Code(Expression(45, Sub)) at (prev + 2, 21) to (start + 0, 27)
-    = ((c26 - c27) - Zero)
-- Code(Expression(56, Sub)) at (prev + 4, 13) to (start + 0, 19)
-    = ((c26 - c27) - c30)
-- Code(Counter(31)) at (prev + 3, 9) to (start + 0, 25)
-- Code(Expression(54, Sub)) at (prev + 2, 5) to (start + 0, 15)
-    = ((c29 + ((c26 - c27) - c30)) - c31)
+    = (c26 - (c27 + Zero))
+- Code(Expression(47, Sub)) at (prev + 4, 13) to (start + 0, 19)
+    = (c26 - (c27 + c29))
+- Code(Counter(30)) at (prev + 3, 9) to (start + 0, 25)
+- Code(Expression(49, Sub)) at (prev + 2, 5) to (start + 0, 15)
+    = ((c26 + c28) - ((c27 + c29) + c30))
 - Code(Expression(53, Sub)) at (prev + 3, 9) to (start + 0, 34)
-    = (((c29 + ((c26 - c27) - c30)) - c31) - c32)
-- Code(Counter(32)) at (prev + 2, 5) to (start + 0, 15)
+    = ((c26 + c28) - (((c27 + c29) + c30) + c31))
+- Code(Counter(31)) at (prev + 2, 5) to (start + 0, 15)
 - Code(Expression(58, Sub)) at (prev + 3, 9) to (start + 0, 44)
-    = (c32 - c33)
-- Code(Counter(33)) at (prev + 2, 1) to (start + 0, 2)
-Highest counter ID seen: c33
+    = (c31 - c32)
+- Code(Counter(32)) at (prev + 2, 1) to (start + 0, 2)
+Highest counter ID seen: c32
 
diff --git a/tests/coverage/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map
index b0c2d736573..3f7788da1eb 100644
--- a/tests/coverage/lazy_boolean.cov-map
+++ b/tests/coverage/lazy_boolean.cov-map
@@ -1,15 +1,15 @@
 Function name: lazy_boolean::main
-Raw bytes (158): 0x[01, 01, 07, 01, 05, 01, 09, 01, 0d, 01, 19, 01, 1d, 01, 21, 01, 25, 1c, 01, 04, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 05, 00, 06, 01, 02, 09, 00, 11, 01, 02, 0d, 00, 12, 06, 02, 0d, 00, 12, 01, 03, 09, 00, 11, 01, 02, 0d, 00, 12, 0a, 02, 0d, 00, 12, 01, 02, 09, 00, 11, 01, 00, 14, 00, 19, 11, 00, 1d, 00, 22, 01, 01, 09, 00, 11, 01, 00, 14, 00, 19, 15, 00, 1d, 00, 22, 01, 03, 09, 01, 10, 0e, 02, 05, 03, 06, 19, 03, 05, 00, 06, 01, 03, 09, 00, 10, 1d, 01, 05, 03, 06, 12, 05, 05, 03, 06, 01, 05, 08, 00, 10, 16, 00, 11, 02, 06, 21, 02, 05, 00, 06, 01, 02, 08, 00, 0f, 25, 00, 10, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02]
+Raw bytes (158): 0x[01, 01, 07, 01, 05, 01, 25, 01, 21, 01, 11, 01, 15, 01, 19, 01, 1d, 1c, 01, 04, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 05, 00, 06, 01, 02, 09, 00, 11, 01, 02, 0d, 00, 12, 06, 02, 0d, 00, 12, 01, 03, 09, 00, 11, 01, 02, 0d, 00, 12, 0a, 02, 0d, 00, 12, 01, 02, 09, 00, 11, 01, 00, 14, 00, 19, 09, 00, 1d, 00, 22, 01, 01, 09, 00, 11, 01, 00, 14, 00, 19, 0d, 00, 1d, 00, 22, 01, 03, 09, 01, 10, 0e, 02, 05, 03, 06, 11, 03, 05, 00, 06, 01, 03, 09, 00, 10, 15, 01, 05, 03, 06, 12, 05, 05, 03, 06, 01, 05, 08, 00, 10, 16, 00, 11, 02, 06, 19, 02, 05, 00, 06, 01, 02, 08, 00, 0f, 1d, 00, 10, 02, 06, 1a, 02, 0c, 02, 06, 01, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 7
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(0), rhs = Counter(2)
-- expression 2 operands: lhs = Counter(0), rhs = Counter(3)
-- expression 3 operands: lhs = Counter(0), rhs = Counter(6)
-- expression 4 operands: lhs = Counter(0), rhs = Counter(7)
-- expression 5 operands: lhs = Counter(0), rhs = Counter(8)
-- expression 6 operands: lhs = Counter(0), rhs = Counter(9)
+- expression 1 operands: lhs = Counter(0), rhs = Counter(9)
+- expression 2 operands: lhs = Counter(0), rhs = Counter(8)
+- expression 3 operands: lhs = Counter(0), rhs = Counter(4)
+- expression 4 operands: lhs = Counter(0), rhs = Counter(5)
+- expression 5 operands: lhs = Counter(0), rhs = Counter(6)
+- expression 6 operands: lhs = Counter(0), rhs = Counter(7)
 Number of file 0 mappings: 28
 - Code(Counter(0)) at (prev + 4, 1) to (start + 7, 15)
 - Code(Counter(1)) at (prev + 7, 16) to (start + 4, 6)
@@ -18,33 +18,33 @@ Number of file 0 mappings: 28
 - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 17)
 - Code(Counter(0)) at (prev + 2, 13) to (start + 0, 18)
 - Code(Expression(1, Sub)) at (prev + 2, 13) to (start + 0, 18)
-    = (c0 - c2)
+    = (c0 - c9)
 - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 17)
 - Code(Counter(0)) at (prev + 2, 13) to (start + 0, 18)
 - Code(Expression(2, Sub)) at (prev + 2, 13) to (start + 0, 18)
-    = (c0 - c3)
+    = (c0 - c8)
 - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 17)
 - Code(Counter(0)) at (prev + 0, 20) to (start + 0, 25)
-- Code(Counter(4)) at (prev + 0, 29) to (start + 0, 34)
+- Code(Counter(2)) at (prev + 0, 29) to (start + 0, 34)
 - Code(Counter(0)) at (prev + 1, 9) to (start + 0, 17)
 - Code(Counter(0)) at (prev + 0, 20) to (start + 0, 25)
-- Code(Counter(5)) at (prev + 0, 29) to (start + 0, 34)
+- Code(Counter(3)) at (prev + 0, 29) to (start + 0, 34)
 - Code(Counter(0)) at (prev + 3, 9) to (start + 1, 16)
 - Code(Expression(3, Sub)) at (prev + 2, 5) to (start + 3, 6)
-    = (c0 - c6)
-- Code(Counter(6)) at (prev + 3, 5) to (start + 0, 6)
+    = (c0 - c4)
+- Code(Counter(4)) at (prev + 3, 5) to (start + 0, 6)
 - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 16)
-- Code(Counter(7)) at (prev + 1, 5) to (start + 3, 6)
+- Code(Counter(5)) at (prev + 1, 5) to (start + 3, 6)
 - Code(Expression(4, Sub)) at (prev + 5, 5) to (start + 3, 6)
-    = (c0 - c7)
+    = (c0 - c5)
 - Code(Counter(0)) at (prev + 5, 8) to (start + 0, 16)
 - Code(Expression(5, Sub)) at (prev + 0, 17) to (start + 2, 6)
-    = (c0 - c8)
-- Code(Counter(8)) at (prev + 2, 5) to (start + 0, 6)
+    = (c0 - c6)
+- Code(Counter(6)) at (prev + 2, 5) to (start + 0, 6)
 - Code(Counter(0)) at (prev + 2, 8) to (start + 0, 15)
-- Code(Counter(9)) at (prev + 0, 16) to (start + 2, 6)
+- Code(Counter(7)) at (prev + 0, 16) to (start + 2, 6)
 - Code(Expression(6, Sub)) at (prev + 2, 12) to (start + 2, 6)
-    = (c0 - c9)
+    = (c0 - c7)
 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2)
-Highest counter ID seen: c9
+Highest counter ID seen: c7
 
diff --git a/tests/coverage/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map
index 61a6bda676a..14707701d8a 100644
--- a/tests/coverage/loops_branches.cov-map
+++ b/tests/coverage/loops_branches.cov-map
@@ -1,50 +1,42 @@
 Function name: <loops_branches::DebugTest as core::fmt::Debug>::fmt
-Raw bytes (228): 0x[01, 01, 2a, 05, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, a3, 01, a7, 01, 0d, 00, 11, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 96, 01, 00, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 96, 01, 11, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 8f, 01, 19, 25, 92, 01, 96, 01, 11, 9a, 01, 00, 9f, 01, 19, a3, 01, a7, 01, 0d, 00, 11, 00, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 02, 01, 0d, 00, 0e, 05, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 9a, 01, 03, 0d, 00, 0e, 9f, 01, 00, 12, 00, 17, 9a, 01, 01, 10, 00, 14, 96, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 46, 01, 11, 00, 12, 96, 01, 01, 11, 00, 22, 92, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, 8b, 01, 01, 05, 00, 06]
+Raw bytes (174): 0x[01, 01, 22, 05, 00, 2f, 7b, 67, 00, 77, 19, 01, 15, 05, 21, 2f, 05, 67, 00, 77, 19, 01, 15, 2f, 7b, 67, 00, 77, 19, 01, 15, 05, 21, 67, 7b, 77, 19, 01, 15, 05, 21, 67, 5b, 77, 19, 01, 15, 7b, 00, 05, 21, 67, 7b, 77, 19, 01, 15, 05, 21, 77, 7b, 01, 15, 05, 21, 83, 01, 05, 87, 01, 15, 01, 11, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 02, 01, 0d, 00, 0e, 05, 01, 0d, 00, 1e, 11, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 2a, 03, 0d, 00, 0e, 1a, 00, 12, 00, 17, 2a, 01, 10, 00, 14, 62, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 4e, 01, 11, 00, 12, 62, 01, 11, 00, 22, 72, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 21, 03, 09, 00, 0f, 7e, 01, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 42
+Number of expressions: 34
 - expression 0 operands: lhs = Counter(1), rhs = Zero
-- expression 1 operands: lhs = Expression(39, Add), rhs = Counter(6)
-- expression 2 operands: lhs = Expression(40, Add), rhs = Expression(41, Add)
-- expression 3 operands: lhs = Counter(3), rhs = Zero
-- expression 4 operands: lhs = Counter(4), rhs = Zero
-- expression 5 operands: lhs = Expression(40, Add), rhs = Expression(41, Add)
-- expression 6 operands: lhs = Counter(3), rhs = Zero
-- expression 7 operands: lhs = Counter(4), rhs = Zero
-- expression 8 operands: lhs = Expression(39, Add), rhs = Counter(6)
-- expression 9 operands: lhs = Expression(40, Add), rhs = Expression(41, Add)
-- expression 10 operands: lhs = Counter(3), rhs = Zero
-- expression 11 operands: lhs = Counter(4), rhs = Zero
-- expression 12 operands: lhs = Expression(38, Sub), rhs = Zero
-- expression 13 operands: lhs = Expression(39, Add), rhs = Counter(6)
-- expression 14 operands: lhs = Expression(40, Add), rhs = Expression(41, Add)
-- expression 15 operands: lhs = Counter(3), rhs = Zero
-- expression 16 operands: lhs = Counter(4), rhs = Zero
-- expression 17 operands: lhs = Expression(37, Sub), rhs = Zero
-- expression 18 operands: lhs = Expression(38, Sub), rhs = Zero
-- expression 19 operands: lhs = Expression(39, Add), rhs = Counter(6)
-- expression 20 operands: lhs = Expression(40, Add), rhs = Expression(41, Add)
-- expression 21 operands: lhs = Counter(3), rhs = Zero
-- expression 22 operands: lhs = Counter(4), rhs = Zero
-- expression 23 operands: lhs = Expression(38, Sub), rhs = Zero
-- expression 24 operands: lhs = Expression(39, Add), rhs = Counter(6)
-- expression 25 operands: lhs = Expression(40, Add), rhs = Expression(41, Add)
-- expression 26 operands: lhs = Counter(3), rhs = Zero
-- expression 27 operands: lhs = Counter(4), rhs = Zero
-- expression 28 operands: lhs = Expression(37, Sub), rhs = Counter(4)
-- expression 29 operands: lhs = Expression(38, Sub), rhs = Zero
-- expression 30 operands: lhs = Expression(39, Add), rhs = Counter(6)
-- expression 31 operands: lhs = Expression(40, Add), rhs = Expression(41, Add)
-- expression 32 operands: lhs = Counter(3), rhs = Zero
-- expression 33 operands: lhs = Counter(4), rhs = Zero
-- expression 34 operands: lhs = Expression(35, Add), rhs = Counter(6)
-- expression 35 operands: lhs = Counter(9), rhs = Expression(36, Sub)
-- expression 36 operands: lhs = Expression(37, Sub), rhs = Counter(4)
-- expression 37 operands: lhs = Expression(38, Sub), rhs = Zero
-- expression 38 operands: lhs = Expression(39, Add), rhs = Counter(6)
-- expression 39 operands: lhs = Expression(40, Add), rhs = Expression(41, Add)
-- expression 40 operands: lhs = Counter(3), rhs = Zero
-- expression 41 operands: lhs = Counter(4), rhs = Zero
+- expression 1 operands: lhs = Expression(11, Add), rhs = Expression(30, Add)
+- expression 2 operands: lhs = Expression(25, Add), rhs = Zero
+- expression 3 operands: lhs = Expression(29, Add), rhs = Counter(6)
+- expression 4 operands: lhs = Counter(0), rhs = Counter(5)
+- expression 5 operands: lhs = Counter(1), rhs = Counter(8)
+- expression 6 operands: lhs = Expression(11, Add), rhs = Counter(1)
+- expression 7 operands: lhs = Expression(25, Add), rhs = Zero
+- expression 8 operands: lhs = Expression(29, Add), rhs = Counter(6)
+- expression 9 operands: lhs = Counter(0), rhs = Counter(5)
+- expression 10 operands: lhs = Expression(11, Add), rhs = Expression(30, Add)
+- expression 11 operands: lhs = Expression(25, Add), rhs = Zero
+- expression 12 operands: lhs = Expression(29, Add), rhs = Counter(6)
+- expression 13 operands: lhs = Counter(0), rhs = Counter(5)
+- expression 14 operands: lhs = Counter(1), rhs = Counter(8)
+- expression 15 operands: lhs = Expression(25, Add), rhs = Expression(30, Add)
+- expression 16 operands: lhs = Expression(29, Add), rhs = Counter(6)
+- expression 17 operands: lhs = Counter(0), rhs = Counter(5)
+- expression 18 operands: lhs = Counter(1), rhs = Counter(8)
+- expression 19 operands: lhs = Expression(25, Add), rhs = Expression(22, Add)
+- expression 20 operands: lhs = Expression(29, Add), rhs = Counter(6)
+- expression 21 operands: lhs = Counter(0), rhs = Counter(5)
+- expression 22 operands: lhs = Expression(30, Add), rhs = Zero
+- expression 23 operands: lhs = Counter(1), rhs = Counter(8)
+- expression 24 operands: lhs = Expression(25, Add), rhs = Expression(30, Add)
+- expression 25 operands: lhs = Expression(29, Add), rhs = Counter(6)
+- expression 26 operands: lhs = Counter(0), rhs = Counter(5)
+- expression 27 operands: lhs = Counter(1), rhs = Counter(8)
+- expression 28 operands: lhs = Expression(29, Add), rhs = Expression(30, Add)
+- expression 29 operands: lhs = Counter(0), rhs = Counter(5)
+- expression 30 operands: lhs = Counter(1), rhs = Counter(8)
+- expression 31 operands: lhs = Expression(32, Add), rhs = Counter(1)
+- expression 32 operands: lhs = Expression(33, Add), rhs = Counter(5)
+- expression 33 operands: lhs = Counter(0), rhs = Counter(4)
 Number of file 0 mappings: 20
 - Code(Counter(0)) at (prev + 9, 5) to (start + 1, 16)
 - Code(Counter(1)) at (prev + 2, 16) to (start + 0, 21)
@@ -53,78 +45,59 @@ Number of file 0 mappings: 20
 - Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 14)
     = (c1 - Zero)
 - Code(Counter(1)) at (prev + 1, 13) to (start + 0, 30)
-- Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31)
+- Code(Counter(4)) at (prev + 0, 30) to (start + 0, 31)
 - Code(Zero) at (prev + 1, 16) to (start + 1, 10)
-- Code(Expression(38, Sub)) at (prev + 3, 13) to (start + 0, 14)
-    = (((c3 + Zero) + (c4 + Zero)) - c6)
-- Code(Expression(39, Add)) at (prev + 0, 18) to (start + 0, 23)
-    = ((c3 + Zero) + (c4 + Zero))
-- Code(Expression(38, Sub)) at (prev + 1, 16) to (start + 0, 20)
-    = (((c3 + Zero) + (c4 + Zero)) - c6)
-- Code(Expression(37, Sub)) at (prev + 1, 20) to (start + 0, 25)
-    = ((((c3 + Zero) + (c4 + Zero)) - c6) - Zero)
+- Code(Expression(10, Sub)) at (prev + 3, 13) to (start + 0, 14)
+    = ((((c0 + c5) + c6) + Zero) - (c1 + c8))
+- Code(Expression(6, Sub)) at (prev + 0, 18) to (start + 0, 23)
+    = ((((c0 + c5) + c6) + Zero) - c1)
+- Code(Expression(10, Sub)) at (prev + 1, 16) to (start + 0, 20)
+    = ((((c0 + c5) + c6) + Zero) - (c1 + c8))
+- Code(Expression(24, Sub)) at (prev + 1, 20) to (start + 0, 25)
+    = (((c0 + c5) + c6) - (c1 + c8))
 - Code(Zero) at (prev + 1, 27) to (start + 0, 31)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 34)
-- Code(Expression(17, Sub)) at (prev + 1, 17) to (start + 0, 18)
-    = (((((c3 + Zero) + (c4 + Zero)) - c6) - Zero) - Zero)
-- Code(Expression(37, Sub)) at (prev + 1, 17) to (start + 0, 34)
-    = ((((c3 + Zero) + (c4 + Zero)) - c6) - Zero)
-- Code(Expression(36, Sub)) at (prev + 0, 34) to (start + 0, 35)
-    = (((((c3 + Zero) + (c4 + Zero)) - c6) - Zero) - c4)
+- Code(Expression(19, Sub)) at (prev + 1, 17) to (start + 0, 18)
+    = (((c0 + c5) + c6) - ((c1 + c8) + Zero))
+- Code(Expression(24, Sub)) at (prev + 1, 17) to (start + 0, 34)
+    = (((c0 + c5) + c6) - (c1 + c8))
+- Code(Expression(28, Sub)) at (prev + 0, 34) to (start + 0, 35)
+    = ((c0 + c5) - (c1 + c8))
 - Code(Zero) at (prev + 1, 20) to (start + 1, 14)
-- Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15)
-- Code(Expression(34, Add)) at (prev + 1, 5) to (start + 0, 6)
-    = ((c9 + (((((c3 + Zero) + (c4 + Zero)) - c6) - Zero) - c4)) + c6)
-Highest counter ID seen: c9
+- Code(Counter(8)) at (prev + 3, 9) to (start + 0, 15)
+- Code(Expression(31, Sub)) at (prev + 1, 5) to (start + 0, 6)
+    = (((c0 + c4) + c5) - c1)
+Highest counter ID seen: c8
 
 Function name: <loops_branches::DisplayTest as core::fmt::Display>::fmt
-Raw bytes (230): 0x[01, 01, 2b, 01, 00, 02, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, a7, 01, ab, 01, 00, 0d, 00, 15, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9a, 01, 00, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9a, 01, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 93, 01, 25, 96, 01, 19, 9a, 01, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 06, 01, 0d, 00, 0e, 02, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 9e, 01, 02, 0d, 00, 0e, a3, 01, 00, 12, 00, 17, 9e, 01, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 9a, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 4a, 01, 11, 00, 12, 9a, 01, 01, 11, 00, 22, 96, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, 8f, 01, 01, 05, 00, 06]
+Raw bytes (152): 0x[01, 01, 18, 01, 00, 01, 00, 23, 15, 27, 11, 00, 0d, 27, 11, 00, 0d, 23, 15, 27, 11, 00, 0d, 4b, 15, 4f, 11, 00, 0d, 4b, 43, 4f, 11, 00, 0d, 15, 00, 4b, 15, 4f, 11, 00, 0d, 5f, 15, 00, 11, 5f, 21, 00, 11, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 06, 01, 0d, 00, 0e, 02, 01, 0d, 00, 1e, 21, 00, 1e, 00, 1f, 1e, 02, 0d, 00, 0e, 23, 00, 12, 00, 17, 1e, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 46, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 36, 01, 11, 00, 12, 46, 01, 11, 00, 22, 52, 00, 22, 00, 23, 15, 03, 09, 00, 0f, 5b, 01, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 43
+Number of expressions: 24
 - expression 0 operands: lhs = Counter(0), rhs = Zero
-- expression 1 operands: lhs = Expression(0, Sub), rhs = Zero
-- expression 2 operands: lhs = Expression(40, Add), rhs = Counter(6)
-- expression 3 operands: lhs = Expression(41, Add), rhs = Expression(42, Add)
+- expression 1 operands: lhs = Counter(0), rhs = Zero
+- expression 2 operands: lhs = Expression(8, Add), rhs = Counter(5)
+- expression 3 operands: lhs = Expression(9, Add), rhs = Counter(4)
 - expression 4 operands: lhs = Zero, rhs = Counter(3)
-- expression 5 operands: lhs = Zero, rhs = Counter(5)
-- expression 6 operands: lhs = Expression(41, Add), rhs = Expression(42, Add)
-- expression 7 operands: lhs = Zero, rhs = Counter(3)
-- expression 8 operands: lhs = Zero, rhs = Counter(5)
-- expression 9 operands: lhs = Expression(40, Add), rhs = Counter(6)
-- expression 10 operands: lhs = Expression(41, Add), rhs = Expression(42, Add)
-- expression 11 operands: lhs = Zero, rhs = Counter(3)
-- expression 12 operands: lhs = Zero, rhs = Counter(5)
-- expression 13 operands: lhs = Expression(39, Sub), rhs = Zero
-- expression 14 operands: lhs = Expression(40, Add), rhs = Counter(6)
-- expression 15 operands: lhs = Expression(41, Add), rhs = Expression(42, Add)
-- expression 16 operands: lhs = Zero, rhs = Counter(3)
-- expression 17 operands: lhs = Zero, rhs = Counter(5)
-- expression 18 operands: lhs = Expression(38, Sub), rhs = Zero
-- expression 19 operands: lhs = Expression(39, Sub), rhs = Zero
-- expression 20 operands: lhs = Expression(40, Add), rhs = Counter(6)
-- expression 21 operands: lhs = Expression(41, Add), rhs = Expression(42, Add)
-- expression 22 operands: lhs = Zero, rhs = Counter(3)
-- expression 23 operands: lhs = Zero, rhs = Counter(5)
-- expression 24 operands: lhs = Expression(39, Sub), rhs = Zero
-- expression 25 operands: lhs = Expression(40, Add), rhs = Counter(6)
-- expression 26 operands: lhs = Expression(41, Add), rhs = Expression(42, Add)
-- expression 27 operands: lhs = Zero, rhs = Counter(3)
-- expression 28 operands: lhs = Zero, rhs = Counter(5)
-- expression 29 operands: lhs = Expression(38, Sub), rhs = Counter(5)
-- expression 30 operands: lhs = Expression(39, Sub), rhs = Zero
-- expression 31 operands: lhs = Expression(40, Add), rhs = Counter(6)
-- expression 32 operands: lhs = Expression(41, Add), rhs = Expression(42, Add)
-- expression 33 operands: lhs = Zero, rhs = Counter(3)
-- expression 34 operands: lhs = Zero, rhs = Counter(5)
-- expression 35 operands: lhs = Expression(36, Add), rhs = Counter(9)
-- expression 36 operands: lhs = Expression(37, Sub), rhs = Counter(6)
-- expression 37 operands: lhs = Expression(38, Sub), rhs = Counter(5)
-- expression 38 operands: lhs = Expression(39, Sub), rhs = Zero
-- expression 39 operands: lhs = Expression(40, Add), rhs = Counter(6)
-- expression 40 operands: lhs = Expression(41, Add), rhs = Expression(42, Add)
-- expression 41 operands: lhs = Zero, rhs = Counter(3)
-- expression 42 operands: lhs = Zero, rhs = Counter(5)
+- expression 5 operands: lhs = Expression(9, Add), rhs = Counter(4)
+- expression 6 operands: lhs = Zero, rhs = Counter(3)
+- expression 7 operands: lhs = Expression(8, Add), rhs = Counter(5)
+- expression 8 operands: lhs = Expression(9, Add), rhs = Counter(4)
+- expression 9 operands: lhs = Zero, rhs = Counter(3)
+- expression 10 operands: lhs = Expression(18, Add), rhs = Counter(5)
+- expression 11 operands: lhs = Expression(19, Add), rhs = Counter(4)
+- expression 12 operands: lhs = Zero, rhs = Counter(3)
+- expression 13 operands: lhs = Expression(18, Add), rhs = Expression(16, Add)
+- expression 14 operands: lhs = Expression(19, Add), rhs = Counter(4)
+- expression 15 operands: lhs = Zero, rhs = Counter(3)
+- expression 16 operands: lhs = Counter(5), rhs = Zero
+- expression 17 operands: lhs = Expression(18, Add), rhs = Counter(5)
+- expression 18 operands: lhs = Expression(19, Add), rhs = Counter(4)
+- expression 19 operands: lhs = Zero, rhs = Counter(3)
+- expression 20 operands: lhs = Expression(23, Add), rhs = Counter(5)
+- expression 21 operands: lhs = Zero, rhs = Counter(4)
+- expression 22 operands: lhs = Expression(23, Add), rhs = Counter(8)
+- expression 23 operands: lhs = Zero, rhs = Counter(4)
 Number of file 0 mappings: 20
 - Code(Counter(0)) at (prev + 34, 5) to (start + 1, 17)
 - Code(Zero) at (prev + 1, 18) to (start + 1, 10)
@@ -133,31 +106,31 @@ Number of file 0 mappings: 20
 - Code(Zero) at (prev + 1, 23) to (start + 0, 27)
 - Code(Zero) at (prev + 0, 28) to (start + 0, 30)
 - Code(Expression(1, Sub)) at (prev + 1, 13) to (start + 0, 14)
-    = ((c0 - Zero) - Zero)
+    = (c0 - Zero)
 - Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 30)
     = (c0 - Zero)
-- Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31)
-- Code(Expression(39, Sub)) at (prev + 2, 13) to (start + 0, 14)
-    = (((Zero + c3) + (Zero + c5)) - c6)
-- Code(Expression(40, Add)) at (prev + 0, 18) to (start + 0, 23)
-    = ((Zero + c3) + (Zero + c5))
-- Code(Expression(39, Sub)) at (prev + 1, 16) to (start + 0, 21)
-    = (((Zero + c3) + (Zero + c5)) - c6)
+- Code(Counter(8)) at (prev + 0, 30) to (start + 0, 31)
+- Code(Expression(7, Sub)) at (prev + 2, 13) to (start + 0, 14)
+    = (((Zero + c3) + c4) - c5)
+- Code(Expression(8, Add)) at (prev + 0, 18) to (start + 0, 23)
+    = ((Zero + c3) + c4)
+- Code(Expression(7, Sub)) at (prev + 1, 16) to (start + 0, 21)
+    = (((Zero + c3) + c4) - c5)
 - Code(Zero) at (prev + 0, 22) to (start + 1, 14)
-- Code(Expression(38, Sub)) at (prev + 2, 20) to (start + 0, 25)
-    = ((((Zero + c3) + (Zero + c5)) - c6) - Zero)
+- Code(Expression(17, Sub)) at (prev + 2, 20) to (start + 0, 25)
+    = (((Zero + c3) + c4) - c5)
 - Code(Zero) at (prev + 1, 27) to (start + 0, 31)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 34)
-- Code(Expression(18, Sub)) at (prev + 1, 17) to (start + 0, 18)
-    = (((((Zero + c3) + (Zero + c5)) - c6) - Zero) - Zero)
-- Code(Expression(38, Sub)) at (prev + 1, 17) to (start + 0, 34)
-    = ((((Zero + c3) + (Zero + c5)) - c6) - Zero)
-- Code(Expression(37, Sub)) at (prev + 0, 34) to (start + 0, 35)
-    = (((((Zero + c3) + (Zero + c5)) - c6) - Zero) - c5)
-- Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15)
-- Code(Expression(35, Add)) at (prev + 1, 5) to (start + 0, 6)
-    = (((((((Zero + c3) + (Zero + c5)) - c6) - Zero) - c5) + c6) + c9)
-Highest counter ID seen: c9
+- Code(Expression(13, Sub)) at (prev + 1, 17) to (start + 0, 18)
+    = (((Zero + c3) + c4) - (c5 + Zero))
+- Code(Expression(17, Sub)) at (prev + 1, 17) to (start + 0, 34)
+    = (((Zero + c3) + c4) - c5)
+- Code(Expression(20, Sub)) at (prev + 0, 34) to (start + 0, 35)
+    = ((Zero + c4) - c5)
+- Code(Counter(5)) at (prev + 3, 9) to (start + 0, 15)
+- Code(Expression(22, Add)) at (prev + 1, 5) to (start + 0, 6)
+    = ((Zero + c4) + c8)
+Highest counter ID seen: c8
 
 Function name: loops_branches::main
 Raw bytes (9): 0x[01, 01, 00, 01, 01, 37, 01, 05, 02]
diff --git a/tests/coverage/mcdc/condition-limit.cov-map b/tests/coverage/mcdc/condition-limit.cov-map
index e3f5b49d363..19716878600 100644
--- a/tests/coverage/mcdc/condition-limit.cov-map
+++ b/tests/coverage/mcdc/condition-limit.cov-map
@@ -1,52 +1,54 @@
 Function name: condition_limit::accept_7_conditions
-Raw bytes (232): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 12, 01, 07, 01, 02, 09, 28, 08, 07, 02, 08, 00, 27, 30, 05, 02, 01, 07, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 7a, 1d, 07, 06, 00, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 30, 76, 19, 06, 05, 00, 00, 12, 00, 13, 76, 00, 17, 00, 18, 30, 72, 15, 05, 04, 00, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 30, 6e, 11, 04, 03, 00, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 30, 6a, 0d, 03, 02, 00, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 30, 21, 09, 02, 00, 00, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 05, 00, 06, 97, 01, 01, 01, 00, 02]
+Raw bytes (237): 0x[01, 01, 2e, 01, 05, 05, 09, 05, 09, 05, 7b, 09, 0d, 05, 7b, 09, 0d, 05, 77, 7b, 11, 09, 0d, 05, 77, 7b, 11, 09, 0d, 05, 73, 77, 15, 7b, 11, 09, 0d, 05, 73, 77, 15, 7b, 11, 09, 0d, 05, 6f, 73, 19, 77, 15, 7b, 11, 09, 0d, 05, 6f, 73, 19, 77, 15, 7b, 11, 09, 0d, 83, 01, 05, a7, 01, 21, ab, 01, 19, af, 01, 15, b3, 01, 11, b7, 01, 0d, 01, 09, 9f, 01, 05, a3, 01, 21, a7, 01, 1d, ab, 01, 19, af, 01, 15, b3, 01, 11, b7, 01, 0d, 01, 09, 12, 01, 07, 01, 02, 09, 28, 08, 07, 02, 08, 00, 27, 30, 05, 02, 01, 07, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0a, 09, 07, 06, 00, 00, 0d, 00, 0e, 0a, 00, 12, 00, 13, 30, 16, 0d, 06, 05, 00, 00, 12, 00, 13, 16, 00, 17, 00, 18, 30, 2a, 11, 05, 04, 00, 00, 17, 00, 18, 2a, 00, 1c, 00, 1d, 30, 46, 15, 04, 03, 00, 00, 1c, 00, 1d, 46, 00, 21, 00, 22, 30, 6a, 19, 03, 02, 00, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 30, 1d, 21, 02, 00, 00, 00, 26, 00, 27, 1d, 00, 28, 02, 06, 7e, 02, 05, 00, 06, 9a, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 44
+Number of expressions: 46
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(1), rhs = Counter(7)
-- expression 2 operands: lhs = Counter(1), rhs = Counter(7)
-- expression 3 operands: lhs = Expression(30, Sub), rhs = Counter(6)
-- expression 4 operands: lhs = Counter(1), rhs = Counter(7)
-- expression 5 operands: lhs = Expression(30, Sub), rhs = Counter(6)
-- expression 6 operands: lhs = Counter(1), rhs = Counter(7)
-- expression 7 operands: lhs = Expression(29, Sub), rhs = Counter(5)
-- expression 8 operands: lhs = Expression(30, Sub), rhs = Counter(6)
-- expression 9 operands: lhs = Counter(1), rhs = Counter(7)
-- expression 10 operands: lhs = Expression(29, Sub), rhs = Counter(5)
-- expression 11 operands: lhs = Expression(30, Sub), rhs = Counter(6)
-- expression 12 operands: lhs = Counter(1), rhs = Counter(7)
-- expression 13 operands: lhs = Expression(28, Sub), rhs = Counter(4)
-- expression 14 operands: lhs = Expression(29, Sub), rhs = Counter(5)
-- expression 15 operands: lhs = Expression(30, Sub), rhs = Counter(6)
-- expression 16 operands: lhs = Counter(1), rhs = Counter(7)
-- expression 17 operands: lhs = Expression(28, Sub), rhs = Counter(4)
-- expression 18 operands: lhs = Expression(29, Sub), rhs = Counter(5)
-- expression 19 operands: lhs = Expression(30, Sub), rhs = Counter(6)
-- expression 20 operands: lhs = Counter(1), rhs = Counter(7)
-- expression 21 operands: lhs = Expression(27, Sub), rhs = Counter(3)
-- expression 22 operands: lhs = Expression(28, Sub), rhs = Counter(4)
-- expression 23 operands: lhs = Expression(29, Sub), rhs = Counter(5)
-- expression 24 operands: lhs = Expression(30, Sub), rhs = Counter(6)
-- expression 25 operands: lhs = Counter(1), rhs = Counter(7)
-- expression 26 operands: lhs = Expression(27, Sub), rhs = Counter(3)
-- expression 27 operands: lhs = Expression(28, Sub), rhs = Counter(4)
-- expression 28 operands: lhs = Expression(29, Sub), rhs = Counter(5)
-- expression 29 operands: lhs = Expression(30, Sub), rhs = Counter(6)
-- expression 30 operands: lhs = Counter(1), rhs = Counter(7)
-- expression 31 operands: lhs = Expression(39, Add), rhs = Expression(0, Sub)
-- expression 32 operands: lhs = Expression(40, Add), rhs = Counter(7)
-- expression 33 operands: lhs = Expression(41, Add), rhs = Counter(6)
-- expression 34 operands: lhs = Expression(42, Add), rhs = Counter(5)
-- expression 35 operands: lhs = Expression(43, Add), rhs = Counter(4)
-- expression 36 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 37 operands: lhs = Counter(8), rhs = Expression(38, Add)
-- expression 38 operands: lhs = Expression(39, Add), rhs = Expression(0, Sub)
-- expression 39 operands: lhs = Expression(40, Add), rhs = Counter(7)
-- expression 40 operands: lhs = Expression(41, Add), rhs = Counter(6)
-- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(5)
-- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(4)
-- expression 43 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 3 operands: lhs = Counter(1), rhs = Expression(30, Add)
+- expression 4 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 5 operands: lhs = Counter(1), rhs = Expression(30, Add)
+- expression 6 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 7 operands: lhs = Counter(1), rhs = Expression(29, Add)
+- expression 8 operands: lhs = Expression(30, Add), rhs = Counter(4)
+- expression 9 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 10 operands: lhs = Counter(1), rhs = Expression(29, Add)
+- expression 11 operands: lhs = Expression(30, Add), rhs = Counter(4)
+- expression 12 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 13 operands: lhs = Counter(1), rhs = Expression(28, Add)
+- expression 14 operands: lhs = Expression(29, Add), rhs = Counter(5)
+- expression 15 operands: lhs = Expression(30, Add), rhs = Counter(4)
+- expression 16 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 17 operands: lhs = Counter(1), rhs = Expression(28, Add)
+- expression 18 operands: lhs = Expression(29, Add), rhs = Counter(5)
+- expression 19 operands: lhs = Expression(30, Add), rhs = Counter(4)
+- expression 20 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 21 operands: lhs = Counter(1), rhs = Expression(27, Add)
+- expression 22 operands: lhs = Expression(28, Add), rhs = Counter(6)
+- expression 23 operands: lhs = Expression(29, Add), rhs = Counter(5)
+- expression 24 operands: lhs = Expression(30, Add), rhs = Counter(4)
+- expression 25 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 26 operands: lhs = Counter(1), rhs = Expression(27, Add)
+- expression 27 operands: lhs = Expression(28, Add), rhs = Counter(6)
+- expression 28 operands: lhs = Expression(29, Add), rhs = Counter(5)
+- expression 29 operands: lhs = Expression(30, Add), rhs = Counter(4)
+- expression 30 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 31 operands: lhs = Expression(32, Add), rhs = Counter(1)
+- expression 32 operands: lhs = Expression(41, Add), rhs = Counter(8)
+- expression 33 operands: lhs = Expression(42, Add), rhs = Counter(6)
+- expression 34 operands: lhs = Expression(43, Add), rhs = Counter(5)
+- expression 35 operands: lhs = Expression(44, Add), rhs = Counter(4)
+- expression 36 operands: lhs = Expression(45, Add), rhs = Counter(3)
+- expression 37 operands: lhs = Counter(0), rhs = Counter(2)
+- expression 38 operands: lhs = Expression(39, Add), rhs = Counter(1)
+- expression 39 operands: lhs = Expression(40, Add), rhs = Counter(8)
+- expression 40 operands: lhs = Expression(41, Add), rhs = Counter(7)
+- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(6)
+- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(5)
+- expression 43 operands: lhs = Expression(44, Add), rhs = Counter(4)
+- expression 44 operands: lhs = Expression(45, Add), rhs = Counter(3)
+- expression 45 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 18
 - Code(Counter(0)) at (prev + 7, 1) to (start + 2, 9)
 - MCDCDecision { bitmap_idx: 8, conditions_num: 7 } at (prev + 2, 8) to (start + 0, 39)
@@ -54,38 +56,38 @@ Number of file 0 mappings: 18
     true  = c1
     false = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14)
-- MCDCBranch { true: Expression(30, Sub), false: Counter(7), condition_id: 7, true_next_id: 6, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
-    true  = (c1 - c7)
-    false = c7
-- Code(Expression(30, Sub)) at (prev + 0, 18) to (start + 0, 19)
-    = (c1 - c7)
-- MCDCBranch { true: Expression(29, Sub), false: Counter(6), condition_id: 6, true_next_id: 5, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19)
-    true  = ((c1 - c7) - c6)
-    false = c6
-- Code(Expression(29, Sub)) at (prev + 0, 23) to (start + 0, 24)
-    = ((c1 - c7) - c6)
-- MCDCBranch { true: Expression(28, Sub), false: Counter(5), condition_id: 5, true_next_id: 4, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24)
-    true  = (((c1 - c7) - c6) - c5)
-    false = c5
-- Code(Expression(28, Sub)) at (prev + 0, 28) to (start + 0, 29)
-    = (((c1 - c7) - c6) - c5)
-- MCDCBranch { true: Expression(27, Sub), false: Counter(4), condition_id: 4, true_next_id: 3, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29)
-    true  = ((((c1 - c7) - c6) - c5) - c4)
-    false = c4
-- Code(Expression(27, Sub)) at (prev + 0, 33) to (start + 0, 34)
-    = ((((c1 - c7) - c6) - c5) - c4)
-- MCDCBranch { true: Expression(26, Sub), false: Counter(3), condition_id: 3, true_next_id: 2, false_next_id: 0 } at (prev + 0, 33) to (start + 0, 34)
-    true  = (((((c1 - c7) - c6) - c5) - c4) - c3)
+- MCDCBranch { true: Expression(2, Sub), false: Counter(2), condition_id: 7, true_next_id: 6, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
+    true  = (c1 - c2)
+    false = c2
+- Code(Expression(2, Sub)) at (prev + 0, 18) to (start + 0, 19)
+    = (c1 - c2)
+- MCDCBranch { true: Expression(5, Sub), false: Counter(3), condition_id: 6, true_next_id: 5, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19)
+    true  = (c1 - (c2 + c3))
     false = c3
+- Code(Expression(5, Sub)) at (prev + 0, 23) to (start + 0, 24)
+    = (c1 - (c2 + c3))
+- MCDCBranch { true: Expression(10, Sub), false: Counter(4), condition_id: 5, true_next_id: 4, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24)
+    true  = (c1 - ((c2 + c3) + c4))
+    false = c4
+- Code(Expression(10, Sub)) at (prev + 0, 28) to (start + 0, 29)
+    = (c1 - ((c2 + c3) + c4))
+- MCDCBranch { true: Expression(17, Sub), false: Counter(5), condition_id: 4, true_next_id: 3, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29)
+    true  = (c1 - (((c2 + c3) + c4) + c5))
+    false = c5
+- Code(Expression(17, Sub)) at (prev + 0, 33) to (start + 0, 34)
+    = (c1 - (((c2 + c3) + c4) + c5))
+- MCDCBranch { true: Expression(26, Sub), false: Counter(6), condition_id: 3, true_next_id: 2, false_next_id: 0 } at (prev + 0, 33) to (start + 0, 34)
+    true  = (c1 - ((((c2 + c3) + c4) + c5) + c6))
+    false = c6
 - Code(Expression(26, Sub)) at (prev + 0, 38) to (start + 0, 39)
-    = (((((c1 - c7) - c6) - c5) - c4) - c3)
-- MCDCBranch { true: Counter(8), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 38) to (start + 0, 39)
-    true  = c8
-    false = c2
-- Code(Counter(8)) at (prev + 0, 40) to (start + 2, 6)
-- Code(Expression(38, Add)) at (prev + 2, 5) to (start + 0, 6)
-    = ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1))
-- Code(Expression(37, Add)) at (prev + 1, 1) to (start + 0, 2)
-    = (c8 + ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1)))
+    = (c1 - ((((c2 + c3) + c4) + c5) + c6))
+- MCDCBranch { true: Counter(7), false: Counter(8), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 38) to (start + 0, 39)
+    true  = c7
+    false = c8
+- Code(Counter(7)) at (prev + 0, 40) to (start + 2, 6)
+- Code(Expression(31, Sub)) at (prev + 2, 5) to (start + 0, 6)
+    = (((((((c0 + c2) + c3) + c4) + c5) + c6) + c8) - c1)
+- Code(Expression(38, Sub)) at (prev + 1, 1) to (start + 0, 2)
+    = ((((((((c0 + c2) + c3) + c4) + c5) + c6) + c7) + c8) - c1)
 Highest counter ID seen: c8
 
diff --git a/tests/coverage/mcdc/if.cov-map b/tests/coverage/mcdc/if.cov-map
index c0e7d08bb02..acb8aac63de 100644
--- a/tests/coverage/mcdc/if.cov-map
+++ b/tests/coverage/mcdc/if.cov-map
@@ -1,12 +1,14 @@
 Function name: if::mcdc_check_a
-Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 0f, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (68): 0x[01, 01, 06, 01, 05, 0b, 05, 01, 0d, 13, 05, 17, 0d, 01, 09, 08, 01, 0f, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 0d, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 06, 02, 0c, 02, 06, 0e, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 4
+Number of expressions: 6
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub)
-- expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
-- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(1)
+- expression 2 operands: lhs = Counter(0), rhs = Counter(3)
+- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(1)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3)
+- expression 5 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 8
 - Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
@@ -14,25 +16,27 @@ Number of file 0 mappings: 8
     true  = c1
     false = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14)
-- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
-    true  = c3
-    false = c2
-- Code(Counter(3)) at (prev + 0, 15) to (start + 2, 6)
-- Code(Expression(3, Add)) at (prev + 2, 12) to (start + 2, 6)
-    = (c2 + (c0 - c1))
-- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2)
-    = (c3 + (c2 + (c0 - c1)))
+- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
+    true  = c2
+    false = c3
+- Code(Counter(2)) at (prev + 0, 15) to (start + 2, 6)
+- Code(Expression(1, Sub)) at (prev + 2, 12) to (start + 2, 6)
+    = ((c0 + c3) - c1)
+- Code(Expression(3, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = (((c0 + c2) + c3) - c1)
 Highest counter ID seen: c3
 
 Function name: if::mcdc_check_b
-Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 17, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (68): 0x[01, 01, 06, 01, 05, 0b, 05, 01, 0d, 13, 05, 17, 0d, 01, 09, 08, 01, 17, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 0d, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 06, 02, 0c, 02, 06, 0e, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 4
+Number of expressions: 6
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub)
-- expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
-- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(1)
+- expression 2 operands: lhs = Counter(0), rhs = Counter(3)
+- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(1)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3)
+- expression 5 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 8
 - Code(Counter(0)) at (prev + 23, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
@@ -40,25 +44,27 @@ Number of file 0 mappings: 8
     true  = c1
     false = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14)
-- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
-    true  = c3
-    false = c2
-- Code(Counter(3)) at (prev + 0, 15) to (start + 2, 6)
-- Code(Expression(3, Add)) at (prev + 2, 12) to (start + 2, 6)
-    = (c2 + (c0 - c1))
-- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2)
-    = (c3 + (c2 + (c0 - c1)))
+- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
+    true  = c2
+    false = c3
+- Code(Counter(2)) at (prev + 0, 15) to (start + 2, 6)
+- Code(Expression(1, Sub)) at (prev + 2, 12) to (start + 2, 6)
+    = ((c0 + c3) - c1)
+- Code(Expression(3, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = (((c0 + c2) + c3) - c1)
 Highest counter ID seen: c3
 
 Function name: if::mcdc_check_both
-Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 1f, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (68): 0x[01, 01, 06, 01, 05, 0b, 05, 01, 0d, 13, 05, 17, 0d, 01, 09, 08, 01, 1f, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 0d, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 06, 02, 0c, 02, 06, 0e, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 4
+Number of expressions: 6
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub)
-- expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
-- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(1)
+- expression 2 operands: lhs = Counter(0), rhs = Counter(3)
+- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(1)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3)
+- expression 5 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 8
 - Code(Counter(0)) at (prev + 31, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
@@ -66,25 +72,27 @@ Number of file 0 mappings: 8
     true  = c1
     false = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14)
-- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
-    true  = c3
-    false = c2
-- Code(Counter(3)) at (prev + 0, 15) to (start + 2, 6)
-- Code(Expression(3, Add)) at (prev + 2, 12) to (start + 2, 6)
-    = (c2 + (c0 - c1))
-- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2)
-    = (c3 + (c2 + (c0 - c1)))
+- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
+    true  = c2
+    false = c3
+- Code(Counter(2)) at (prev + 0, 15) to (start + 2, 6)
+- Code(Expression(1, Sub)) at (prev + 2, 12) to (start + 2, 6)
+    = ((c0 + c3) - c1)
+- Code(Expression(3, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = (((c0 + c2) + c3) - c1)
 Highest counter ID seen: c3
 
 Function name: if::mcdc_check_neither
-Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 07, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (68): 0x[01, 01, 06, 01, 05, 0b, 05, 01, 0d, 13, 05, 17, 0d, 01, 09, 08, 01, 07, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 09, 0d, 02, 00, 00, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 06, 02, 0c, 02, 06, 0e, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 4
+Number of expressions: 6
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub)
-- expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
-- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(1)
+- expression 2 operands: lhs = Counter(0), rhs = Counter(3)
+- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(1)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3)
+- expression 5 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 8
 - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
@@ -92,29 +100,32 @@ Number of file 0 mappings: 8
     true  = c1
     false = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14)
-- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
-    true  = c3
-    false = c2
-- Code(Counter(3)) at (prev + 0, 15) to (start + 2, 6)
-- Code(Expression(3, Add)) at (prev + 2, 12) to (start + 2, 6)
-    = (c2 + (c0 - c1))
-- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2)
-    = (c3 + (c2 + (c0 - c1)))
+- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
+    true  = c2
+    false = c3
+- Code(Counter(2)) at (prev + 0, 15) to (start + 2, 6)
+- Code(Expression(1, Sub)) at (prev + 2, 12) to (start + 2, 6)
+    = ((c0 + c3) - c1)
+- Code(Expression(3, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = (((c0 + c2) + c3) - c1)
 Highest counter ID seen: c3
 
 Function name: if::mcdc_check_not_tree_decision
-Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 31, 01, 03, 0a, 28, 05, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
+Raw bytes (93): 0x[01, 01, 0b, 01, 05, 01, 2b, 05, 09, 05, 09, 17, 2b, 01, 11, 05, 09, 23, 2b, 27, 11, 01, 0d, 05, 09, 0a, 01, 31, 01, 03, 0a, 28, 05, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 06, 03, 02, 00, 00, 0e, 00, 0f, 2b, 00, 14, 00, 15, 30, 0d, 11, 02, 00, 00, 00, 14, 00, 15, 0d, 00, 16, 02, 06, 12, 02, 0c, 02, 06, 1e, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 8
+Number of expressions: 11
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(2)
+- expression 1 operands: lhs = Counter(0), rhs = Expression(10, Add)
 - expression 2 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 3 operands: lhs = Counter(3), rhs = Expression(7, Sub)
-- expression 4 operands: lhs = Expression(0, Sub), rhs = Counter(2)
-- expression 5 operands: lhs = Counter(4), rhs = Expression(6, Add)
-- expression 6 operands: lhs = Counter(3), rhs = Expression(7, Sub)
-- expression 7 operands: lhs = Expression(0, Sub), rhs = Counter(2)
+- expression 3 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Expression(10, Add)
+- expression 5 operands: lhs = Counter(0), rhs = Counter(4)
+- expression 6 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 7 operands: lhs = Expression(8, Add), rhs = Expression(10, Add)
+- expression 8 operands: lhs = Expression(9, Add), rhs = Counter(4)
+- expression 9 operands: lhs = Counter(0), rhs = Counter(3)
+- expression 10 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 10
 - Code(Counter(0)) at (prev + 49, 1) to (start + 3, 10)
 - MCDCDecision { bitmap_idx: 5, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21)
@@ -123,34 +134,36 @@ Number of file 0 mappings: 10
     false = (c0 - c1)
 - Code(Expression(0, Sub)) at (prev + 0, 14) to (start + 0, 15)
     = (c0 - c1)
-- MCDCBranch { true: Counter(2), false: Expression(7, Sub), condition_id: 3, true_next_id: 2, false_next_id: 0 } at (prev + 0, 14) to (start + 0, 15)
+- MCDCBranch { true: Counter(2), false: Expression(1, Sub), condition_id: 3, true_next_id: 2, false_next_id: 0 } at (prev + 0, 14) to (start + 0, 15)
     true  = c2
-    false = ((c0 - c1) - c2)
-- Code(Expression(2, Add)) at (prev + 0, 20) to (start + 0, 21)
+    false = (c0 - (c1 + c2))
+- Code(Expression(10, Add)) at (prev + 0, 20) to (start + 0, 21)
     = (c1 + c2)
-- MCDCBranch { true: Counter(4), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 20) to (start + 0, 21)
-    true  = c4
-    false = c3
-- Code(Counter(4)) at (prev + 0, 22) to (start + 2, 6)
-- Code(Expression(6, Add)) at (prev + 2, 12) to (start + 2, 6)
-    = (c3 + ((c0 - c1) - c2))
-- Code(Expression(5, Add)) at (prev + 3, 1) to (start + 0, 2)
-    = (c4 + (c3 + ((c0 - c1) - c2)))
+- MCDCBranch { true: Counter(3), false: Counter(4), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 20) to (start + 0, 21)
+    true  = c3
+    false = c4
+- Code(Counter(3)) at (prev + 0, 22) to (start + 2, 6)
+- Code(Expression(4, Sub)) at (prev + 2, 12) to (start + 2, 6)
+    = ((c0 + c4) - (c1 + c2))
+- Code(Expression(7, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = (((c0 + c3) + c4) - (c1 + c2))
 Highest counter ID seen: c4
 
 Function name: if::mcdc_check_tree_decision
-Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 27, 01, 03, 09, 28, 04, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
+Raw bytes (91): 0x[01, 01, 0a, 01, 05, 05, 09, 05, 09, 09, 0d, 17, 05, 01, 11, 1f, 05, 23, 11, 27, 0d, 01, 09, 0a, 01, 27, 01, 03, 09, 28, 04, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 09, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 0d, 11, 03, 00, 00, 00, 13, 00, 14, 0f, 00, 16, 02, 06, 12, 02, 0c, 02, 06, 1a, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 8
+Number of expressions: 10
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(1), rhs = Counter(3)
-- expression 2 operands: lhs = Counter(1), rhs = Counter(3)
-- expression 3 operands: lhs = Counter(3), rhs = Counter(4)
-- expression 4 operands: lhs = Counter(2), rhs = Expression(0, Sub)
-- expression 5 operands: lhs = Expression(6, Add), rhs = Expression(7, Add)
-- expression 6 operands: lhs = Counter(3), rhs = Counter(4)
-- expression 7 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 3 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(1)
+- expression 5 operands: lhs = Counter(0), rhs = Counter(4)
+- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(1)
+- expression 7 operands: lhs = Expression(8, Add), rhs = Counter(4)
+- expression 8 operands: lhs = Expression(9, Add), rhs = Counter(3)
+- expression 9 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 10
 - Code(Counter(0)) at (prev + 39, 1) to (start + 3, 9)
 - MCDCDecision { bitmap_idx: 4, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21)
@@ -158,40 +171,43 @@ Number of file 0 mappings: 10
     true  = c1
     false = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 14) to (start + 0, 15)
-- MCDCBranch { true: Counter(3), false: Expression(2, Sub), condition_id: 2, true_next_id: 0, false_next_id: 3 } at (prev + 0, 14) to (start + 0, 15)
-    true  = c3
-    false = (c1 - c3)
+- MCDCBranch { true: Counter(2), false: Expression(2, Sub), condition_id: 2, true_next_id: 0, false_next_id: 3 } at (prev + 0, 14) to (start + 0, 15)
+    true  = c2
+    false = (c1 - c2)
 - Code(Expression(2, Sub)) at (prev + 0, 19) to (start + 0, 20)
-    = (c1 - c3)
-- MCDCBranch { true: Counter(4), false: Counter(2), condition_id: 3, true_next_id: 0, false_next_id: 0 } at (prev + 0, 19) to (start + 0, 20)
-    true  = c4
-    false = c2
-- Code(Expression(6, Add)) at (prev + 0, 22) to (start + 2, 6)
-    = (c3 + c4)
-- Code(Expression(7, Add)) at (prev + 2, 12) to (start + 2, 6)
-    = (c2 + (c0 - c1))
-- Code(Expression(5, Add)) at (prev + 3, 1) to (start + 0, 2)
-    = ((c3 + c4) + (c2 + (c0 - c1)))
+    = (c1 - c2)
+- MCDCBranch { true: Counter(3), false: Counter(4), condition_id: 3, true_next_id: 0, false_next_id: 0 } at (prev + 0, 19) to (start + 0, 20)
+    true  = c3
+    false = c4
+- Code(Expression(3, Add)) at (prev + 0, 22) to (start + 2, 6)
+    = (c2 + c3)
+- Code(Expression(4, Sub)) at (prev + 2, 12) to (start + 2, 6)
+    = ((c0 + c4) - c1)
+- Code(Expression(6, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = ((((c0 + c2) + c3) + c4) - c1)
 Highest counter ID seen: c4
 
 Function name: if::mcdc_nested_if
-Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3b, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 06, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 09, 00, 0a, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02]
+Raw bytes (130): 0x[01, 01, 10, 01, 05, 01, 3f, 05, 09, 05, 09, 3f, 0d, 05, 09, 3f, 0d, 05, 09, 0d, 15, 01, 3f, 05, 09, 33, 3f, 37, 15, 3b, 11, 01, 0d, 05, 09, 0e, 01, 3b, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 26, 02, 00, 00, 00, 0d, 00, 0e, 3f, 01, 09, 01, 0d, 28, 06, 02, 01, 0c, 00, 12, 30, 1a, 0d, 01, 02, 00, 00, 0c, 00, 0d, 1a, 00, 11, 00, 12, 30, 11, 15, 02, 00, 00, 00, 11, 00, 12, 11, 00, 13, 02, 0a, 23, 02, 09, 00, 0a, 26, 01, 0c, 02, 06, 2e, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 13
+Number of expressions: 16
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(2)
+- expression 1 operands: lhs = Counter(0), rhs = Expression(15, Add)
 - expression 2 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 3 operands: lhs = Expression(6, Add), rhs = Counter(5)
-- expression 4 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(5)
-- expression 6 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 7 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 8 operands: lhs = Expression(0, Sub), rhs = Counter(2)
-- expression 9 operands: lhs = Expression(10, Add), rhs = Expression(12, Sub)
-- expression 10 operands: lhs = Counter(3), rhs = Expression(11, Add)
-- expression 11 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 12 operands: lhs = Expression(0, Sub), rhs = Counter(2)
+- expression 3 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 4 operands: lhs = Expression(15, Add), rhs = Counter(3)
+- expression 5 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 6 operands: lhs = Expression(15, Add), rhs = Counter(3)
+- expression 7 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 8 operands: lhs = Counter(3), rhs = Counter(5)
+- expression 9 operands: lhs = Counter(0), rhs = Expression(15, Add)
+- expression 10 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 11 operands: lhs = Expression(12, Add), rhs = Expression(15, Add)
+- expression 12 operands: lhs = Expression(13, Add), rhs = Counter(5)
+- expression 13 operands: lhs = Expression(14, Add), rhs = Counter(4)
+- expression 14 operands: lhs = Counter(0), rhs = Counter(3)
+- expression 15 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 14
 - Code(Counter(0)) at (prev + 59, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
@@ -200,26 +216,26 @@ Number of file 0 mappings: 14
     false = (c0 - c1)
 - Code(Expression(0, Sub)) at (prev + 0, 13) to (start + 0, 14)
     = (c0 - c1)
-- MCDCBranch { true: Counter(2), false: Expression(12, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
+- MCDCBranch { true: Counter(2), false: Expression(9, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
     true  = c2
-    false = ((c0 - c1) - c2)
-- Code(Expression(6, Add)) at (prev + 1, 9) to (start + 1, 13)
+    false = (c0 - (c1 + c2))
+- Code(Expression(15, Add)) at (prev + 1, 9) to (start + 1, 13)
     = (c1 + c2)
 - MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 1, 12) to (start + 0, 18)
-- MCDCBranch { true: Expression(5, Sub), false: Counter(5), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 12) to (start + 0, 13)
-    true  = ((c1 + c2) - c5)
+- MCDCBranch { true: Expression(6, Sub), false: Counter(3), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 12) to (start + 0, 13)
+    true  = ((c1 + c2) - c3)
+    false = c3
+- Code(Expression(6, Sub)) at (prev + 0, 17) to (start + 0, 18)
+    = ((c1 + c2) - c3)
+- MCDCBranch { true: Counter(4), false: Counter(5), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 17) to (start + 0, 18)
+    true  = c4
     false = c5
-- Code(Expression(5, Sub)) at (prev + 0, 17) to (start + 0, 18)
-    = ((c1 + c2) - c5)
-- MCDCBranch { true: Counter(3), false: Counter(4), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 17) to (start + 0, 18)
-    true  = c3
-    false = c4
-- Code(Counter(3)) at (prev + 0, 19) to (start + 2, 10)
-- Code(Expression(11, Add)) at (prev + 2, 9) to (start + 0, 10)
-    = (c4 + c5)
-- Code(Expression(12, Sub)) at (prev + 1, 12) to (start + 2, 6)
-    = ((c0 - c1) - c2)
-- Code(Expression(9, Add)) at (prev + 3, 1) to (start + 0, 2)
-    = ((c3 + (c4 + c5)) + ((c0 - c1) - c2))
+- Code(Counter(4)) at (prev + 0, 19) to (start + 2, 10)
+- Code(Expression(8, Add)) at (prev + 2, 9) to (start + 0, 10)
+    = (c3 + c5)
+- Code(Expression(9, Sub)) at (prev + 1, 12) to (start + 2, 6)
+    = (c0 - (c1 + c2))
+- Code(Expression(11, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = ((((c0 + c3) + c4) + c5) - (c1 + c2))
 Highest counter ID seen: c5
 
diff --git a/tests/coverage/mcdc/inlined_expressions.cov-map b/tests/coverage/mcdc/inlined_expressions.cov-map
index 4f44e0f2b85..92ec60dc23c 100644
--- a/tests/coverage/mcdc/inlined_expressions.cov-map
+++ b/tests/coverage/mcdc/inlined_expressions.cov-map
@@ -1,11 +1,12 @@
 Function name: inlined_expressions::inlined_instance
-Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 08, 01, 01, 06, 28, 03, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 0d, 02, 00, 00, 00, 0a, 00, 0b, 07, 01, 01, 00, 02]
+Raw bytes (54): 0x[01, 01, 04, 01, 05, 0b, 05, 0f, 0d, 01, 09, 06, 01, 08, 01, 01, 06, 28, 03, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 0d, 02, 00, 00, 00, 0a, 00, 0b, 06, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 3
+Number of expressions: 4
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub)
-- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(1)
+- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(3)
+- expression 3 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 6
 - Code(Counter(0)) at (prev + 8, 1) to (start + 1, 6)
 - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 5) to (start + 0, 11)
@@ -16,7 +17,7 @@ Number of file 0 mappings: 6
 - MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 10) to (start + 0, 11)
     true  = c2
     false = c3
-- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2)
-    = ((c2 + c3) + (c0 - c1))
+- Code(Expression(1, Sub)) at (prev + 1, 1) to (start + 0, 2)
+    = (((c0 + c2) + c3) - c1)
 Highest counter ID seen: c3
 
diff --git a/tests/coverage/mcdc/nested_if.cov-map b/tests/coverage/mcdc/nested_if.cov-map
index 3bed49e7a12..72daecabc77 100644
--- a/tests/coverage/mcdc/nested_if.cov-map
+++ b/tests/coverage/mcdc/nested_if.cov-map
@@ -1,205 +1,213 @@
 Function name: nested_if::doubly_nested_if_in_condition
-Raw bytes (168): 0x[01, 01, 0e, 01, 05, 05, 11, 05, 11, 26, 19, 05, 11, 19, 1d, 19, 1d, 1d, 22, 26, 19, 05, 11, 11, 15, 09, 02, 0d, 37, 09, 02, 14, 01, 0f, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 06, 02, 00, 10, 00, 36, 30, 11, 26, 01, 00, 02, 00, 10, 00, 11, 30, 15, 21, 02, 00, 00, 00, 15, 00, 36, 26, 00, 18, 00, 19, 28, 03, 02, 00, 18, 00, 1e, 30, 19, 22, 01, 02, 00, 00, 18, 00, 19, 19, 00, 1d, 00, 1e, 30, 1a, 1d, 02, 00, 00, 00, 1d, 00, 1e, 1a, 00, 21, 00, 25, 1f, 00, 2f, 00, 34, 2b, 00, 39, 00, 3e, 21, 00, 48, 00, 4c, 0d, 00, 4f, 02, 06, 37, 02, 0c, 02, 06, 33, 03, 01, 00, 02]
+Raw bytes (172): 0x[01, 01, 10, 01, 05, 05, 09, 05, 09, 05, 27, 09, 19, 19, 1d, 19, 1d, 23, 27, 05, 1d, 09, 19, 09, 0d, 33, 05, 01, 15, 3b, 05, 3f, 15, 01, 11, 14, 01, 0f, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 11, 15, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 06, 02, 00, 10, 00, 36, 30, 09, 0a, 01, 00, 02, 00, 10, 00, 11, 30, 0d, 21, 02, 00, 00, 00, 15, 00, 36, 0a, 00, 18, 00, 19, 28, 03, 02, 00, 18, 00, 1e, 30, 19, 0e, 01, 02, 00, 00, 18, 00, 19, 19, 00, 1d, 00, 1e, 30, 1a, 1d, 02, 00, 00, 00, 1d, 00, 1e, 1a, 00, 21, 00, 25, 1e, 00, 2f, 00, 34, 2b, 00, 39, 00, 3e, 21, 00, 48, 00, 4c, 11, 00, 4f, 02, 06, 2e, 02, 0c, 02, 06, 36, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 14
+Number of expressions: 16
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(1), rhs = Counter(4)
-- expression 2 operands: lhs = Counter(1), rhs = Counter(4)
-- expression 3 operands: lhs = Expression(9, Sub), rhs = Counter(6)
-- expression 4 operands: lhs = Counter(1), rhs = Counter(4)
+- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 3 operands: lhs = Counter(1), rhs = Expression(9, Add)
+- expression 4 operands: lhs = Counter(2), rhs = Counter(6)
 - expression 5 operands: lhs = Counter(6), rhs = Counter(7)
 - expression 6 operands: lhs = Counter(6), rhs = Counter(7)
-- expression 7 operands: lhs = Counter(7), rhs = Expression(8, Sub)
-- expression 8 operands: lhs = Expression(9, Sub), rhs = Counter(6)
-- expression 9 operands: lhs = Counter(1), rhs = Counter(4)
-- expression 10 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 11 operands: lhs = Counter(2), rhs = Expression(0, Sub)
-- expression 12 operands: lhs = Counter(3), rhs = Expression(13, Add)
-- expression 13 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 7 operands: lhs = Expression(8, Add), rhs = Expression(9, Add)
+- expression 8 operands: lhs = Counter(1), rhs = Counter(7)
+- expression 9 operands: lhs = Counter(2), rhs = Counter(6)
+- expression 10 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(1)
+- expression 12 operands: lhs = Counter(0), rhs = Counter(5)
+- expression 13 operands: lhs = Expression(14, Add), rhs = Counter(1)
+- expression 14 operands: lhs = Expression(15, Add), rhs = Counter(5)
+- expression 15 operands: lhs = Counter(0), rhs = Counter(4)
 Number of file 0 mappings: 20
 - Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 9, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 78)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
     false = (c0 - c1)
-- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 78)
-    true  = c3
-    false = c2
+- MCDCBranch { true: Counter(4), false: Counter(5), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 78)
+    true  = c4
+    false = c5
 - Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17)
 - MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 54)
-- MCDCBranch { true: Counter(4), false: Expression(9, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17)
-    true  = c4
-    false = (c1 - c4)
-- MCDCBranch { true: Counter(5), false: Counter(8), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 21) to (start + 0, 54)
-    true  = c5
+- MCDCBranch { true: Counter(2), false: Expression(2, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17)
+    true  = c2
+    false = (c1 - c2)
+- MCDCBranch { true: Counter(3), false: Counter(8), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 21) to (start + 0, 54)
+    true  = c3
     false = c8
-- Code(Expression(9, Sub)) at (prev + 0, 24) to (start + 0, 25)
-    = (c1 - c4)
+- Code(Expression(2, Sub)) at (prev + 0, 24) to (start + 0, 25)
+    = (c1 - c2)
 - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 24) to (start + 0, 30)
-- MCDCBranch { true: Counter(6), false: Expression(8, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 24) to (start + 0, 25)
+- MCDCBranch { true: Counter(6), false: Expression(3, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 24) to (start + 0, 25)
     true  = c6
-    false = ((c1 - c4) - c6)
+    false = (c1 - (c2 + c6))
 - Code(Counter(6)) at (prev + 0, 29) to (start + 0, 30)
 - MCDCBranch { true: Expression(6, Sub), false: Counter(7), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 29) to (start + 0, 30)
     true  = (c6 - c7)
     false = c7
 - Code(Expression(6, Sub)) at (prev + 0, 33) to (start + 0, 37)
     = (c6 - c7)
-- Code(Expression(7, Add)) at (prev + 0, 47) to (start + 0, 52)
-    = (c7 + ((c1 - c4) - c6))
+- Code(Expression(7, Sub)) at (prev + 0, 47) to (start + 0, 52)
+    = ((c1 + c7) - (c2 + c6))
 - Code(Expression(10, Add)) at (prev + 0, 57) to (start + 0, 62)
-    = (c4 + c5)
+    = (c2 + c3)
 - Code(Counter(8)) at (prev + 0, 72) to (start + 0, 76)
-- Code(Counter(3)) at (prev + 0, 79) to (start + 2, 6)
-- Code(Expression(13, Add)) at (prev + 2, 12) to (start + 2, 6)
-    = (c2 + (c0 - c1))
-- Code(Expression(12, Add)) at (prev + 3, 1) to (start + 0, 2)
-    = (c3 + (c2 + (c0 - c1)))
+- Code(Counter(4)) at (prev + 0, 79) to (start + 2, 6)
+- Code(Expression(11, Sub)) at (prev + 2, 12) to (start + 2, 6)
+    = ((c0 + c5) - c1)
+- Code(Expression(13, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = (((c0 + c4) + c5) - c1)
 Highest counter ID seen: c8
 
 Function name: nested_if::nested_if_in_condition
-Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 07, 01, 01, 09, 28, 06, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02]
+Raw bytes (124): 0x[01, 01, 0d, 01, 05, 05, 09, 05, 09, 05, 1f, 09, 0d, 09, 0d, 05, 1f, 09, 0d, 27, 05, 01, 15, 2f, 05, 33, 15, 01, 11, 0e, 01, 07, 01, 01, 09, 28, 06, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 11, 15, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 09, 0a, 01, 00, 02, 00, 10, 00, 11, 0a, 00, 15, 00, 16, 30, 0d, 1a, 02, 00, 00, 00, 15, 00, 16, 1f, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 11, 00, 2f, 02, 06, 22, 02, 0c, 02, 06, 2a, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 11
+Number of expressions: 13
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(1), rhs = Counter(4)
-- expression 2 operands: lhs = Counter(1), rhs = Counter(4)
-- expression 3 operands: lhs = Expression(7, Sub), rhs = Counter(5)
-- expression 4 operands: lhs = Counter(1), rhs = Counter(4)
-- expression 5 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 6 operands: lhs = Expression(7, Sub), rhs = Counter(5)
-- expression 7 operands: lhs = Counter(1), rhs = Counter(4)
-- expression 8 operands: lhs = Counter(2), rhs = Expression(0, Sub)
-- expression 9 operands: lhs = Counter(3), rhs = Expression(10, Add)
-- expression 10 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 3 operands: lhs = Counter(1), rhs = Expression(7, Add)
+- expression 4 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 5 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 6 operands: lhs = Counter(1), rhs = Expression(7, Add)
+- expression 7 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 8 operands: lhs = Expression(9, Add), rhs = Counter(1)
+- expression 9 operands: lhs = Counter(0), rhs = Counter(5)
+- expression 10 operands: lhs = Expression(11, Add), rhs = Counter(1)
+- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(5)
+- expression 12 operands: lhs = Counter(0), rhs = Counter(4)
 Number of file 0 mappings: 14
 - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 46)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
     false = (c0 - c1)
-- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 46)
-    true  = c3
-    false = c2
+- MCDCBranch { true: Counter(4), false: Counter(5), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 46)
+    true  = c4
+    false = c5
 - Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17)
 - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 22)
-- MCDCBranch { true: Counter(4), false: Expression(7, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17)
-    true  = c4
-    false = (c1 - c4)
-- Code(Expression(7, Sub)) at (prev + 0, 21) to (start + 0, 22)
-    = (c1 - c4)
-- MCDCBranch { true: Counter(5), false: Expression(6, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 21) to (start + 0, 22)
-    true  = c5
-    false = ((c1 - c4) - c5)
-- Code(Expression(5, Add)) at (prev + 0, 25) to (start + 0, 29)
-    = (c4 + c5)
+- MCDCBranch { true: Counter(2), false: Expression(2, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17)
+    true  = c2
+    false = (c1 - c2)
+- Code(Expression(2, Sub)) at (prev + 0, 21) to (start + 0, 22)
+    = (c1 - c2)
+- MCDCBranch { true: Counter(3), false: Expression(6, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 21) to (start + 0, 22)
+    true  = c3
+    false = (c1 - (c2 + c3))
+- Code(Expression(7, Add)) at (prev + 0, 25) to (start + 0, 29)
+    = (c2 + c3)
 - Code(Expression(6, Sub)) at (prev + 0, 39) to (start + 0, 44)
-    = ((c1 - c4) - c5)
-- Code(Counter(3)) at (prev + 0, 47) to (start + 2, 6)
-- Code(Expression(10, Add)) at (prev + 2, 12) to (start + 2, 6)
-    = (c2 + (c0 - c1))
-- Code(Expression(9, Add)) at (prev + 3, 1) to (start + 0, 2)
-    = (c3 + (c2 + (c0 - c1)))
+    = (c1 - (c2 + c3))
+- Code(Counter(4)) at (prev + 0, 47) to (start + 2, 6)
+- Code(Expression(8, Sub)) at (prev + 2, 12) to (start + 2, 6)
+    = ((c0 + c5) - c1)
+- Code(Expression(10, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = (((c0 + c4) + c5) - c1)
 Highest counter ID seen: c5
 
 Function name: nested_if::nested_in_then_block_in_condition
-Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 22, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 06, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02]
+Raw bytes (180): 0x[01, 01, 14, 01, 05, 05, 09, 05, 09, 05, 3b, 09, 0d, 09, 0d, 3b, 11, 09, 0d, 11, 15, 11, 15, 2f, 11, 3b, 15, 09, 0d, 05, 3b, 09, 0d, 43, 05, 01, 1d, 4b, 05, 4f, 1d, 01, 19, 14, 01, 22, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 19, 1d, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 09, 0a, 01, 00, 02, 00, 10, 00, 11, 0a, 00, 15, 00, 16, 30, 0d, 36, 02, 00, 00, 00, 15, 00, 16, 3b, 00, 1c, 00, 1d, 28, 06, 02, 00, 1c, 00, 22, 30, 11, 1a, 01, 02, 00, 00, 1c, 00, 1d, 11, 00, 21, 00, 22, 30, 26, 15, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2a, 00, 33, 00, 38, 36, 00, 44, 00, 49, 19, 00, 4c, 02, 06, 3e, 02, 0c, 02, 06, 46, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 18
+Number of expressions: 20
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(1), rhs = Counter(4)
-- expression 2 operands: lhs = Counter(1), rhs = Counter(4)
-- expression 3 operands: lhs = Expression(14, Sub), rhs = Counter(5)
-- expression 4 operands: lhs = Counter(1), rhs = Counter(4)
-- expression 5 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 6 operands: lhs = Expression(12, Add), rhs = Counter(6)
-- expression 7 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 8 operands: lhs = Counter(6), rhs = Counter(7)
-- expression 9 operands: lhs = Counter(6), rhs = Counter(7)
-- expression 10 operands: lhs = Counter(7), rhs = Expression(11, Sub)
-- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(6)
-- expression 12 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 13 operands: lhs = Expression(14, Sub), rhs = Counter(5)
-- expression 14 operands: lhs = Counter(1), rhs = Counter(4)
-- expression 15 operands: lhs = Counter(2), rhs = Expression(0, Sub)
-- expression 16 operands: lhs = Counter(3), rhs = Expression(17, Add)
-- expression 17 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 3 operands: lhs = Counter(1), rhs = Expression(14, Add)
+- expression 4 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 5 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 6 operands: lhs = Expression(14, Add), rhs = Counter(4)
+- expression 7 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 8 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 9 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 10 operands: lhs = Expression(11, Add), rhs = Counter(4)
+- expression 11 operands: lhs = Expression(14, Add), rhs = Counter(5)
+- expression 12 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 13 operands: lhs = Counter(1), rhs = Expression(14, Add)
+- expression 14 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 15 operands: lhs = Expression(16, Add), rhs = Counter(1)
+- expression 16 operands: lhs = Counter(0), rhs = Counter(7)
+- expression 17 operands: lhs = Expression(18, Add), rhs = Counter(1)
+- expression 18 operands: lhs = Expression(19, Add), rhs = Counter(7)
+- expression 19 operands: lhs = Counter(0), rhs = Counter(6)
 Number of file 0 mappings: 20
 - Code(Counter(0)) at (prev + 34, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 9, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 75)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
     false = (c0 - c1)
-- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 75)
-    true  = c3
-    false = c2
+- MCDCBranch { true: Counter(6), false: Counter(7), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 75)
+    true  = c6
+    false = c7
 - Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17)
 - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 22)
-- MCDCBranch { true: Counter(4), false: Expression(14, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17)
-    true  = c4
-    false = (c1 - c4)
-- Code(Expression(14, Sub)) at (prev + 0, 21) to (start + 0, 22)
-    = (c1 - c4)
-- MCDCBranch { true: Counter(5), false: Expression(13, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 21) to (start + 0, 22)
-    true  = c5
-    false = ((c1 - c4) - c5)
-- Code(Expression(12, Add)) at (prev + 0, 28) to (start + 0, 29)
-    = (c4 + c5)
+- MCDCBranch { true: Counter(2), false: Expression(2, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17)
+    true  = c2
+    false = (c1 - c2)
+- Code(Expression(2, Sub)) at (prev + 0, 21) to (start + 0, 22)
+    = (c1 - c2)
+- MCDCBranch { true: Counter(3), false: Expression(13, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 21) to (start + 0, 22)
+    true  = c3
+    false = (c1 - (c2 + c3))
+- Code(Expression(14, Add)) at (prev + 0, 28) to (start + 0, 29)
+    = (c2 + c3)
 - MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 0, 28) to (start + 0, 34)
-- MCDCBranch { true: Counter(6), false: Expression(11, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29)
-    true  = c6
-    false = ((c4 + c5) - c6)
-- Code(Counter(6)) at (prev + 0, 33) to (start + 0, 34)
-- MCDCBranch { true: Expression(9, Sub), false: Counter(7), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 33) to (start + 0, 34)
-    true  = (c6 - c7)
-    false = c7
+- MCDCBranch { true: Counter(4), false: Expression(6, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29)
+    true  = c4
+    false = ((c2 + c3) - c4)
+- Code(Counter(4)) at (prev + 0, 33) to (start + 0, 34)
+- MCDCBranch { true: Expression(9, Sub), false: Counter(5), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 33) to (start + 0, 34)
+    true  = (c4 - c5)
+    false = c5
 - Code(Expression(9, Sub)) at (prev + 0, 37) to (start + 0, 41)
-    = (c6 - c7)
-- Code(Expression(10, Add)) at (prev + 0, 51) to (start + 0, 56)
-    = (c7 + ((c4 + c5) - c6))
+    = (c4 - c5)
+- Code(Expression(10, Sub)) at (prev + 0, 51) to (start + 0, 56)
+    = (((c2 + c3) + c5) - c4)
 - Code(Expression(13, Sub)) at (prev + 0, 68) to (start + 0, 73)
-    = ((c1 - c4) - c5)
-- Code(Counter(3)) at (prev + 0, 76) to (start + 2, 6)
-- Code(Expression(17, Add)) at (prev + 2, 12) to (start + 2, 6)
-    = (c2 + (c0 - c1))
-- Code(Expression(16, Add)) at (prev + 3, 1) to (start + 0, 2)
-    = (c3 + (c2 + (c0 - c1)))
+    = (c1 - (c2 + c3))
+- Code(Counter(6)) at (prev + 0, 76) to (start + 2, 6)
+- Code(Expression(15, Sub)) at (prev + 2, 12) to (start + 2, 6)
+    = ((c0 + c7) - c1)
+- Code(Expression(17, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = (((c0 + c6) + c7) - c1)
 Highest counter ID seen: c7
 
 Function name: nested_if::nested_single_condition_decision
-Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 17, 01, 04, 09, 28, 03, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02]
+Raw bytes (89): 0x[01, 01, 08, 01, 05, 05, 09, 05, 09, 13, 05, 01, 11, 1b, 05, 1f, 11, 01, 0d, 0b, 01, 17, 01, 04, 09, 28, 03, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 11, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 09, 0a, 00, 10, 00, 11, 09, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 0e, 02, 0c, 02, 06, 16, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 6
+Number of expressions: 8
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(1), rhs = Counter(4)
-- expression 2 operands: lhs = Counter(1), rhs = Counter(4)
-- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
-- expression 4 operands: lhs = Counter(3), rhs = Expression(5, Add)
-- expression 5 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(1)
+- expression 4 operands: lhs = Counter(0), rhs = Counter(4)
+- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(1)
+- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(4)
+- expression 7 operands: lhs = Counter(0), rhs = Counter(3)
 Number of file 0 mappings: 11
 - Code(Counter(0)) at (prev + 23, 1) to (start + 4, 9)
 - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 4, 8) to (start + 0, 41)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
     false = (c0 - c1)
-- MCDCBranch { true: Counter(3), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 41)
+- MCDCBranch { true: Counter(3), false: Counter(4), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 41)
     true  = c3
-    false = c2
+    false = c4
 - Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17)
-- Branch { true: Counter(4), false: Expression(2, Sub) } at (prev + 0, 16) to (start + 0, 17)
-    true  = c4
-    false = (c1 - c4)
-- Code(Counter(4)) at (prev + 0, 20) to (start + 0, 25)
+- Branch { true: Counter(2), false: Expression(2, Sub) } at (prev + 0, 16) to (start + 0, 17)
+    true  = c2
+    false = (c1 - c2)
+- Code(Counter(2)) at (prev + 0, 20) to (start + 0, 25)
 - Code(Expression(2, Sub)) at (prev + 0, 35) to (start + 0, 39)
-    = (c1 - c4)
+    = (c1 - c2)
 - Code(Counter(3)) at (prev + 0, 42) to (start + 2, 6)
-- Code(Expression(5, Add)) at (prev + 2, 12) to (start + 2, 6)
-    = (c2 + (c0 - c1))
-- Code(Expression(4, Add)) at (prev + 3, 1) to (start + 0, 2)
-    = (c3 + (c2 + (c0 - c1)))
+- Code(Expression(3, Sub)) at (prev + 2, 12) to (start + 2, 6)
+    = ((c0 + c4) - c1)
+- Code(Expression(5, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = (((c0 + c3) + c4) - c1)
 Highest counter ID seen: c4
 
diff --git a/tests/coverage/mcdc/non_control_flow.cov-map b/tests/coverage/mcdc/non_control_flow.cov-map
index 677e31e404e..0edeff9a586 100644
--- a/tests/coverage/mcdc/non_control_flow.cov-map
+++ b/tests/coverage/mcdc/non_control_flow.cov-map
@@ -1,67 +1,65 @@
 Function name: non_control_flow::assign_3
-Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 04, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
+Raw bytes (89): 0x[01, 01, 09, 07, 11, 0b, 0d, 05, 09, 01, 05, 01, 05, 01, 23, 05, 11, 01, 23, 05, 11, 0a, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 04, 03, 00, 0d, 00, 18, 30, 05, 12, 01, 00, 02, 00, 0d, 00, 0e, 12, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 9
-- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add)
-- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(4)
-- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(4)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3)
+- expression 2 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 3 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 4 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 5 operands: lhs = Expression(8, Sub), rhs = Counter(4)
-- expression 6 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(4)
-- expression 8 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 5 operands: lhs = Counter(0), rhs = Expression(8, Add)
+- expression 6 operands: lhs = Counter(1), rhs = Counter(4)
+- expression 7 operands: lhs = Counter(0), rhs = Expression(8, Add)
+- expression 8 operands: lhs = Counter(1), rhs = Counter(4)
 Number of file 0 mappings: 10
 - Code(Counter(0)) at (prev + 22, 1) to (start + 0, 40)
 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
-    = (c1 + ((c2 + c3) + c4))
+    = (((c1 + c2) + c3) + c4)
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
 - MCDCDecision { bitmap_idx: 4, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24)
-- MCDCBranch { true: Counter(1), false: Expression(8, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14)
+- MCDCBranch { true: Counter(1), false: Expression(4, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14)
     true  = c1
     false = (c0 - c1)
-- Code(Expression(8, Sub)) at (prev + 0, 18) to (start + 0, 19)
+- Code(Expression(4, Sub)) at (prev + 0, 18) to (start + 0, 19)
     = (c0 - c1)
 - MCDCBranch { true: Expression(7, Sub), false: Counter(4), condition_id: 2, true_next_id: 3, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19)
-    true  = ((c0 - c1) - c4)
+    true  = (c0 - (c1 + c4))
     false = c4
 - Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 24)
-    = ((c0 - c1) - c4)
+    = (c0 - (c1 + c4))
 - MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 3, true_next_id: 0, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24)
     true  = c2
     false = c3
 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2)
-    = (c1 + ((c2 + c3) + c4))
+    = (((c1 + c2) + c3) + c4)
 Highest counter ID seen: c4
 
 Function name: non_control_flow::assign_3_bis
-Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 05, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
+Raw bytes (81): 0x[01, 01, 05, 07, 11, 09, 0d, 01, 05, 05, 09, 01, 09, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 05, 03, 00, 0d, 00, 18, 30, 05, 0a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0e, 03, 00, 02, 00, 12, 00, 13, 12, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 7
+Number of expressions: 5
 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(4)
 - expression 1 operands: lhs = Counter(2), rhs = Counter(3)
 - expression 2 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 3 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 4 operands: lhs = Expression(5, Sub), rhs = Expression(6, Sub)
-- expression 5 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 6 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 4 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 10
 - Code(Counter(0)) at (prev + 27, 1) to (start + 0, 44)
 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
     = ((c2 + c3) + c4)
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
 - MCDCDecision { bitmap_idx: 5, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24)
-- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 3, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14)
+- MCDCBranch { true: Counter(1), false: Expression(2, Sub), condition_id: 1, true_next_id: 3, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14)
     true  = c1
     false = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19)
-- MCDCBranch { true: Counter(2), false: Expression(5, Sub), condition_id: 3, true_next_id: 0, false_next_id: 2 } at (prev + 0, 18) to (start + 0, 19)
+- MCDCBranch { true: Counter(2), false: Expression(3, Sub), condition_id: 3, true_next_id: 0, false_next_id: 2 } at (prev + 0, 18) to (start + 0, 19)
     true  = c2
     false = (c1 - c2)
-- Code(Expression(4, Add)) at (prev + 0, 23) to (start + 0, 24)
-    = ((c1 - c2) + (c0 - c1))
+- Code(Expression(4, Sub)) at (prev + 0, 23) to (start + 0, 24)
+    = (c0 - c2)
 - MCDCBranch { true: Counter(3), false: Counter(4), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24)
     true  = c3
     false = c4
@@ -70,18 +68,18 @@ Number of file 0 mappings: 10
 Highest counter ID seen: c4
 
 Function name: non_control_flow::assign_and
-Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02]
+Raw bytes (64): 0x[01, 01, 04, 07, 05, 0b, 0d, 01, 09, 01, 05, 08, 01, 0c, 01, 00, 21, 02, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 02, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
-- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(3, Sub)
-- expression 1 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 2 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(1)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3)
+- expression 2 operands: lhs = Counter(0), rhs = Counter(2)
 - expression 3 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 8
 - Code(Counter(0)) at (prev + 12, 1) to (start + 0, 33)
-- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
-    = ((c2 + c3) + (c0 - c1))
+- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10)
+    = (((c0 + c2) + c3) - c1)
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
 - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19)
 - MCDCBranch { true: Counter(1), false: Expression(3, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
@@ -91,8 +89,8 @@ Number of file 0 mappings: 8
 - MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19)
     true  = c2
     false = c3
-- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2)
-    = ((c2 + c3) + (c0 - c1))
+- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 1, 2)
+    = (((c0 + c2) + c3) - c1)
 Highest counter ID seen: c3
 
 Function name: non_control_flow::assign_or
@@ -132,13 +130,14 @@ Number of file 0 mappings: 1
 Highest counter ID seen: c0
 
 Function name: non_control_flow::func_call
-Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 29, 01, 01, 0a, 28, 03, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02]
+Raw bytes (54): 0x[01, 01, 04, 01, 05, 0b, 05, 0f, 0d, 01, 09, 06, 01, 29, 01, 01, 0a, 28, 03, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 06, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 3
+Number of expressions: 4
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub)
-- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(1)
+- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(3)
+- expression 3 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 6
 - Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10)
 - MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15)
@@ -149,63 +148,63 @@ Number of file 0 mappings: 6
 - MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 14) to (start + 0, 15)
     true  = c2
     false = c3
-- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2)
-    = ((c2 + c3) + (c0 - c1))
+- Code(Expression(1, Sub)) at (prev + 1, 1) to (start + 0, 2)
+    = (((c0 + c2) + c3) - c1)
 Highest counter ID seen: c3
 
 Function name: non_control_flow::right_comb_tree
-Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 06, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02]
+Raw bytes (139): 0x[01, 01, 13, 07, 05, 0b, 19, 0f, 15, 13, 11, 17, 0d, 01, 09, 01, 05, 05, 09, 05, 09, 05, 4b, 09, 0d, 05, 4b, 09, 0d, 05, 47, 4b, 11, 09, 0d, 05, 47, 4b, 11, 09, 0d, 0e, 01, 20, 01, 00, 41, 02, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 06, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 22, 09, 02, 03, 00, 00, 13, 00, 14, 22, 00, 19, 00, 1a, 30, 2e, 0d, 03, 04, 00, 00, 19, 00, 1a, 2e, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 15, 19, 05, 00, 00, 00, 24, 00, 27, 02, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 19
-- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(6, Sub)
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(1)
 - expression 1 operands: lhs = Expression(2, Add), rhs = Counter(6)
 - expression 2 operands: lhs = Expression(3, Add), rhs = Counter(5)
 - expression 3 operands: lhs = Expression(4, Add), rhs = Counter(4)
-- expression 4 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 5 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3)
+- expression 5 operands: lhs = Counter(0), rhs = Counter(2)
 - expression 6 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 7 operands: lhs = Counter(1), rhs = Counter(6)
-- expression 8 operands: lhs = Counter(1), rhs = Counter(6)
-- expression 9 operands: lhs = Expression(18, Sub), rhs = Counter(5)
-- expression 10 operands: lhs = Counter(1), rhs = Counter(6)
-- expression 11 operands: lhs = Expression(18, Sub), rhs = Counter(5)
-- expression 12 operands: lhs = Counter(1), rhs = Counter(6)
-- expression 13 operands: lhs = Expression(17, Sub), rhs = Counter(4)
-- expression 14 operands: lhs = Expression(18, Sub), rhs = Counter(5)
-- expression 15 operands: lhs = Counter(1), rhs = Counter(6)
-- expression 16 operands: lhs = Expression(17, Sub), rhs = Counter(4)
-- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(5)
-- expression 18 operands: lhs = Counter(1), rhs = Counter(6)
+- expression 7 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 8 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 9 operands: lhs = Counter(1), rhs = Expression(18, Add)
+- expression 10 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 11 operands: lhs = Counter(1), rhs = Expression(18, Add)
+- expression 12 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 13 operands: lhs = Counter(1), rhs = Expression(17, Add)
+- expression 14 operands: lhs = Expression(18, Add), rhs = Counter(4)
+- expression 15 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 16 operands: lhs = Counter(1), rhs = Expression(17, Add)
+- expression 17 operands: lhs = Expression(18, Add), rhs = Counter(4)
+- expression 18 operands: lhs = Counter(2), rhs = Counter(3)
 Number of file 0 mappings: 14
 - Code(Counter(0)) at (prev + 32, 1) to (start + 0, 65)
-- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
-    = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1))
+- Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10)
+    = ((((((c0 + c2) + c3) + c4) + c5) + c6) - c1)
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
 - MCDCDecision { bitmap_idx: 6, conditions_num: 5 } at (prev + 0, 13) to (start + 0, 42)
 - MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14)
     true  = c1
     false = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 19) to (start + 0, 20)
-- MCDCBranch { true: Expression(18, Sub), false: Counter(6), condition_id: 2, true_next_id: 3, false_next_id: 0 } at (prev + 0, 19) to (start + 0, 20)
-    true  = (c1 - c6)
-    false = c6
-- Code(Expression(18, Sub)) at (prev + 0, 25) to (start + 0, 26)
-    = (c1 - c6)
-- MCDCBranch { true: Expression(17, Sub), false: Counter(5), condition_id: 3, true_next_id: 4, false_next_id: 0 } at (prev + 0, 25) to (start + 0, 26)
-    true  = ((c1 - c6) - c5)
-    false = c5
-- Code(Expression(17, Sub)) at (prev + 0, 31) to (start + 0, 32)
-    = ((c1 - c6) - c5)
+- MCDCBranch { true: Expression(8, Sub), false: Counter(2), condition_id: 2, true_next_id: 3, false_next_id: 0 } at (prev + 0, 19) to (start + 0, 20)
+    true  = (c1 - c2)
+    false = c2
+- Code(Expression(8, Sub)) at (prev + 0, 25) to (start + 0, 26)
+    = (c1 - c2)
+- MCDCBranch { true: Expression(11, Sub), false: Counter(3), condition_id: 3, true_next_id: 4, false_next_id: 0 } at (prev + 0, 25) to (start + 0, 26)
+    true  = (c1 - (c2 + c3))
+    false = c3
+- Code(Expression(11, Sub)) at (prev + 0, 31) to (start + 0, 32)
+    = (c1 - (c2 + c3))
 - MCDCBranch { true: Expression(16, Sub), false: Counter(4), condition_id: 4, true_next_id: 5, false_next_id: 0 } at (prev + 0, 31) to (start + 0, 32)
-    true  = (((c1 - c6) - c5) - c4)
+    true  = (c1 - ((c2 + c3) + c4))
     false = c4
 - Code(Expression(16, Sub)) at (prev + 0, 36) to (start + 0, 39)
-    = (((c1 - c6) - c5) - c4)
-- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 5, true_next_id: 0, false_next_id: 0 } at (prev + 0, 36) to (start + 0, 39)
-    true  = c2
-    false = c3
-- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2)
-    = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1))
+    = (c1 - ((c2 + c3) + c4))
+- MCDCBranch { true: Counter(5), false: Counter(6), condition_id: 5, true_next_id: 0, false_next_id: 0 } at (prev + 0, 36) to (start + 0, 39)
+    true  = c5
+    false = c6
+- Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 1, 2)
+    = ((((((c0 + c2) + c3) + c4) + c5) + c6) - c1)
 Highest counter ID seen: c6
 
diff --git a/tests/coverage/nested_loops.cov-map b/tests/coverage/nested_loops.cov-map
index 21871ef3206..6ba5887d243 100644
--- a/tests/coverage/nested_loops.cov-map
+++ b/tests/coverage/nested_loops.cov-map
@@ -1,52 +1,46 @@
 Function name: nested_loops::main
-Raw bytes (115): 0x[01, 01, 17, 01, 57, 05, 09, 03, 0d, 4e, 53, 03, 0d, 15, 19, 4b, 09, 4e, 53, 03, 0d, 15, 19, 46, 05, 4b, 09, 4e, 53, 03, 0d, 15, 19, 42, 19, 46, 05, 4b, 09, 4e, 53, 03, 0d, 15, 19, 05, 09, 11, 0d, 0d, 01, 01, 01, 02, 1b, 03, 04, 13, 00, 20, 4e, 01, 0d, 01, 18, 4b, 02, 12, 00, 17, 46, 01, 10, 00, 16, 05, 01, 11, 00, 16, 42, 01, 0e, 03, 16, 3e, 04, 11, 01, 1b, 11, 02, 15, 00, 21, 15, 01, 18, 02, 12, 19, 03, 0d, 00, 0e, 57, 02, 09, 00, 17, 5b, 02, 01, 00, 02]
+Raw bytes (103): 0x[01, 01, 11, 27, 09, 01, 05, 03, 0d, 13, 0d, 17, 15, 03, 11, 1f, 0d, 23, 15, 27, 11, 01, 05, 2f, 0d, 3b, 15, 01, 11, 3b, 0d, 01, 11, 05, 09, 0d, 19, 0d, 01, 01, 01, 02, 1b, 03, 04, 13, 00, 20, 0a, 01, 0d, 01, 18, 0e, 02, 12, 00, 17, 1a, 01, 10, 00, 16, 05, 01, 11, 00, 16, 2a, 01, 0e, 03, 16, 36, 04, 11, 01, 1b, 19, 02, 15, 00, 21, 11, 01, 18, 02, 12, 15, 03, 0d, 00, 0e, 3f, 02, 09, 00, 17, 43, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 23
-- expression 0 operands: lhs = Counter(0), rhs = Expression(21, Add)
-- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
+Number of expressions: 17
+- expression 0 operands: lhs = Expression(9, Add), rhs = Counter(2)
+- expression 1 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 3 operands: lhs = Expression(19, Sub), rhs = Expression(20, Add)
-- expression 4 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 5 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 6 operands: lhs = Expression(18, Add), rhs = Counter(2)
-- expression 7 operands: lhs = Expression(19, Sub), rhs = Expression(20, Add)
-- expression 8 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 9 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 10 operands: lhs = Expression(17, Sub), rhs = Counter(1)
-- expression 11 operands: lhs = Expression(18, Add), rhs = Counter(2)
-- expression 12 operands: lhs = Expression(19, Sub), rhs = Expression(20, Add)
-- expression 13 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 14 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 15 operands: lhs = Expression(16, Sub), rhs = Counter(6)
-- expression 16 operands: lhs = Expression(17, Sub), rhs = Counter(1)
-- expression 17 operands: lhs = Expression(18, Add), rhs = Counter(2)
-- expression 18 operands: lhs = Expression(19, Sub), rhs = Expression(20, Add)
-- expression 19 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 20 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 21 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 22 operands: lhs = Counter(4), rhs = Counter(3)
+- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(3)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(5)
+- expression 5 operands: lhs = Expression(0, Add), rhs = Counter(4)
+- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(3)
+- expression 7 operands: lhs = Expression(8, Add), rhs = Counter(5)
+- expression 8 operands: lhs = Expression(9, Add), rhs = Counter(4)
+- expression 9 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 10 operands: lhs = Expression(11, Add), rhs = Counter(3)
+- expression 11 operands: lhs = Expression(14, Add), rhs = Counter(5)
+- expression 12 operands: lhs = Counter(0), rhs = Counter(4)
+- expression 13 operands: lhs = Expression(14, Add), rhs = Counter(3)
+- expression 14 operands: lhs = Counter(0), rhs = Counter(4)
+- expression 15 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 16 operands: lhs = Counter(3), rhs = Counter(6)
 Number of file 0 mappings: 13
 - Code(Counter(0)) at (prev + 1, 1) to (start + 2, 27)
 - Code(Expression(0, Add)) at (prev + 4, 19) to (start + 0, 32)
-    = (c0 + (c1 + c2))
-- Code(Expression(19, Sub)) at (prev + 1, 13) to (start + 1, 24)
-    = ((c0 + (c1 + c2)) - c3)
-- Code(Expression(18, Add)) at (prev + 2, 18) to (start + 0, 23)
-    = (((c0 + (c1 + c2)) - c3) + (c5 + c6))
-- Code(Expression(17, Sub)) at (prev + 1, 16) to (start + 0, 22)
-    = ((((c0 + (c1 + c2)) - c3) + (c5 + c6)) - c2)
+    = ((c0 + c1) + c2)
+- Code(Expression(2, Sub)) at (prev + 1, 13) to (start + 1, 24)
+    = (((c0 + c1) + c2) - c3)
+- Code(Expression(3, Sub)) at (prev + 2, 18) to (start + 0, 23)
+    = (((((c0 + c1) + c2) + c4) + c5) - c3)
+- Code(Expression(6, Sub)) at (prev + 1, 16) to (start + 0, 22)
+    = ((((c0 + c1) + c4) + c5) - c3)
 - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 22)
-- Code(Expression(16, Sub)) at (prev + 1, 14) to (start + 3, 22)
-    = (((((c0 + (c1 + c2)) - c3) + (c5 + c6)) - c2) - c1)
-- Code(Expression(15, Sub)) at (prev + 4, 17) to (start + 1, 27)
-    = ((((((c0 + (c1 + c2)) - c3) + (c5 + c6)) - c2) - c1) - c6)
-- Code(Counter(4)) at (prev + 2, 21) to (start + 0, 33)
-- Code(Counter(5)) at (prev + 1, 24) to (start + 2, 18)
-- Code(Counter(6)) at (prev + 3, 13) to (start + 0, 14)
-- Code(Expression(21, Add)) at (prev + 2, 9) to (start + 0, 23)
+- Code(Expression(10, Sub)) at (prev + 1, 14) to (start + 3, 22)
+    = (((c0 + c4) + c5) - c3)
+- Code(Expression(13, Sub)) at (prev + 4, 17) to (start + 1, 27)
+    = ((c0 + c4) - c3)
+- Code(Counter(6)) at (prev + 2, 21) to (start + 0, 33)
+- Code(Counter(4)) at (prev + 1, 24) to (start + 2, 18)
+- Code(Counter(5)) at (prev + 3, 13) to (start + 0, 14)
+- Code(Expression(15, Add)) at (prev + 2, 9) to (start + 0, 23)
     = (c1 + c2)
-- Code(Expression(22, Add)) at (prev + 2, 1) to (start + 0, 2)
-    = (c4 + c3)
+- Code(Expression(16, Add)) at (prev + 2, 1) to (start + 0, 2)
+    = (c3 + c6)
 Highest counter ID seen: c6
 
diff --git a/tests/coverage/overflow.cov-map b/tests/coverage/overflow.cov-map
index f6bfb465bf9..01abcc15003 100644
--- a/tests/coverage/overflow.cov-map
+++ b/tests/coverage/overflow.cov-map
@@ -1,29 +1,30 @@
 Function name: overflow::main
-Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 10, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 03, 0a, 12, 03, 13, 00, 20, 09, 00, 21, 03, 0a, 0d, 03, 09, 00, 0a, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02]
+Raw bytes (67): 0x[01, 01, 09, 07, 0d, 0b, 09, 01, 05, 03, 11, 17, 11, 1b, 0d, 01, 09, 23, 0d, 05, 09, 09, 01, 10, 01, 01, 1b, 03, 02, 0b, 00, 18, 0e, 01, 0c, 00, 1a, 05, 00, 1b, 03, 0a, 12, 03, 13, 00, 20, 09, 00, 21, 03, 0a, 0d, 03, 09, 00, 0a, 1f, 01, 09, 00, 17, 11, 02, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 8
-- expression 0 operands: lhs = Counter(0), rhs = Expression(6, Add)
-- expression 1 operands: lhs = Counter(1), rhs = Expression(7, Add)
-- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
+Number of expressions: 9
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 3 operands: lhs = Expression(0, Add), rhs = Counter(4)
-- expression 4 operands: lhs = Expression(5, Sub), rhs = Counter(1)
-- expression 5 operands: lhs = Expression(0, Add), rhs = Counter(4)
-- expression 6 operands: lhs = Counter(1), rhs = Expression(7, Add)
-- expression 7 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(4)
+- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(3)
+- expression 6 operands: lhs = Counter(0), rhs = Counter(2)
+- expression 7 operands: lhs = Expression(8, Add), rhs = Counter(3)
+- expression 8 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 9
 - Code(Counter(0)) at (prev + 16, 1) to (start + 1, 27)
 - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24)
-    = (c0 + (c1 + (c2 + c3)))
-- Code(Expression(5, Sub)) at (prev + 1, 12) to (start + 0, 26)
-    = ((c0 + (c1 + (c2 + c3))) - c4)
+    = (((c0 + c1) + c2) + c3)
+- Code(Expression(3, Sub)) at (prev + 1, 12) to (start + 0, 26)
+    = ((((c0 + c1) + c2) + c3) - c4)
 - Code(Counter(1)) at (prev + 0, 27) to (start + 3, 10)
 - Code(Expression(4, Sub)) at (prev + 3, 19) to (start + 0, 32)
-    = (((c0 + (c1 + (c2 + c3))) - c4) - c1)
+    = (((c0 + c2) + c3) - c4)
 - Code(Counter(2)) at (prev + 0, 33) to (start + 3, 10)
 - Code(Counter(3)) at (prev + 3, 9) to (start + 0, 10)
-- Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23)
-    = (c1 + (c2 + c3))
+- Code(Expression(7, Add)) at (prev + 1, 9) to (start + 0, 23)
+    = ((c1 + c2) + c3)
 - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2)
 Highest counter ID seen: c4
 
diff --git a/tests/coverage/panic_unwind.cov-map b/tests/coverage/panic_unwind.cov-map
index 58a796ff3a2..005c4babbea 100644
--- a/tests/coverage/panic_unwind.cov-map
+++ b/tests/coverage/panic_unwind.cov-map
@@ -1,29 +1,30 @@
 Function name: panic_unwind::main
-Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 0d, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 02, 0a, 12, 02, 13, 00, 20, 09, 00, 21, 02, 0a, 0d, 02, 09, 00, 0a, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02]
+Raw bytes (67): 0x[01, 01, 09, 07, 0d, 0b, 09, 01, 05, 03, 11, 17, 11, 1b, 0d, 01, 09, 23, 0d, 05, 09, 09, 01, 0d, 01, 01, 1b, 03, 02, 0b, 00, 18, 0e, 01, 0c, 00, 1a, 05, 00, 1b, 02, 0a, 12, 02, 13, 00, 20, 09, 00, 21, 02, 0a, 0d, 02, 09, 00, 0a, 1f, 01, 09, 00, 17, 11, 02, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 8
-- expression 0 operands: lhs = Counter(0), rhs = Expression(6, Add)
-- expression 1 operands: lhs = Counter(1), rhs = Expression(7, Add)
-- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
+Number of expressions: 9
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 3 operands: lhs = Expression(0, Add), rhs = Counter(4)
-- expression 4 operands: lhs = Expression(5, Sub), rhs = Counter(1)
-- expression 5 operands: lhs = Expression(0, Add), rhs = Counter(4)
-- expression 6 operands: lhs = Counter(1), rhs = Expression(7, Add)
-- expression 7 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(4)
+- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(3)
+- expression 6 operands: lhs = Counter(0), rhs = Counter(2)
+- expression 7 operands: lhs = Expression(8, Add), rhs = Counter(3)
+- expression 8 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 9
 - Code(Counter(0)) at (prev + 13, 1) to (start + 1, 27)
 - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24)
-    = (c0 + (c1 + (c2 + c3)))
-- Code(Expression(5, Sub)) at (prev + 1, 12) to (start + 0, 26)
-    = ((c0 + (c1 + (c2 + c3))) - c4)
+    = (((c0 + c1) + c2) + c3)
+- Code(Expression(3, Sub)) at (prev + 1, 12) to (start + 0, 26)
+    = ((((c0 + c1) + c2) + c3) - c4)
 - Code(Counter(1)) at (prev + 0, 27) to (start + 2, 10)
 - Code(Expression(4, Sub)) at (prev + 2, 19) to (start + 0, 32)
-    = (((c0 + (c1 + (c2 + c3))) - c4) - c1)
+    = (((c0 + c2) + c3) - c4)
 - Code(Counter(2)) at (prev + 0, 33) to (start + 2, 10)
 - Code(Counter(3)) at (prev + 2, 9) to (start + 0, 10)
-- Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23)
-    = (c1 + (c2 + c3))
+- Code(Expression(7, Add)) at (prev + 1, 9) to (start + 0, 23)
+    = ((c1 + c2) + c3)
 - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2)
 Highest counter ID seen: c4
 
diff --git a/tests/coverage/simple_match.cov-map b/tests/coverage/simple_match.cov-map
index d8bf9eae4bc..8f973742959 100644
--- a/tests/coverage/simple_match.cov-map
+++ b/tests/coverage/simple_match.cov-map
@@ -1,29 +1,29 @@
 Function name: simple_match::main
-Raw bytes (72): 0x[01, 01, 09, 01, 05, 01, 23, 09, 0d, 1f, 11, 01, 23, 09, 0d, 1f, 11, 01, 23, 09, 0d, 0a, 01, 04, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 05, 00, 06, 1f, 05, 09, 00, 0d, 1a, 05, 0d, 00, 16, 09, 02, 0d, 00, 0e, 1a, 02, 11, 02, 12, 09, 04, 0d, 07, 0e, 0d, 0a, 0d, 00, 0f, 11, 03, 01, 00, 02]
+Raw bytes (72): 0x[01, 01, 09, 01, 05, 23, 0d, 01, 09, 1f, 11, 23, 0d, 01, 09, 1f, 11, 23, 0d, 01, 09, 0a, 01, 04, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 05, 00, 06, 1f, 05, 09, 00, 0d, 1a, 05, 0d, 00, 16, 09, 02, 0d, 00, 0e, 1a, 02, 11, 02, 12, 09, 04, 0d, 07, 0e, 0d, 0a, 0d, 00, 0f, 11, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 9
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(0), rhs = Expression(8, Add)
-- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 1 operands: lhs = Expression(8, Add), rhs = Counter(3)
+- expression 2 operands: lhs = Counter(0), rhs = Counter(2)
 - expression 3 operands: lhs = Expression(7, Add), rhs = Counter(4)
-- expression 4 operands: lhs = Counter(0), rhs = Expression(8, Add)
-- expression 5 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 4 operands: lhs = Expression(8, Add), rhs = Counter(3)
+- expression 5 operands: lhs = Counter(0), rhs = Counter(2)
 - expression 6 operands: lhs = Expression(7, Add), rhs = Counter(4)
-- expression 7 operands: lhs = Counter(0), rhs = Expression(8, Add)
-- expression 8 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 7 operands: lhs = Expression(8, Add), rhs = Counter(3)
+- expression 8 operands: lhs = Counter(0), rhs = Counter(2)
 Number of file 0 mappings: 10
 - Code(Counter(0)) at (prev + 4, 1) to (start + 7, 15)
 - Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6)
 - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6)
     = (c0 - c1)
 - Code(Expression(7, Add)) at (prev + 5, 9) to (start + 0, 13)
-    = (c0 + (c2 + c3))
+    = ((c0 + c2) + c3)
 - Code(Expression(6, Sub)) at (prev + 5, 13) to (start + 0, 22)
-    = ((c0 + (c2 + c3)) - c4)
+    = (((c0 + c2) + c3) - c4)
 - Code(Counter(2)) at (prev + 2, 13) to (start + 0, 14)
 - Code(Expression(6, Sub)) at (prev + 2, 17) to (start + 2, 18)
-    = ((c0 + (c2 + c3)) - c4)
+    = (((c0 + c2) + c3) - c4)
 - Code(Counter(2)) at (prev + 4, 13) to (start + 7, 14)
 - Code(Counter(3)) at (prev + 10, 13) to (start + 0, 15)
 - Code(Counter(4)) at (prev + 3, 1) to (start + 0, 2)
diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map
index 246a1ba738b..7fbd2cc642e 100644
--- a/tests/coverage/try_error_result.cov-map
+++ b/tests/coverage/try_error_result.cov-map
@@ -55,162 +55,162 @@ Number of file 0 mappings: 4
 Highest counter ID seen: c1
 
 Function name: try_error_result::test1
-Raw bytes (75): 0x[01, 01, 08, 01, 07, 00, 09, 03, 0d, 12, 1d, 03, 0d, 1b, 0d, 1f, 00, 11, 00, 0b, 01, 0d, 01, 02, 17, 03, 07, 09, 00, 0e, 12, 02, 09, 04, 1a, 1d, 06, 0d, 00, 29, 11, 00, 29, 00, 2a, 00, 01, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0e, 04, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0d, 03, 05, 00, 0b, 17, 01, 01, 00, 02]
+Raw bytes (75): 0x[01, 01, 08, 07, 09, 01, 00, 03, 0d, 03, 13, 0d, 11, 1b, 00, 1f, 00, 0d, 15, 0b, 01, 0d, 01, 02, 17, 03, 07, 09, 00, 0e, 0a, 02, 09, 04, 1a, 11, 06, 0d, 00, 29, 15, 00, 29, 00, 2a, 00, 01, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0e, 04, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0d, 03, 05, 00, 0b, 17, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 8
-- expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add)
-- expression 1 operands: lhs = Zero, rhs = Counter(2)
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(2)
+- expression 1 operands: lhs = Counter(0), rhs = Zero
 - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 3 operands: lhs = Expression(4, Sub), rhs = Counter(7)
-- expression 4 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 5 operands: lhs = Expression(6, Add), rhs = Counter(3)
+- expression 3 operands: lhs = Expression(0, Add), rhs = Expression(4, Add)
+- expression 4 operands: lhs = Counter(3), rhs = Counter(4)
+- expression 5 operands: lhs = Expression(6, Add), rhs = Zero
 - expression 6 operands: lhs = Expression(7, Add), rhs = Zero
-- expression 7 operands: lhs = Counter(4), rhs = Zero
+- expression 7 operands: lhs = Counter(3), rhs = Counter(5)
 Number of file 0 mappings: 11
 - Code(Counter(0)) at (prev + 13, 1) to (start + 2, 23)
 - Code(Expression(0, Add)) at (prev + 7, 9) to (start + 0, 14)
-    = (c0 + (Zero + c2))
-- Code(Expression(4, Sub)) at (prev + 2, 9) to (start + 4, 26)
-    = ((c0 + (Zero + c2)) - c3)
-- Code(Counter(7)) at (prev + 6, 13) to (start + 0, 41)
-- Code(Counter(4)) at (prev + 0, 41) to (start + 0, 42)
+    = ((c0 + Zero) + c2)
+- Code(Expression(2, Sub)) at (prev + 2, 9) to (start + 4, 26)
+    = (((c0 + Zero) + c2) - c3)
+- Code(Counter(4)) at (prev + 6, 13) to (start + 0, 41)
+- Code(Counter(5)) at (prev + 0, 41) to (start + 0, 42)
 - Code(Zero) at (prev + 1, 13) to (start + 0, 42)
 - Code(Zero) at (prev + 0, 42) to (start + 0, 43)
 - Code(Expression(3, Sub)) at (prev + 4, 13) to (start + 0, 42)
-    = (((c0 + (Zero + c2)) - c3) - c7)
+    = (((c0 + Zero) + c2) - (c3 + c4))
 - Code(Zero) at (prev + 0, 42) to (start + 0, 43)
 - Code(Counter(3)) at (prev + 3, 5) to (start + 0, 11)
 - Code(Expression(5, Add)) at (prev + 1, 1) to (start + 0, 2)
-    = (((c4 + Zero) + Zero) + c3)
-Highest counter ID seen: c7
+    = (((c3 + c5) + Zero) + Zero)
+Highest counter ID seen: c5
 
 Function name: try_error_result::test2
-Raw bytes (358): 0x[01, 01, 3b, 01, 07, 05, 09, 03, 0d, 41, 11, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 4a, 15, 41, 11, 46, 19, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 5e, 25, 49, 21, 49, 21, 5e, 25, 49, 21, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, 92, 01, 41, 03, 0d, 8e, 01, 29, 92, 01, 41, 03, 0d, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, a6, 01, 35, 45, 31, 45, 31, a6, 01, 35, 45, 31, ba, 01, 3d, 4d, 39, 4d, 39, ba, 01, 3d, 4d, 39, c3, 01, 0d, c7, 01, db, 01, cb, 01, cf, 01, 11, 15, d3, 01, d7, 01, 19, 1d, 21, 25, df, 01, e3, 01, 29, 2d, e7, 01, eb, 01, 31, 35, 39, 3d, 28, 01, 3d, 01, 03, 17, 03, 08, 09, 00, 0e, 92, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 4a, 00, 31, 03, 35, 15, 04, 11, 00, 12, 46, 02, 11, 04, 12, 3e, 05, 11, 00, 14, 46, 00, 17, 00, 41, 19, 00, 41, 00, 42, 42, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 3e, 01, 0d, 00, 20, 5a, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 5e, 00, 43, 00, 60, 25, 00, 60, 00, 61, 5a, 01, 0d, 00, 20, 86, 01, 04, 11, 00, 14, 8e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 8a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 86, 01, 01, 0d, 00, 20, a2, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, a6, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, ba, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, bf, 01, 01, 01, 00, 02]
+Raw bytes (355): 0x[01, 01, 3b, 07, 09, 01, 05, 03, 0d, 11, 15, 11, 4b, 15, 19, 11, 43, 47, 21, 4b, 1d, 15, 19, 11, 4b, 15, 19, 11, 47, 4b, 1d, 15, 19, 11, 43, 47, 21, 4b, 1d, 15, 19, 45, 5f, 25, 29, 45, 25, 45, 5f, 25, 29, 03, 8b, 01, 8f, 01, 31, 93, 01, 2d, 0d, 11, 03, 93, 01, 0d, 11, 03, 8f, 01, 93, 01, 2d, 0d, 11, 03, 8b, 01, 8f, 01, 31, 93, 01, 2d, 0d, 11, 49, a7, 01, 35, 39, 49, 35, 49, a7, 01, 35, 39, 4d, bb, 01, 3d, 41, 4d, 3d, 4d, bb, 01, 3d, 41, c3, 01, 41, c7, 01, 3d, cb, 01, 39, cf, 01, 35, d3, 01, 31, d7, 01, 2d, db, 01, 29, df, 01, 25, e3, 01, 21, e7, 01, 1d, eb, 01, 19, 0d, 15, 28, 01, 3d, 01, 03, 17, 03, 08, 09, 00, 0e, 0a, 02, 09, 04, 1a, 11, 06, 0d, 00, 2f, 15, 00, 2f, 00, 30, 0e, 00, 31, 03, 35, 19, 04, 11, 00, 12, 2a, 02, 11, 04, 12, 3e, 05, 11, 00, 14, 2a, 00, 17, 00, 41, 1d, 00, 41, 00, 42, 32, 00, 43, 00, 5f, 21, 00, 5f, 00, 60, 3e, 01, 0d, 00, 20, 5a, 01, 11, 00, 14, 45, 00, 17, 00, 41, 25, 00, 41, 00, 42, 56, 00, 43, 00, 60, 29, 00, 60, 00, 61, 5a, 01, 0d, 00, 20, 86, 01, 04, 11, 00, 14, 72, 00, 17, 00, 42, 2d, 00, 42, 00, 43, 7a, 00, 44, 00, 61, 31, 00, 61, 00, 62, 86, 01, 01, 0d, 00, 20, a2, 01, 01, 11, 00, 14, 49, 00, 17, 01, 36, 35, 01, 36, 00, 37, 9e, 01, 01, 12, 00, 2f, 39, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 3d, 02, 11, 00, 12, b2, 01, 01, 12, 00, 2f, 41, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, bf, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 59
-- expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add)
-- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(2)
+- expression 1 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 3 operands: lhs = Counter(16), rhs = Counter(4)
-- expression 4 operands: lhs = Expression(18, Sub), rhs = Counter(5)
-- expression 5 operands: lhs = Counter(16), rhs = Counter(4)
-- expression 6 operands: lhs = Expression(16, Sub), rhs = Counter(7)
-- expression 7 operands: lhs = Expression(17, Sub), rhs = Counter(6)
-- expression 8 operands: lhs = Expression(18, Sub), rhs = Counter(5)
-- expression 9 operands: lhs = Counter(16), rhs = Counter(4)
-- expression 10 operands: lhs = Expression(18, Sub), rhs = Counter(5)
-- expression 11 operands: lhs = Counter(16), rhs = Counter(4)
-- expression 12 operands: lhs = Expression(17, Sub), rhs = Counter(6)
-- expression 13 operands: lhs = Expression(18, Sub), rhs = Counter(5)
-- expression 14 operands: lhs = Counter(16), rhs = Counter(4)
-- expression 15 operands: lhs = Expression(16, Sub), rhs = Counter(7)
-- expression 16 operands: lhs = Expression(17, Sub), rhs = Counter(6)
-- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(5)
-- expression 18 operands: lhs = Counter(16), rhs = Counter(4)
-- expression 19 operands: lhs = Expression(23, Sub), rhs = Counter(9)
-- expression 20 operands: lhs = Counter(18), rhs = Counter(8)
-- expression 21 operands: lhs = Counter(18), rhs = Counter(8)
-- expression 22 operands: lhs = Expression(23, Sub), rhs = Counter(9)
-- expression 23 operands: lhs = Counter(18), rhs = Counter(8)
-- expression 24 operands: lhs = Expression(34, Sub), rhs = Counter(11)
-- expression 25 operands: lhs = Expression(35, Sub), rhs = Counter(10)
-- expression 26 operands: lhs = Expression(36, Sub), rhs = Counter(16)
-- expression 27 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 28 operands: lhs = Expression(36, Sub), rhs = Counter(16)
-- expression 29 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 30 operands: lhs = Expression(35, Sub), rhs = Counter(10)
-- expression 31 operands: lhs = Expression(36, Sub), rhs = Counter(16)
-- expression 32 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 33 operands: lhs = Expression(34, Sub), rhs = Counter(11)
-- expression 34 operands: lhs = Expression(35, Sub), rhs = Counter(10)
-- expression 35 operands: lhs = Expression(36, Sub), rhs = Counter(16)
-- expression 36 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 37 operands: lhs = Expression(41, Sub), rhs = Counter(13)
-- expression 38 operands: lhs = Counter(17), rhs = Counter(12)
-- expression 39 operands: lhs = Counter(17), rhs = Counter(12)
-- expression 40 operands: lhs = Expression(41, Sub), rhs = Counter(13)
-- expression 41 operands: lhs = Counter(17), rhs = Counter(12)
-- expression 42 operands: lhs = Expression(46, Sub), rhs = Counter(15)
-- expression 43 operands: lhs = Counter(19), rhs = Counter(14)
-- expression 44 operands: lhs = Counter(19), rhs = Counter(14)
-- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(15)
-- expression 46 operands: lhs = Counter(19), rhs = Counter(14)
-- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(3)
-- expression 48 operands: lhs = Expression(49, Add), rhs = Expression(54, Add)
-- expression 49 operands: lhs = Expression(50, Add), rhs = Expression(51, Add)
-- expression 50 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 51 operands: lhs = Expression(52, Add), rhs = Expression(53, Add)
-- expression 52 operands: lhs = Counter(6), rhs = Counter(7)
-- expression 53 operands: lhs = Counter(8), rhs = Counter(9)
-- expression 54 operands: lhs = Expression(55, Add), rhs = Expression(56, Add)
-- expression 55 operands: lhs = Counter(10), rhs = Counter(11)
-- expression 56 operands: lhs = Expression(57, Add), rhs = Expression(58, Add)
-- expression 57 operands: lhs = Counter(12), rhs = Counter(13)
-- expression 58 operands: lhs = Counter(14), rhs = Counter(15)
+- expression 3 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 4 operands: lhs = Counter(4), rhs = Expression(18, Add)
+- expression 5 operands: lhs = Counter(5), rhs = Counter(6)
+- expression 6 operands: lhs = Counter(4), rhs = Expression(16, Add)
+- expression 7 operands: lhs = Expression(17, Add), rhs = Counter(8)
+- expression 8 operands: lhs = Expression(18, Add), rhs = Counter(7)
+- expression 9 operands: lhs = Counter(5), rhs = Counter(6)
+- expression 10 operands: lhs = Counter(4), rhs = Expression(18, Add)
+- expression 11 operands: lhs = Counter(5), rhs = Counter(6)
+- expression 12 operands: lhs = Counter(4), rhs = Expression(17, Add)
+- expression 13 operands: lhs = Expression(18, Add), rhs = Counter(7)
+- expression 14 operands: lhs = Counter(5), rhs = Counter(6)
+- expression 15 operands: lhs = Counter(4), rhs = Expression(16, Add)
+- expression 16 operands: lhs = Expression(17, Add), rhs = Counter(8)
+- expression 17 operands: lhs = Expression(18, Add), rhs = Counter(7)
+- expression 18 operands: lhs = Counter(5), rhs = Counter(6)
+- expression 19 operands: lhs = Counter(17), rhs = Expression(23, Add)
+- expression 20 operands: lhs = Counter(9), rhs = Counter(10)
+- expression 21 operands: lhs = Counter(17), rhs = Counter(9)
+- expression 22 operands: lhs = Counter(17), rhs = Expression(23, Add)
+- expression 23 operands: lhs = Counter(9), rhs = Counter(10)
+- expression 24 operands: lhs = Expression(0, Add), rhs = Expression(34, Add)
+- expression 25 operands: lhs = Expression(35, Add), rhs = Counter(12)
+- expression 26 operands: lhs = Expression(36, Add), rhs = Counter(11)
+- expression 27 operands: lhs = Counter(3), rhs = Counter(4)
+- expression 28 operands: lhs = Expression(0, Add), rhs = Expression(36, Add)
+- expression 29 operands: lhs = Counter(3), rhs = Counter(4)
+- expression 30 operands: lhs = Expression(0, Add), rhs = Expression(35, Add)
+- expression 31 operands: lhs = Expression(36, Add), rhs = Counter(11)
+- expression 32 operands: lhs = Counter(3), rhs = Counter(4)
+- expression 33 operands: lhs = Expression(0, Add), rhs = Expression(34, Add)
+- expression 34 operands: lhs = Expression(35, Add), rhs = Counter(12)
+- expression 35 operands: lhs = Expression(36, Add), rhs = Counter(11)
+- expression 36 operands: lhs = Counter(3), rhs = Counter(4)
+- expression 37 operands: lhs = Counter(18), rhs = Expression(41, Add)
+- expression 38 operands: lhs = Counter(13), rhs = Counter(14)
+- expression 39 operands: lhs = Counter(18), rhs = Counter(13)
+- expression 40 operands: lhs = Counter(18), rhs = Expression(41, Add)
+- expression 41 operands: lhs = Counter(13), rhs = Counter(14)
+- expression 42 operands: lhs = Counter(19), rhs = Expression(46, Add)
+- expression 43 operands: lhs = Counter(15), rhs = Counter(16)
+- expression 44 operands: lhs = Counter(19), rhs = Counter(15)
+- expression 45 operands: lhs = Counter(19), rhs = Expression(46, Add)
+- expression 46 operands: lhs = Counter(15), rhs = Counter(16)
+- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(16)
+- expression 48 operands: lhs = Expression(49, Add), rhs = Counter(15)
+- expression 49 operands: lhs = Expression(50, Add), rhs = Counter(14)
+- expression 50 operands: lhs = Expression(51, Add), rhs = Counter(13)
+- expression 51 operands: lhs = Expression(52, Add), rhs = Counter(12)
+- expression 52 operands: lhs = Expression(53, Add), rhs = Counter(11)
+- expression 53 operands: lhs = Expression(54, Add), rhs = Counter(10)
+- expression 54 operands: lhs = Expression(55, Add), rhs = Counter(9)
+- expression 55 operands: lhs = Expression(56, Add), rhs = Counter(8)
+- expression 56 operands: lhs = Expression(57, Add), rhs = Counter(7)
+- expression 57 operands: lhs = Expression(58, Add), rhs = Counter(6)
+- expression 58 operands: lhs = Counter(3), rhs = Counter(5)
 Number of file 0 mappings: 40
 - Code(Counter(0)) at (prev + 61, 1) to (start + 3, 23)
 - Code(Expression(0, Add)) at (prev + 8, 9) to (start + 0, 14)
-    = (c0 + (c1 + c2))
-- Code(Expression(36, Sub)) at (prev + 2, 9) to (start + 4, 26)
-    = ((c0 + (c1 + c2)) - c3)
-- Code(Counter(16)) at (prev + 6, 13) to (start + 0, 47)
-- Code(Counter(4)) at (prev + 0, 47) to (start + 0, 48)
-- Code(Expression(18, Sub)) at (prev + 0, 49) to (start + 3, 53)
-    = (c16 - c4)
-- Code(Counter(5)) at (prev + 4, 17) to (start + 0, 18)
-- Code(Expression(17, Sub)) at (prev + 2, 17) to (start + 4, 18)
-    = ((c16 - c4) - c5)
+    = ((c0 + c1) + c2)
+- Code(Expression(2, Sub)) at (prev + 2, 9) to (start + 4, 26)
+    = (((c0 + c1) + c2) - c3)
+- Code(Counter(4)) at (prev + 6, 13) to (start + 0, 47)
+- Code(Counter(5)) at (prev + 0, 47) to (start + 0, 48)
+- Code(Expression(3, Sub)) at (prev + 0, 49) to (start + 3, 53)
+    = (c4 - c5)
+- Code(Counter(6)) at (prev + 4, 17) to (start + 0, 18)
+- Code(Expression(10, Sub)) at (prev + 2, 17) to (start + 4, 18)
+    = (c4 - (c5 + c6))
 - Code(Expression(15, Sub)) at (prev + 5, 17) to (start + 0, 20)
-    = ((((c16 - c4) - c5) - c6) - c7)
-- Code(Expression(17, Sub)) at (prev + 0, 23) to (start + 0, 65)
-    = ((c16 - c4) - c5)
-- Code(Counter(6)) at (prev + 0, 65) to (start + 0, 66)
-- Code(Expression(16, Sub)) at (prev + 0, 67) to (start + 0, 95)
-    = (((c16 - c4) - c5) - c6)
-- Code(Counter(7)) at (prev + 0, 95) to (start + 0, 96)
+    = (c4 - (((c5 + c6) + c7) + c8))
+- Code(Expression(10, Sub)) at (prev + 0, 23) to (start + 0, 65)
+    = (c4 - (c5 + c6))
+- Code(Counter(7)) at (prev + 0, 65) to (start + 0, 66)
+- Code(Expression(12, Sub)) at (prev + 0, 67) to (start + 0, 95)
+    = (c4 - ((c5 + c6) + c7))
+- Code(Counter(8)) at (prev + 0, 95) to (start + 0, 96)
 - Code(Expression(15, Sub)) at (prev + 1, 13) to (start + 0, 32)
-    = ((((c16 - c4) - c5) - c6) - c7)
+    = (c4 - (((c5 + c6) + c7) + c8))
 - Code(Expression(22, Sub)) at (prev + 1, 17) to (start + 0, 20)
-    = ((c18 - c8) - c9)
-- Code(Counter(18)) at (prev + 0, 23) to (start + 0, 65)
-- Code(Counter(8)) at (prev + 0, 65) to (start + 0, 66)
-- Code(Expression(23, Sub)) at (prev + 0, 67) to (start + 0, 96)
-    = (c18 - c8)
-- Code(Counter(9)) at (prev + 0, 96) to (start + 0, 97)
+    = (c17 - (c9 + c10))
+- Code(Counter(17)) at (prev + 0, 23) to (start + 0, 65)
+- Code(Counter(9)) at (prev + 0, 65) to (start + 0, 66)
+- Code(Expression(21, Sub)) at (prev + 0, 67) to (start + 0, 96)
+    = (c17 - c9)
+- Code(Counter(10)) at (prev + 0, 96) to (start + 0, 97)
 - Code(Expression(22, Sub)) at (prev + 1, 13) to (start + 0, 32)
-    = ((c18 - c8) - c9)
+    = (c17 - (c9 + c10))
 - Code(Expression(33, Sub)) at (prev + 4, 17) to (start + 0, 20)
-    = (((((c0 + (c1 + c2)) - c3) - c16) - c10) - c11)
-- Code(Expression(35, Sub)) at (prev + 0, 23) to (start + 0, 66)
-    = (((c0 + (c1 + c2)) - c3) - c16)
-- Code(Counter(10)) at (prev + 0, 66) to (start + 0, 67)
-- Code(Expression(34, Sub)) at (prev + 0, 68) to (start + 0, 97)
-    = ((((c0 + (c1 + c2)) - c3) - c16) - c10)
-- Code(Counter(11)) at (prev + 0, 97) to (start + 0, 98)
+    = (((c0 + c1) + c2) - (((c3 + c4) + c11) + c12))
+- Code(Expression(28, Sub)) at (prev + 0, 23) to (start + 0, 66)
+    = (((c0 + c1) + c2) - (c3 + c4))
+- Code(Counter(11)) at (prev + 0, 66) to (start + 0, 67)
+- Code(Expression(30, Sub)) at (prev + 0, 68) to (start + 0, 97)
+    = (((c0 + c1) + c2) - ((c3 + c4) + c11))
+- Code(Counter(12)) at (prev + 0, 97) to (start + 0, 98)
 - Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 32)
-    = (((((c0 + (c1 + c2)) - c3) - c16) - c10) - c11)
+    = (((c0 + c1) + c2) - (((c3 + c4) + c11) + c12))
 - Code(Expression(40, Sub)) at (prev + 1, 17) to (start + 0, 20)
-    = ((c17 - c12) - c13)
-- Code(Counter(17)) at (prev + 0, 23) to (start + 1, 54)
-- Code(Counter(12)) at (prev + 1, 54) to (start + 0, 55)
-- Code(Expression(41, Sub)) at (prev + 1, 18) to (start + 0, 47)
-    = (c17 - c12)
-- Code(Counter(13)) at (prev + 0, 47) to (start + 0, 48)
+    = (c18 - (c13 + c14))
+- Code(Counter(18)) at (prev + 0, 23) to (start + 1, 54)
+- Code(Counter(13)) at (prev + 1, 54) to (start + 0, 55)
+- Code(Expression(39, Sub)) at (prev + 1, 18) to (start + 0, 47)
+    = (c18 - c13)
+- Code(Counter(14)) at (prev + 0, 47) to (start + 0, 48)
 - Code(Expression(40, Sub)) at (prev + 1, 13) to (start + 0, 32)
-    = ((c17 - c12) - c13)
+    = (c18 - (c13 + c14))
 - Code(Expression(45, Sub)) at (prev + 1, 17) to (start + 0, 20)
-    = ((c19 - c14) - c15)
+    = (c19 - (c15 + c16))
 - Code(Counter(19)) at (prev + 0, 23) to (start + 1, 54)
-- Code(Counter(14)) at (prev + 2, 17) to (start + 0, 18)
-- Code(Expression(46, Sub)) at (prev + 1, 18) to (start + 0, 47)
-    = (c19 - c14)
-- Code(Counter(15)) at (prev + 1, 17) to (start + 0, 18)
+- Code(Counter(15)) at (prev + 2, 17) to (start + 0, 18)
+- Code(Expression(44, Sub)) at (prev + 1, 18) to (start + 0, 47)
+    = (c19 - c15)
+- Code(Counter(16)) at (prev + 1, 17) to (start + 0, 18)
 - Code(Expression(45, Sub)) at (prev + 2, 13) to (start + 0, 32)
-    = ((c19 - c14) - c15)
+    = (c19 - (c15 + c16))
 - Code(Counter(3)) at (prev + 3, 5) to (start + 0, 11)
 - Code(Expression(47, Add)) at (prev + 1, 1) to (start + 0, 2)
-    = ((((c4 + c5) + ((c6 + c7) + (c8 + c9))) + ((c10 + c11) + ((c12 + c13) + (c14 + c15)))) + c3)
+    = ((((((((((((c3 + c5) + c6) + c7) + c8) + c9) + c10) + c11) + c12) + c13) + c14) + c15) + c16)
 Highest counter ID seen: c19
 
diff --git a/tests/coverage/unicode.cov-map b/tests/coverage/unicode.cov-map
index 769930110d6..630ab4ce47e 100644
--- a/tests/coverage/unicode.cov-map
+++ b/tests/coverage/unicode.cov-map
@@ -1,14 +1,14 @@
 Function name: unicode::main
-Raw bytes (61): 0x[01, 01, 06, 01, 05, 16, 0d, 01, 09, 11, 13, 16, 0d, 01, 09, 09, 01, 0e, 01, 00, 0b, 05, 01, 09, 00, 0c, 03, 00, 10, 00, 1b, 05, 00, 1c, 00, 28, 01, 02, 08, 00, 25, 09, 00, 29, 00, 46, 11, 00, 47, 02, 06, 13, 02, 05, 00, 06, 0f, 02, 05, 01, 02]
+Raw bytes (61): 0x[01, 01, 06, 01, 05, 0b, 09, 01, 11, 13, 09, 17, 11, 01, 0d, 09, 01, 0e, 01, 00, 0b, 05, 01, 09, 00, 0c, 03, 00, 10, 00, 1b, 05, 00, 1c, 00, 28, 01, 02, 08, 00, 25, 09, 00, 29, 00, 46, 0d, 00, 47, 02, 06, 06, 02, 05, 00, 06, 0e, 02, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 6
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Expression(5, Sub), rhs = Counter(3)
-- expression 2 operands: lhs = Counter(0), rhs = Counter(2)
-- expression 3 operands: lhs = Counter(4), rhs = Expression(4, Add)
-- expression 4 operands: lhs = Expression(5, Sub), rhs = Counter(3)
-- expression 5 operands: lhs = Counter(0), rhs = Counter(2)
+- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(2)
+- expression 2 operands: lhs = Counter(0), rhs = Counter(4)
+- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(2)
+- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(4)
+- expression 5 operands: lhs = Counter(0), rhs = Counter(3)
 Number of file 0 mappings: 9
 - Code(Counter(0)) at (prev + 14, 1) to (start + 0, 11)
 - Code(Counter(1)) at (prev + 1, 9) to (start + 0, 12)
@@ -17,12 +17,12 @@ Number of file 0 mappings: 9
 - Code(Counter(1)) at (prev + 0, 28) to (start + 0, 40)
 - Code(Counter(0)) at (prev + 2, 8) to (start + 0, 37)
 - Code(Counter(2)) at (prev + 0, 41) to (start + 0, 70)
-- Code(Counter(4)) at (prev + 0, 71) to (start + 2, 6)
-- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6)
-    = ((c0 - c2) + c3)
-- Code(Expression(3, Add)) at (prev + 2, 5) to (start + 1, 2)
-    = (c4 + ((c0 - c2) + c3))
-Highest counter ID seen: c4
+- Code(Counter(3)) at (prev + 0, 71) to (start + 2, 6)
+- Code(Expression(1, Sub)) at (prev + 2, 5) to (start + 0, 6)
+    = ((c0 + c4) - c2)
+- Code(Expression(3, Sub)) at (prev + 2, 5) to (start + 1, 2)
+    = (((c0 + c3) + c4) - c2)
+Highest counter ID seen: c3
 
 Function name: unicode::ä»– (unused)
 Raw bytes (9): 0x[01, 01, 00, 01, 00, 1e, 19, 00, 25]
diff --git a/tests/coverage/unused.cov-map b/tests/coverage/unused.cov-map
index e865ac3ee62..4eae63f380c 100644
--- a/tests/coverage/unused.cov-map
+++ b/tests/coverage/unused.cov-map
@@ -1,18 +1,18 @@
 Function name: unused::foo::<f32>
-Raw bytes (42): 0x[01, 01, 04, 01, 0f, 05, 09, 03, 0d, 05, 09, 06, 01, 03, 01, 01, 12, 03, 02, 0b, 00, 11, 0a, 01, 09, 00, 0f, 09, 00, 13, 00, 19, 0f, 01, 09, 00, 0f, 0d, 02, 01, 00, 02]
+Raw bytes (42): 0x[01, 01, 04, 07, 09, 01, 05, 03, 0d, 05, 09, 06, 01, 03, 01, 01, 12, 03, 02, 0b, 00, 11, 0a, 01, 09, 00, 0f, 09, 00, 13, 00, 19, 0f, 01, 09, 00, 0f, 0d, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
-- expression 0 operands: lhs = Counter(0), rhs = Expression(3, Add)
-- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(2)
+- expression 1 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3)
 - expression 3 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 6
 - Code(Counter(0)) at (prev + 3, 1) to (start + 1, 18)
 - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 17)
-    = (c0 + (c1 + c2))
+    = ((c0 + c1) + c2)
 - Code(Expression(2, Sub)) at (prev + 1, 9) to (start + 0, 15)
-    = ((c0 + (c1 + c2)) - c3)
+    = (((c0 + c1) + c2) - c3)
 - Code(Counter(2)) at (prev + 0, 19) to (start + 0, 25)
 - Code(Expression(3, Add)) at (prev + 1, 9) to (start + 0, 15)
     = (c1 + c2)
@@ -20,20 +20,20 @@ Number of file 0 mappings: 6
 Highest counter ID seen: c3
 
 Function name: unused::foo::<u32>
-Raw bytes (42): 0x[01, 01, 04, 01, 0f, 05, 09, 03, 0d, 05, 09, 06, 01, 03, 01, 01, 12, 03, 02, 0b, 00, 11, 0a, 01, 09, 00, 0f, 09, 00, 13, 00, 19, 0f, 01, 09, 00, 0f, 0d, 02, 01, 00, 02]
+Raw bytes (42): 0x[01, 01, 04, 07, 09, 01, 05, 03, 0d, 05, 09, 06, 01, 03, 01, 01, 12, 03, 02, 0b, 00, 11, 0a, 01, 09, 00, 0f, 09, 00, 13, 00, 19, 0f, 01, 09, 00, 0f, 0d, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
-- expression 0 operands: lhs = Counter(0), rhs = Expression(3, Add)
-- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(2)
+- expression 1 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3)
 - expression 3 operands: lhs = Counter(1), rhs = Counter(2)
 Number of file 0 mappings: 6
 - Code(Counter(0)) at (prev + 3, 1) to (start + 1, 18)
 - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 17)
-    = (c0 + (c1 + c2))
+    = ((c0 + c1) + c2)
 - Code(Expression(2, Sub)) at (prev + 1, 9) to (start + 0, 15)
-    = ((c0 + (c1 + c2)) - c3)
+    = (((c0 + c1) + c2) - c3)
 - Code(Counter(2)) at (prev + 0, 19) to (start + 0, 25)
 - Code(Expression(3, Add)) at (prev + 1, 9) to (start + 0, 15)
     = (c1 + c2)
diff --git a/tests/coverage/while_early_ret.cov-map b/tests/coverage/while_early_ret.cov-map
index 6254dfbcf01..ade770597e2 100644
--- a/tests/coverage/while_early_ret.cov-map
+++ b/tests/coverage/while_early_ret.cov-map
@@ -1,27 +1,26 @@
 Function name: while_early_ret::main
-Raw bytes (61): 0x[01, 01, 06, 01, 05, 03, 09, 0e, 05, 03, 09, 17, 09, 0d, 11, 09, 01, 05, 01, 01, 1b, 03, 03, 09, 02, 0a, 0e, 05, 0d, 02, 0e, 0a, 06, 15, 02, 16, 0d, 04, 15, 00, 1b, 11, 04, 15, 00, 1b, 05, 03, 0a, 03, 0a, 09, 06, 05, 00, 0b, 13, 01, 01, 00, 02]
+Raw bytes (59): 0x[01, 01, 05, 01, 05, 03, 09, 01, 09, 13, 11, 09, 0d, 09, 01, 05, 01, 01, 1b, 03, 03, 09, 02, 0a, 06, 05, 0d, 02, 0e, 0a, 06, 15, 02, 16, 0d, 04, 15, 00, 1b, 11, 04, 15, 00, 1b, 05, 03, 0a, 03, 0a, 09, 06, 05, 00, 0b, 0f, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 6
+Number of expressions: 5
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 1 operands: lhs = Expression(0, Add), rhs = Counter(2)
-- expression 2 operands: lhs = Expression(3, Sub), rhs = Counter(1)
-- expression 3 operands: lhs = Expression(0, Add), rhs = Counter(2)
-- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(2)
-- expression 5 operands: lhs = Counter(3), rhs = Counter(4)
+- expression 2 operands: lhs = Counter(0), rhs = Counter(2)
+- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(4)
+- expression 4 operands: lhs = Counter(2), rhs = Counter(3)
 Number of file 0 mappings: 9
 - Code(Counter(0)) at (prev + 5, 1) to (start + 1, 27)
 - Code(Expression(0, Add)) at (prev + 3, 9) to (start + 2, 10)
     = (c0 + c1)
-- Code(Expression(3, Sub)) at (prev + 5, 13) to (start + 2, 14)
+- Code(Expression(1, Sub)) at (prev + 5, 13) to (start + 2, 14)
     = ((c0 + c1) - c2)
 - Code(Expression(2, Sub)) at (prev + 6, 21) to (start + 2, 22)
-    = (((c0 + c1) - c2) - c1)
+    = (c0 - c2)
 - Code(Counter(3)) at (prev + 4, 21) to (start + 0, 27)
 - Code(Counter(4)) at (prev + 4, 21) to (start + 0, 27)
 - Code(Counter(1)) at (prev + 3, 10) to (start + 3, 10)
 - Code(Counter(2)) at (prev + 6, 5) to (start + 0, 11)
-- Code(Expression(4, Add)) at (prev + 1, 1) to (start + 0, 2)
-    = ((c3 + c4) + c2)
+- Code(Expression(3, Add)) at (prev + 1, 1) to (start + 0, 2)
+    = ((c2 + c3) + c4)
 Highest counter ID seen: c4
 
diff --git a/tests/coverage/yield.cov-map b/tests/coverage/yield.cov-map
index 578994a4530..e01ec8f9edb 100644
--- a/tests/coverage/yield.cov-map
+++ b/tests/coverage/yield.cov-map
@@ -1,17 +1,17 @@
 Function name: yield::main
-Raw bytes (106): 0x[01, 01, 0b, 05, 00, 0d, 11, 22, 15, 0d, 11, 11, 15, 22, 15, 0d, 11, 22, 15, 0d, 11, 19, 1d, 25, 29, 10, 01, 07, 01, 01, 16, 01, 07, 0b, 00, 2e, 0d, 01, 27, 00, 29, 03, 01, 0e, 00, 34, 0d, 02, 0b, 00, 2e, 22, 01, 22, 00, 27, 1e, 00, 2c, 00, 2e, 13, 01, 0e, 00, 34, 1e, 03, 09, 00, 16, 1e, 08, 0b, 00, 2e, 21, 01, 27, 00, 29, 27, 01, 0e, 00, 34, 21, 02, 0b, 00, 2e, 2d, 01, 27, 00, 29, 2b, 01, 0e, 00, 34, 2d, 02, 01, 00, 02]
+Raw bytes (106): 0x[01, 01, 0b, 05, 00, 0d, 11, 0d, 23, 11, 15, 11, 15, 0d, 23, 11, 15, 0d, 23, 11, 15, 19, 1d, 25, 29, 10, 01, 07, 01, 01, 16, 01, 07, 0b, 00, 2e, 0d, 01, 27, 00, 29, 03, 01, 0e, 00, 34, 0d, 02, 0b, 00, 2e, 06, 01, 22, 00, 27, 1e, 00, 2c, 00, 2e, 23, 01, 0e, 00, 34, 1e, 03, 09, 00, 16, 1e, 08, 0b, 00, 2e, 21, 01, 27, 00, 29, 27, 01, 0e, 00, 34, 21, 02, 0b, 00, 2e, 2d, 01, 27, 00, 29, 2b, 01, 0e, 00, 34, 2d, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 11
 - expression 0 operands: lhs = Counter(1), rhs = Zero
 - expression 1 operands: lhs = Counter(3), rhs = Counter(4)
-- expression 2 operands: lhs = Expression(8, Sub), rhs = Counter(5)
-- expression 3 operands: lhs = Counter(3), rhs = Counter(4)
+- expression 2 operands: lhs = Counter(3), rhs = Expression(8, Add)
+- expression 3 operands: lhs = Counter(4), rhs = Counter(5)
 - expression 4 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 5 operands: lhs = Expression(8, Sub), rhs = Counter(5)
-- expression 6 operands: lhs = Counter(3), rhs = Counter(4)
-- expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(5)
-- expression 8 operands: lhs = Counter(3), rhs = Counter(4)
+- expression 5 operands: lhs = Counter(3), rhs = Expression(8, Add)
+- expression 6 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 7 operands: lhs = Counter(3), rhs = Expression(8, Add)
+- expression 8 operands: lhs = Counter(4), rhs = Counter(5)
 - expression 9 operands: lhs = Counter(6), rhs = Counter(7)
 - expression 10 operands: lhs = Counter(9), rhs = Counter(10)
 Number of file 0 mappings: 16
@@ -21,16 +21,16 @@ Number of file 0 mappings: 16
 - Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 52)
     = (c1 + Zero)
 - Code(Counter(3)) at (prev + 2, 11) to (start + 0, 46)
-- Code(Expression(8, Sub)) at (prev + 1, 34) to (start + 0, 39)
+- Code(Expression(1, Sub)) at (prev + 1, 34) to (start + 0, 39)
     = (c3 - c4)
 - Code(Expression(7, Sub)) at (prev + 0, 44) to (start + 0, 46)
-    = ((c3 - c4) - c5)
-- Code(Expression(4, Add)) at (prev + 1, 14) to (start + 0, 52)
+    = (c3 - (c4 + c5))
+- Code(Expression(8, Add)) at (prev + 1, 14) to (start + 0, 52)
     = (c4 + c5)
 - Code(Expression(7, Sub)) at (prev + 3, 9) to (start + 0, 22)
-    = ((c3 - c4) - c5)
+    = (c3 - (c4 + c5))
 - Code(Expression(7, Sub)) at (prev + 8, 11) to (start + 0, 46)
-    = ((c3 - c4) - c5)
+    = (c3 - (c4 + c5))
 - Code(Counter(8)) at (prev + 1, 39) to (start + 0, 41)
 - Code(Expression(9, Add)) at (prev + 1, 14) to (start + 0, 52)
     = (c6 + c7)
diff --git a/tests/crashes/121429.rs b/tests/crashes/121429.rs
index 09bd343e0ba..e407754db5c 100644
--- a/tests/crashes/121429.rs
+++ b/tests/crashes/121429.rs
@@ -1,14 +1,11 @@
 //@ known-bug: #121429
-#![feature(generic_const_exprs)]
-
-pub trait True {}
 
-impl<const N: usize = { const { 3 } }> PartialEq<FixedI8<FRAC_RHS>> for FixedI8<FRAC_LHS> where
-    If<{}>: True
-{
-}
 #![feature(generic_const_exprs)]
 
+struct FixedI8<const X: usize>;
+const FRAC_LHS: usize = 0;
+const FRAC_RHS: usize = 1;
+
 pub trait True {}
 
 impl<const N: usize = { const { 3 } }> PartialEq<FixedI8<FRAC_RHS>> for FixedI8<FRAC_LHS> where
diff --git a/tests/crashes/124020.rs b/tests/crashes/124020.rs
index f461f32f59d..1b875497465 100644
--- a/tests/crashes/124020.rs
+++ b/tests/crashes/124020.rs
@@ -1,7 +1,7 @@
 //@ known-bug: #124020
 //@ compile-flags: -Zpolymorphize=on --edition=2018 --crate-type=lib
 
-#![feature(async_closure, noop_waker, async_fn_traits)]
+#![feature(async_closure, noop_waker, async_trait_bounds)]
 
 use std::future::Future;
 use std::pin::pin;
@@ -19,7 +19,7 @@ pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
     }
 }
 
-async fn call_once(f: impl async FnOnce(DropMe)) {
+async fn call_once(f: impl AsyncFnOnce(DropMe)) {
     f(DropMe("world")).await;
 }
 
diff --git a/tests/crashes/125476.rs b/tests/crashes/125476.rs
deleted file mode 100644
index ad739639b72..00000000000
--- a/tests/crashes/125476.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ known-bug: rust-lang/rust#125476
-//@ only-x86_64
-pub struct Data([u8; usize::MAX >> 2]);
-const _: &'static [Data] = &[];
diff --git a/tests/crashes/126267.rs b/tests/crashes/126267.rs
deleted file mode 100644
index 728578179ed..00000000000
--- a/tests/crashes/126267.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//@ known-bug: rust-lang/rust#126267
-
-#![feature(transmutability)]
-#![crate_type = "lib"]
-
-pub enum ApiError {}
-pub struct TokioError {
-    b: bool,
-}
-pub enum Error {
-    Api { source: ApiError },
-    Ethereum,
-    Tokio { source: TokioError },
-}
-
-mod assert {
-    use std::mem::TransmuteFrom;
-
-    pub fn is_transmutable<Src, Dst>()
-    where
-        Dst: TransmuteFrom<Src>, // safety is NOT assumed
-    {
-    }
-}
-
-fn test() {
-    struct Src;
-    type Dst = Error;
-    assert::is_transmutable::<Src, Dst>();
-}
diff --git a/tests/crashes/128176.rs b/tests/crashes/128176.rs
deleted file mode 100644
index 970ad9ff2cd..00000000000
--- a/tests/crashes/128176.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//@ known-bug: rust-lang/rust#128176
-
-#![feature(generic_const_exprs)]
-#![feature(dyn_compatible_for_dispatch)]
-trait X {
-    type Y<const N: i16>;
-}
-
-const _: () = {
-    fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {}
-};
-
-fn main() {}
diff --git a/tests/crashes/131538.rs b/tests/crashes/131538.rs
deleted file mode 100644
index f971d8b7791..00000000000
--- a/tests/crashes/131538.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//@ known-bug: #131538
-#![feature(generic_associated_types_extended)]
-#![feature(trivial_bounds)]
-
-trait HealthCheck {
-    async fn check<const N: usize>();
-}
-
-fn do_health_check_par()
-where
-    HealthCheck: HealthCheck,
-{
-}
diff --git a/tests/crashes/132320.rs b/tests/crashes/132320.rs
deleted file mode 100644
index 79181c3a2c5..00000000000
--- a/tests/crashes/132320.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ known-bug: #132320
-//@ compile-flags: -Znext-solver=globally
-
-trait Foo {
-    type Item;
-    fn foo(&mut self);
-}
-
-impl Foo for () {
-    type Item = Option<()>;
-
-    fn foo(&mut self) {
-        let _ = Self::Item::None;
-    }
-}
diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
index cbb11d50f79..8dd23e4d6a3 100644
--- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
@@ -30,15 +30,12 @@
 +     coverage ExpressionId(0) => Expression { lhs: Counter(1), op: Add, rhs: Counter(2) };
 +     coverage ExpressionId(1) => Expression { lhs: Expression(0), op: Add, rhs: Counter(3) };
 +     coverage ExpressionId(2) => Expression { lhs: Counter(0), op: Subtract, rhs: Expression(1) };
-+     coverage ExpressionId(3) => Expression { lhs: Counter(3), op: Add, rhs: Counter(2) };
-+     coverage ExpressionId(4) => Expression { lhs: Expression(3), op: Add, rhs: Counter(1) };
-+     coverage ExpressionId(5) => Expression { lhs: Expression(4), op: Add, rhs: Expression(2) };
 +     coverage Code(Counter(0)) => 14:1 - 15:21;
-+     coverage Code(Counter(3)) => 16:17 - 16:33;
++     coverage Code(Counter(1)) => 16:17 - 16:33;
 +     coverage Code(Counter(2)) => 17:17 - 17:33;
-+     coverage Code(Counter(1)) => 18:17 - 18:33;
++     coverage Code(Counter(3)) => 18:17 - 18:33;
 +     coverage Code(Expression(2)) => 19:17 - 19:33;
-+     coverage Code(Expression(5)) => 21:1 - 21:2;
++     coverage Code(Counter(0)) => 21:1 - 21:2;
 + 
       bb0: {
 +         Coverage::CounterIncrement(0);
@@ -55,7 +52,7 @@
       }
   
       bb2: {
-+         Coverage::CounterIncrement(3);
++         Coverage::CounterIncrement(1);
           falseEdge -> [real: bb8, imaginary: bb3];
       }
   
@@ -65,7 +62,7 @@
       }
   
       bb4: {
-+         Coverage::CounterIncrement(1);
++         Coverage::CounterIncrement(3);
           falseEdge -> [real: bb6, imaginary: bb5];
       }
   
@@ -127,7 +124,6 @@
       }
   
       bb13: {
-+         Coverage::ExpressionUsed(5);
           StorageDead(_1);
           return;
       }
diff --git a/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot b/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot
new file mode 100644
index 00000000000..7c7d8921fb3
--- /dev/null
+++ b/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot
@@ -0,0 +1,6 @@
+digraph graph_for_def_id_0_3 {
+    graph[fontname="Courier, monospace"];
+    node[fontname="Courier, monospace"];
+    edge[fontname="Courier, monospace"];
+    bb_0[label=<<table border="1" cellborder="1" cellspacing="0" cellpadding="3" sides="rb"><tr><td colspan="3" sides="tl">bb0</td></tr><tr><td colspan="2" bgcolor="#a0a0a0" sides="tl">MIR</td><td bgcolor="#a0a0a0" sides="tl">STATE</td></tr><tr><td valign="bottom" sides="tl"  align="right"></td><td valign="bottom" sides="tl"  align="left">(on start)</td><td colspan="1" valign="bottom" sides="tl"  align="left">{}</td></tr><tr><td valign="top" sides="tl" bgcolor="#f0f0f0" align="right">0</td><td valign="top" sides="tl" bgcolor="#f0f0f0" align="left">_0 = const ()</td><td valign="top" sides="tl" bgcolor="#f0f0f0" align="left"><font color="darkgreen">+_0</font></td></tr><tr><td valign="top" sides="tl"  align="right">T</td><td valign="top" sides="tl"  align="left">return</td><td valign="top" sides="tl"  align="left"></td></tr><tr><td valign="bottom" sides="tl" bgcolor="#f0f0f0" align="right"></td><td valign="bottom" sides="tl" bgcolor="#f0f0f0" align="left">(on end)</td><td colspan="1" valign="bottom" sides="tl" bgcolor="#f0f0f0" align="left">{_0}</td></tr></table>>][shape="none"];
+}
diff --git a/tests/mir-opt/dataflow.rs b/tests/mir-opt/dataflow.rs
new file mode 100644
index 00000000000..3a28f5d47b9
--- /dev/null
+++ b/tests/mir-opt/dataflow.rs
@@ -0,0 +1,6 @@
+// skip-filecheck
+// Test graphviz dataflow output
+//@ compile-flags: -Z dump-mir=main -Z dump-mir-dataflow
+
+// EMIT_MIR dataflow.main.maybe_init.borrowck.dot
+fn main() {}
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
index 87fbcca9177..027c71dfaae 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
@@ -31,7 +31,6 @@
               }
           }
           scope 9 (inlined NonNull::<[u8]>::as_ptr) {
-              let mut _17: *const [u8];
           }
       }
       scope 3 (inlined #[track_caller] Option::<Layout>::unwrap) {
@@ -102,16 +101,9 @@
           StorageDead(_16);
           StorageDead(_12);
           StorageDead(_6);
--         StorageLive(_17);
-+         nop;
-          _17 = copy (_5.0: *const [u8]);
--         _4 = move _17 as *mut [u8] (PtrToPtr);
--         StorageDead(_17);
-+         _4 = copy _17 as *mut [u8] (PtrToPtr);
-+         nop;
+          _4 = copy _5 as *mut [u8] (Transmute);
           StorageDead(_5);
--         _3 = move _4 as *mut u8 (PtrToPtr);
-+         _3 = copy _17 as *mut u8 (PtrToPtr);
+          _3 = move _4 as *mut u8 (PtrToPtr);
           StorageDead(_4);
           StorageDead(_3);
 -         StorageDead(_1);
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
index 5fcece2280d..88bd4628c29 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
@@ -20,7 +20,6 @@
           scope 5 (inlined <std::alloc::Global as Allocator>::allocate) {
           }
           scope 6 (inlined NonNull::<[u8]>::as_ptr) {
-              let mut _12: *const [u8];
           }
       }
       scope 3 (inlined #[track_caller] Option::<Layout>::unwrap) {
@@ -45,16 +44,9 @@
   
       bb1: {
           StorageDead(_6);
--         StorageLive(_12);
-+         nop;
-          _12 = copy (_5.0: *const [u8]);
--         _4 = move _12 as *mut [u8] (PtrToPtr);
--         StorageDead(_12);
-+         _4 = copy _12 as *mut [u8] (PtrToPtr);
-+         nop;
+          _4 = copy _5 as *mut [u8] (Transmute);
           StorageDead(_5);
--         _3 = move _4 as *mut u8 (PtrToPtr);
-+         _3 = copy _12 as *mut u8 (PtrToPtr);
+          _3 = move _4 as *mut u8 (PtrToPtr);
           StorageDead(_4);
           StorageDead(_3);
 -         StorageDead(_1);
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
index 13258c17160..ebf305a6f1b 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
@@ -31,7 +31,6 @@
               }
           }
           scope 9 (inlined NonNull::<[u8]>::as_ptr) {
-              let mut _17: *const [u8];
           }
       }
       scope 3 (inlined #[track_caller] Option::<Layout>::unwrap) {
@@ -102,16 +101,9 @@
           StorageDead(_16);
           StorageDead(_12);
           StorageDead(_6);
--         StorageLive(_17);
-+         nop;
-          _17 = copy (_5.0: *const [u8]);
--         _4 = move _17 as *mut [u8] (PtrToPtr);
--         StorageDead(_17);
-+         _4 = copy _17 as *mut [u8] (PtrToPtr);
-+         nop;
+          _4 = copy _5 as *mut [u8] (Transmute);
           StorageDead(_5);
--         _3 = move _4 as *mut u8 (PtrToPtr);
-+         _3 = copy _17 as *mut u8 (PtrToPtr);
+          _3 = move _4 as *mut u8 (PtrToPtr);
           StorageDead(_4);
           StorageDead(_3);
 -         StorageDead(_1);
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
index 0821ea272bf..0c52f1e0583 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
@@ -20,7 +20,6 @@
           scope 5 (inlined <std::alloc::Global as Allocator>::allocate) {
           }
           scope 6 (inlined NonNull::<[u8]>::as_ptr) {
-              let mut _12: *const [u8];
           }
       }
       scope 3 (inlined #[track_caller] Option::<Layout>::unwrap) {
@@ -45,16 +44,9 @@
   
       bb1: {
           StorageDead(_6);
--         StorageLive(_12);
-+         nop;
-          _12 = copy (_5.0: *const [u8]);
--         _4 = move _12 as *mut [u8] (PtrToPtr);
--         StorageDead(_12);
-+         _4 = copy _12 as *mut [u8] (PtrToPtr);
-+         nop;
+          _4 = copy _5 as *mut [u8] (Transmute);
           StorageDead(_5);
--         _3 = move _4 as *mut u8 (PtrToPtr);
-+         _3 = copy _12 as *mut u8 (PtrToPtr);
+          _3 = move _4 as *mut u8 (PtrToPtr);
           StorageDead(_4);
           StorageDead(_3);
 -         StorageDead(_1);
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
index bd56ab67e00..a3308cc5df1 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
@@ -4,28 +4,28 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::slice::Iter<'_, T>;
-    let mut _12: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _13: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _21: std::option::Option<(usize, &T)>;
-    let mut _24: &impl Fn(usize, &T);
-    let mut _25: (usize, &T);
-    let _26: ();
+    let mut _13: std::slice::Iter<'_, T>;
+    let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _15: std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _23: std::option::Option<(usize, &T)>;
+    let mut _26: &impl Fn(usize, &T);
+    let mut _27: (usize, &T);
+    let _28: ();
     scope 1 {
-        debug iter => _13;
-        let _22: usize;
-        let _23: &T;
+        debug iter => _15;
+        let _24: usize;
+        let _25: &T;
         scope 2 {
-            debug i => _22;
-            debug x => _23;
+            debug i => _24;
+            debug x => _25;
         }
         scope 18 (inlined <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next) {
-            let mut _14: &mut std::slice::Iter<'_, T>;
-            let mut _15: std::option::Option<&T>;
-            let mut _19: (usize, bool);
-            let mut _20: (usize, &T);
+            let mut _16: &mut std::slice::Iter<'_, T>;
+            let mut _17: std::option::Option<&T>;
+            let mut _21: (usize, bool);
+            let mut _22: (usize, &T);
             scope 19 {
-                let _18: usize;
+                let _20: usize;
                 scope 24 {
                 }
             }
@@ -40,8 +40,8 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                 }
             }
             scope 25 (inlined <Option<&T> as Try>::branch) {
-                let mut _16: isize;
-                let _17: &T;
+                let mut _18: isize;
+                let _19: &T;
                 scope 26 {
                 }
             }
@@ -50,13 +50,14 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _7: *mut T;
-            let mut _8: *mut T;
-            let mut _10: *const T;
+            let mut _5: std::ptr::NonNull<[T]>;
+            let mut _9: *mut T;
+            let mut _10: *mut T;
+            let mut _12: *const T;
             scope 5 {
-                let _6: std::ptr::NonNull<T>;
+                let _8: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _9: *const T;
+                    let _11: *const T;
                     scope 7 {
                     }
                     scope 12 (inlined without_provenance::<T>) {
@@ -72,7 +73,8 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                     }
                 }
                 scope 10 (inlined NonNull::<[T]>::cast::<T>) {
-                    let mut _5: *const T;
+                    let mut _6: *mut [T];
+                    let mut _7: *const T;
                     scope 11 (inlined NonNull::<[T]>::as_ptr) {
                     }
                 }
@@ -87,76 +89,82 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb0: {
-        StorageLive(_11);
+        StorageLive(_13);
         StorageLive(_3);
-        StorageLive(_6);
-        StorageLive(_4);
-        StorageLive(_5);
+        StorageLive(_8);
         _3 = PtrMetadata(copy _1);
+        StorageLive(_5);
+        StorageLive(_4);
         _4 = &raw const (*_1);
-        _5 = copy _4 as *const T (PtrToPtr);
-        _6 = NonNull::<T> { pointer: copy _5 };
-        StorageLive(_9);
+        _5 = NonNull::<[T]> { pointer: move _4 };
+        StorageDead(_4);
+        StorageLive(_6);
+        StorageLive(_7);
+        _6 = copy _5 as *mut [T] (Transmute);
+        _7 = copy _6 as *const T (PtrToPtr);
+        _8 = NonNull::<T> { pointer: move _7 };
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_5);
+        StorageLive(_11);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_8);
-        StorageLive(_7);
-        _7 = copy _4 as *mut T (PtrToPtr);
-        _8 = Offset(copy _7, copy _3);
-        StorageDead(_7);
-        _9 = move _8 as *const T (PtrToPtr);
-        StorageDead(_8);
+        StorageLive(_10);
+        StorageLive(_9);
+        _9 = copy _8 as *mut T (Transmute);
+        _10 = Offset(copy _9, copy _3);
+        StorageDead(_9);
+        _11 = move _10 as *const T (PtrToPtr);
+        StorageDead(_10);
         goto -> bb3;
     }
 
     bb2: {
-        _9 = copy _3 as *const T (Transmute);
+        _11 = copy _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageLive(_10);
-        _10 = copy _9;
-        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_10);
-        StorageDead(_9);
-        StorageDead(_5);
-        StorageDead(_4);
-        StorageDead(_6);
-        StorageDead(_3);
-        _12 = Enumerate::<std::slice::Iter<'_, T>> { iter: copy _11, count: const 0_usize };
+        StorageLive(_12);
+        _12 = copy _11;
+        _13 = std::slice::Iter::<'_, T> { ptr: copy _8, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_12);
         StorageDead(_11);
-        StorageLive(_13);
-        _13 = copy _12;
+        StorageDead(_8);
+        StorageDead(_3);
+        _14 = Enumerate::<std::slice::Iter<'_, T>> { iter: copy _13, count: const 0_usize };
+        StorageDead(_13);
+        StorageLive(_15);
+        _15 = copy _14;
         goto -> bb4;
     }
 
     bb4: {
+        StorageLive(_23);
+        StorageLive(_20);
         StorageLive(_21);
-        StorageLive(_18);
-        StorageLive(_19);
-        StorageLive(_15);
-        StorageLive(_14);
-        _14 = &mut (_13.0: std::slice::Iter<'_, T>);
-        _15 = <std::slice::Iter<'_, T> as Iterator>::next(move _14) -> [return: bb5, unwind unreachable];
+        StorageLive(_17);
+        StorageLive(_16);
+        _16 = &mut (_15.0: std::slice::Iter<'_, T>);
+        _17 = <std::slice::Iter<'_, T> as Iterator>::next(move _16) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        StorageDead(_14);
-        StorageLive(_16);
-        _16 = discriminant(_15);
-        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb11];
+        StorageDead(_16);
+        StorageLive(_18);
+        _18 = discriminant(_17);
+        switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb11];
     }
 
     bb6: {
-        StorageDead(_16);
-        StorageDead(_15);
-        StorageDead(_19);
         StorageDead(_18);
+        StorageDead(_17);
         StorageDead(_21);
-        StorageDead(_13);
+        StorageDead(_20);
+        StorageDead(_23);
+        StorageDead(_15);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -165,35 +173,35 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb8: {
-        _17 = move ((_15 as Some).0: &T);
-        StorageDead(_16);
-        StorageDead(_15);
-        _18 = copy (_13.1: usize);
-        _19 = AddWithOverflow(copy (_13.1: usize), const 1_usize);
-        assert(!move (_19.1: bool), "attempt to compute `{} + {}`, which would overflow", copy (_13.1: usize), const 1_usize) -> [success: bb9, unwind unreachable];
+        _19 = move ((_17 as Some).0: &T);
+        StorageDead(_18);
+        StorageDead(_17);
+        _20 = copy (_15.1: usize);
+        _21 = AddWithOverflow(copy (_15.1: usize), const 1_usize);
+        assert(!move (_21.1: bool), "attempt to compute `{} + {}`, which would overflow", copy (_15.1: usize), const 1_usize) -> [success: bb9, unwind unreachable];
     }
 
     bb9: {
-        (_13.1: usize) = move (_19.0: usize);
-        StorageLive(_20);
-        _20 = (copy _18, copy _17);
-        _21 = Option::<(usize, &T)>::Some(move _20);
+        (_15.1: usize) = move (_21.0: usize);
+        StorageLive(_22);
+        _22 = (copy _20, copy _19);
+        _23 = Option::<(usize, &T)>::Some(move _22);
+        StorageDead(_22);
+        StorageDead(_21);
         StorageDead(_20);
-        StorageDead(_19);
-        StorageDead(_18);
-        _22 = copy (((_21 as Some).0: (usize, &T)).0: usize);
-        _23 = copy (((_21 as Some).0: (usize, &T)).1: &T);
-        StorageLive(_24);
-        _24 = &_2;
-        StorageLive(_25);
-        _25 = (copy _22, copy _23);
-        _26 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _24, move _25) -> [return: bb10, unwind unreachable];
+        _24 = copy (((_23 as Some).0: (usize, &T)).0: usize);
+        _25 = copy (((_23 as Some).0: (usize, &T)).1: &T);
+        StorageLive(_26);
+        _26 = &_2;
+        StorageLive(_27);
+        _27 = (copy _24, copy _25);
+        _28 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _26, move _27) -> [return: bb10, unwind unreachable];
     }
 
     bb10: {
-        StorageDead(_25);
-        StorageDead(_24);
-        StorageDead(_21);
+        StorageDead(_27);
+        StorageDead(_26);
+        StorageDead(_23);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
index 57f09a4631b..2a837fabd4c 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
@@ -4,34 +4,35 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::slice::Iter<'_, T>;
-    let mut _12: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _13: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _14: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _15: std::option::Option<(usize, &T)>;
-    let mut _16: isize;
-    let mut _19: &impl Fn(usize, &T);
-    let mut _20: (usize, &T);
-    let _21: ();
+    let mut _13: std::slice::Iter<'_, T>;
+    let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _15: std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _16: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _17: std::option::Option<(usize, &T)>;
+    let mut _18: isize;
+    let mut _21: &impl Fn(usize, &T);
+    let mut _22: (usize, &T);
+    let _23: ();
     scope 1 {
-        debug iter => _13;
-        let _17: usize;
-        let _18: &T;
+        debug iter => _15;
+        let _19: usize;
+        let _20: &T;
         scope 2 {
-            debug i => _17;
-            debug x => _18;
+            debug i => _19;
+            debug x => _20;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _7: *mut T;
-            let mut _8: *mut T;
-            let mut _10: *const T;
+            let mut _5: std::ptr::NonNull<[T]>;
+            let mut _9: *mut T;
+            let mut _10: *mut T;
+            let mut _12: *const T;
             scope 5 {
-                let _6: std::ptr::NonNull<T>;
+                let _8: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _9: *const T;
+                    let _11: *const T;
                     scope 7 {
                     }
                     scope 12 (inlined without_provenance::<T>) {
@@ -47,7 +48,8 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                     }
                 }
                 scope 10 (inlined NonNull::<[T]>::cast::<T>) {
-                    let mut _5: *const T;
+                    let mut _6: *mut [T];
+                    let mut _7: *const T;
                     scope 11 (inlined NonNull::<[T]>::as_ptr) {
                     }
                 }
@@ -62,66 +64,72 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb0: {
-        StorageLive(_11);
+        StorageLive(_13);
         StorageLive(_3);
-        StorageLive(_6);
-        StorageLive(_4);
-        StorageLive(_5);
+        StorageLive(_8);
         _3 = PtrMetadata(copy _1);
+        StorageLive(_5);
+        StorageLive(_4);
         _4 = &raw const (*_1);
-        _5 = copy _4 as *const T (PtrToPtr);
-        _6 = NonNull::<T> { pointer: copy _5 };
-        StorageLive(_9);
+        _5 = NonNull::<[T]> { pointer: move _4 };
+        StorageDead(_4);
+        StorageLive(_6);
+        StorageLive(_7);
+        _6 = copy _5 as *mut [T] (Transmute);
+        _7 = copy _6 as *const T (PtrToPtr);
+        _8 = NonNull::<T> { pointer: move _7 };
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_5);
+        StorageLive(_11);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_8);
-        StorageLive(_7);
-        _7 = copy _4 as *mut T (PtrToPtr);
-        _8 = Offset(copy _7, copy _3);
-        StorageDead(_7);
-        _9 = move _8 as *const T (PtrToPtr);
-        StorageDead(_8);
+        StorageLive(_10);
+        StorageLive(_9);
+        _9 = copy _8 as *mut T (Transmute);
+        _10 = Offset(copy _9, copy _3);
+        StorageDead(_9);
+        _11 = move _10 as *const T (PtrToPtr);
+        StorageDead(_10);
         goto -> bb3;
     }
 
     bb2: {
-        _9 = copy _3 as *const T (Transmute);
+        _11 = copy _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageLive(_10);
-        _10 = copy _9;
-        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_10);
-        StorageDead(_9);
-        StorageDead(_5);
-        StorageDead(_4);
-        StorageDead(_6);
-        StorageDead(_3);
-        _12 = Enumerate::<std::slice::Iter<'_, T>> { iter: copy _11, count: const 0_usize };
+        StorageLive(_12);
+        _12 = copy _11;
+        _13 = std::slice::Iter::<'_, T> { ptr: copy _8, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_12);
         StorageDead(_11);
-        StorageLive(_13);
-        _13 = copy _12;
+        StorageDead(_8);
+        StorageDead(_3);
+        _14 = Enumerate::<std::slice::Iter<'_, T>> { iter: copy _13, count: const 0_usize };
+        StorageDead(_13);
+        StorageLive(_15);
+        _15 = copy _14;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_15);
-        _14 = &mut _13;
-        _15 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _14) -> [return: bb5, unwind: bb11];
+        StorageLive(_17);
+        _16 = &mut _15;
+        _17 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _16) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        _16 = discriminant(_15);
-        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
+        _18 = discriminant(_17);
+        switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
+        StorageDead(_17);
         StorageDead(_15);
-        StorageDead(_13);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -130,19 +138,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb8: {
-        _17 = copy (((_15 as Some).0: (usize, &T)).0: usize);
-        _18 = copy (((_15 as Some).0: (usize, &T)).1: &T);
-        StorageLive(_19);
-        _19 = &_2;
-        StorageLive(_20);
-        _20 = (copy _17, copy _18);
-        _21 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _19, move _20) -> [return: bb9, unwind: bb11];
+        _19 = copy (((_17 as Some).0: (usize, &T)).0: usize);
+        _20 = copy (((_17 as Some).0: (usize, &T)).1: &T);
+        StorageLive(_21);
+        _21 = &_2;
+        StorageLive(_22);
+        _22 = (copy _19, copy _20);
+        _23 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _21, move _22) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_20);
-        StorageDead(_19);
-        StorageDead(_15);
+        StorageDead(_22);
+        StorageDead(_21);
+        StorageDead(_17);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
index 4050304f469..063045caebb 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -4,31 +4,32 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::slice::Iter<'_, T>;
-    let mut _12: std::slice::Iter<'_, T>;
-    let mut _13: &mut std::slice::Iter<'_, T>;
-    let mut _14: std::option::Option<&T>;
-    let mut _15: isize;
-    let mut _17: &impl Fn(&T);
-    let mut _18: (&T,);
-    let _19: ();
+    let mut _13: std::slice::Iter<'_, T>;
+    let mut _14: std::slice::Iter<'_, T>;
+    let mut _15: &mut std::slice::Iter<'_, T>;
+    let mut _16: std::option::Option<&T>;
+    let mut _17: isize;
+    let mut _19: &impl Fn(&T);
+    let mut _20: (&T,);
+    let _21: ();
     scope 1 {
-        debug iter => _12;
-        let _16: &T;
+        debug iter => _14;
+        let _18: &T;
         scope 2 {
-            debug x => _16;
+            debug x => _18;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _7: *mut T;
-            let mut _8: *mut T;
-            let mut _10: *const T;
+            let mut _5: std::ptr::NonNull<[T]>;
+            let mut _9: *mut T;
+            let mut _10: *mut T;
+            let mut _12: *const T;
             scope 5 {
-                let _6: std::ptr::NonNull<T>;
+                let _8: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _9: *const T;
+                    let _11: *const T;
                     scope 7 {
                     }
                     scope 12 (inlined without_provenance::<T>) {
@@ -44,7 +45,8 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     }
                 }
                 scope 10 (inlined NonNull::<[T]>::cast::<T>) {
-                    let mut _5: *const T;
+                    let mut _6: *mut [T];
+                    let mut _7: *const T;
                     scope 11 (inlined NonNull::<[T]>::as_ptr) {
                     }
                 }
@@ -56,62 +58,68 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
 
     bb0: {
         StorageLive(_3);
-        StorageLive(_6);
-        StorageLive(_4);
-        StorageLive(_5);
+        StorageLive(_8);
         _3 = PtrMetadata(copy _1);
+        StorageLive(_5);
+        StorageLive(_4);
         _4 = &raw const (*_1);
-        _5 = copy _4 as *const T (PtrToPtr);
-        _6 = NonNull::<T> { pointer: copy _5 };
-        StorageLive(_9);
+        _5 = NonNull::<[T]> { pointer: move _4 };
+        StorageDead(_4);
+        StorageLive(_6);
+        StorageLive(_7);
+        _6 = copy _5 as *mut [T] (Transmute);
+        _7 = copy _6 as *const T (PtrToPtr);
+        _8 = NonNull::<T> { pointer: move _7 };
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_5);
+        StorageLive(_11);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_8);
-        StorageLive(_7);
-        _7 = copy _4 as *mut T (PtrToPtr);
-        _8 = Offset(copy _7, copy _3);
-        StorageDead(_7);
-        _9 = move _8 as *const T (PtrToPtr);
-        StorageDead(_8);
+        StorageLive(_10);
+        StorageLive(_9);
+        _9 = copy _8 as *mut T (Transmute);
+        _10 = Offset(copy _9, copy _3);
+        StorageDead(_9);
+        _11 = move _10 as *const T (PtrToPtr);
+        StorageDead(_10);
         goto -> bb3;
     }
 
     bb2: {
-        _9 = copy _3 as *const T (Transmute);
+        _11 = copy _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageLive(_10);
-        _10 = copy _9;
-        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_10);
-        StorageDead(_9);
-        StorageDead(_5);
-        StorageDead(_4);
-        StorageDead(_6);
-        StorageDead(_3);
         StorageLive(_12);
         _12 = copy _11;
+        _13 = std::slice::Iter::<'_, T> { ptr: copy _8, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_12);
+        StorageDead(_11);
+        StorageDead(_8);
+        StorageDead(_3);
+        StorageLive(_14);
+        _14 = copy _13;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_14);
-        _13 = &mut _12;
-        _14 = <std::slice::Iter<'_, T> as Iterator>::next(move _13) -> [return: bb5, unwind unreachable];
+        StorageLive(_16);
+        _15 = &mut _14;
+        _16 = <std::slice::Iter<'_, T> as Iterator>::next(move _15) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        _15 = discriminant(_14);
-        switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
+        _17 = discriminant(_16);
+        switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
+        StorageDead(_16);
         StorageDead(_14);
-        StorageDead(_12);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -120,18 +128,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _16 = copy ((_14 as Some).0: &T);
-        StorageLive(_17);
-        _17 = &_2;
-        StorageLive(_18);
-        _18 = (copy _16,);
-        _19 = <impl Fn(&T) as Fn<(&T,)>>::call(move _17, move _18) -> [return: bb9, unwind unreachable];
+        _18 = copy ((_16 as Some).0: &T);
+        StorageLive(_19);
+        _19 = &_2;
+        StorageLive(_20);
+        _20 = (copy _18,);
+        _21 = <impl Fn(&T) as Fn<(&T,)>>::call(move _19, move _20) -> [return: bb9, unwind unreachable];
     }
 
     bb9: {
-        StorageDead(_18);
-        StorageDead(_17);
-        StorageDead(_14);
+        StorageDead(_20);
+        StorageDead(_19);
+        StorageDead(_16);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index 2c3d7ab1e4a..d401ed8fcf3 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -4,31 +4,32 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::slice::Iter<'_, T>;
-    let mut _12: std::slice::Iter<'_, T>;
-    let mut _13: &mut std::slice::Iter<'_, T>;
-    let mut _14: std::option::Option<&T>;
-    let mut _15: isize;
-    let mut _17: &impl Fn(&T);
-    let mut _18: (&T,);
-    let _19: ();
+    let mut _13: std::slice::Iter<'_, T>;
+    let mut _14: std::slice::Iter<'_, T>;
+    let mut _15: &mut std::slice::Iter<'_, T>;
+    let mut _16: std::option::Option<&T>;
+    let mut _17: isize;
+    let mut _19: &impl Fn(&T);
+    let mut _20: (&T,);
+    let _21: ();
     scope 1 {
-        debug iter => _12;
-        let _16: &T;
+        debug iter => _14;
+        let _18: &T;
         scope 2 {
-            debug x => _16;
+            debug x => _18;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _7: *mut T;
-            let mut _8: *mut T;
-            let mut _10: *const T;
+            let mut _5: std::ptr::NonNull<[T]>;
+            let mut _9: *mut T;
+            let mut _10: *mut T;
+            let mut _12: *const T;
             scope 5 {
-                let _6: std::ptr::NonNull<T>;
+                let _8: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _9: *const T;
+                    let _11: *const T;
                     scope 7 {
                     }
                     scope 12 (inlined without_provenance::<T>) {
@@ -44,7 +45,8 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     }
                 }
                 scope 10 (inlined NonNull::<[T]>::cast::<T>) {
-                    let mut _5: *const T;
+                    let mut _6: *mut [T];
+                    let mut _7: *const T;
                     scope 11 (inlined NonNull::<[T]>::as_ptr) {
                     }
                 }
@@ -56,62 +58,68 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
 
     bb0: {
         StorageLive(_3);
-        StorageLive(_6);
-        StorageLive(_4);
-        StorageLive(_5);
+        StorageLive(_8);
         _3 = PtrMetadata(copy _1);
+        StorageLive(_5);
+        StorageLive(_4);
         _4 = &raw const (*_1);
-        _5 = copy _4 as *const T (PtrToPtr);
-        _6 = NonNull::<T> { pointer: copy _5 };
-        StorageLive(_9);
+        _5 = NonNull::<[T]> { pointer: move _4 };
+        StorageDead(_4);
+        StorageLive(_6);
+        StorageLive(_7);
+        _6 = copy _5 as *mut [T] (Transmute);
+        _7 = copy _6 as *const T (PtrToPtr);
+        _8 = NonNull::<T> { pointer: move _7 };
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_5);
+        StorageLive(_11);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_8);
-        StorageLive(_7);
-        _7 = copy _4 as *mut T (PtrToPtr);
-        _8 = Offset(copy _7, copy _3);
-        StorageDead(_7);
-        _9 = move _8 as *const T (PtrToPtr);
-        StorageDead(_8);
+        StorageLive(_10);
+        StorageLive(_9);
+        _9 = copy _8 as *mut T (Transmute);
+        _10 = Offset(copy _9, copy _3);
+        StorageDead(_9);
+        _11 = move _10 as *const T (PtrToPtr);
+        StorageDead(_10);
         goto -> bb3;
     }
 
     bb2: {
-        _9 = copy _3 as *const T (Transmute);
+        _11 = copy _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageLive(_10);
-        _10 = copy _9;
-        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_10);
-        StorageDead(_9);
-        StorageDead(_5);
-        StorageDead(_4);
-        StorageDead(_6);
-        StorageDead(_3);
         StorageLive(_12);
         _12 = copy _11;
+        _13 = std::slice::Iter::<'_, T> { ptr: copy _8, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_12);
+        StorageDead(_11);
+        StorageDead(_8);
+        StorageDead(_3);
+        StorageLive(_14);
+        _14 = copy _13;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_14);
-        _13 = &mut _12;
-        _14 = <std::slice::Iter<'_, T> as Iterator>::next(move _13) -> [return: bb5, unwind: bb11];
+        StorageLive(_16);
+        _15 = &mut _14;
+        _16 = <std::slice::Iter<'_, T> as Iterator>::next(move _15) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        _15 = discriminant(_14);
-        switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
+        _17 = discriminant(_16);
+        switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
+        StorageDead(_16);
         StorageDead(_14);
-        StorageDead(_12);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -120,18 +128,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _16 = copy ((_14 as Some).0: &T);
-        StorageLive(_17);
-        _17 = &_2;
-        StorageLive(_18);
-        _18 = (copy _16,);
-        _19 = <impl Fn(&T) as Fn<(&T,)>>::call(move _17, move _18) -> [return: bb9, unwind: bb11];
+        _18 = copy ((_16 as Some).0: &T);
+        StorageLive(_19);
+        _19 = &_2;
+        StorageLive(_20);
+        _20 = (copy _18,);
+        _21 = <impl Fn(&T) as Fn<(&T,)>>::call(move _19, move _20) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_18);
-        StorageDead(_17);
-        StorageDead(_14);
+        StorageDead(_20);
+        StorageDead(_19);
+        StorageDead(_16);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
index a6ccd435c40..deb12c4f1c2 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
@@ -4,34 +4,35 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::slice::Iter<'_, T>;
-    let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _13: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _15: std::option::Option<&T>;
-    let mut _16: isize;
-    let mut _18: &impl Fn(&T);
-    let mut _19: (&T,);
-    let _20: ();
+    let mut _13: std::slice::Iter<'_, T>;
+    let mut _14: std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _15: std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _17: std::option::Option<&T>;
+    let mut _18: isize;
+    let mut _20: &impl Fn(&T);
+    let mut _21: (&T,);
+    let _22: ();
     scope 1 {
-        debug iter => _13;
-        let _17: &T;
+        debug iter => _15;
+        let _19: &T;
         scope 2 {
-            debug x => _17;
+            debug x => _19;
         }
         scope 18 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            let mut _14: &mut std::slice::Iter<'_, T>;
+            let mut _16: &mut std::slice::Iter<'_, T>;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _7: *mut T;
-            let mut _8: *mut T;
-            let mut _10: *const T;
+            let mut _5: std::ptr::NonNull<[T]>;
+            let mut _9: *mut T;
+            let mut _10: *mut T;
+            let mut _12: *const T;
             scope 5 {
-                let _6: std::ptr::NonNull<T>;
+                let _8: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _9: *const T;
+                    let _11: *const T;
                     scope 7 {
                     }
                     scope 12 (inlined without_provenance::<T>) {
@@ -47,7 +48,8 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     }
                 }
                 scope 10 (inlined NonNull::<[T]>::cast::<T>) {
-                    let mut _5: *const T;
+                    let mut _6: *mut [T];
+                    let mut _7: *const T;
                     scope 11 (inlined NonNull::<[T]>::as_ptr) {
                     }
                 }
@@ -62,68 +64,74 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb0: {
-        StorageLive(_11);
+        StorageLive(_13);
         StorageLive(_3);
-        StorageLive(_6);
-        StorageLive(_4);
-        StorageLive(_5);
+        StorageLive(_8);
         _3 = PtrMetadata(copy _1);
+        StorageLive(_5);
+        StorageLive(_4);
         _4 = &raw const (*_1);
-        _5 = copy _4 as *const T (PtrToPtr);
-        _6 = NonNull::<T> { pointer: copy _5 };
-        StorageLive(_9);
+        _5 = NonNull::<[T]> { pointer: move _4 };
+        StorageDead(_4);
+        StorageLive(_6);
+        StorageLive(_7);
+        _6 = copy _5 as *mut [T] (Transmute);
+        _7 = copy _6 as *const T (PtrToPtr);
+        _8 = NonNull::<T> { pointer: move _7 };
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_5);
+        StorageLive(_11);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_8);
-        StorageLive(_7);
-        _7 = copy _4 as *mut T (PtrToPtr);
-        _8 = Offset(copy _7, copy _3);
-        StorageDead(_7);
-        _9 = move _8 as *const T (PtrToPtr);
-        StorageDead(_8);
+        StorageLive(_10);
+        StorageLive(_9);
+        _9 = copy _8 as *mut T (Transmute);
+        _10 = Offset(copy _9, copy _3);
+        StorageDead(_9);
+        _11 = move _10 as *const T (PtrToPtr);
+        StorageDead(_10);
         goto -> bb3;
     }
 
     bb2: {
-        _9 = copy _3 as *const T (Transmute);
+        _11 = copy _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageLive(_10);
-        _10 = copy _9;
-        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_10);
-        StorageDead(_9);
-        StorageDead(_5);
-        StorageDead(_4);
-        StorageDead(_6);
-        StorageDead(_3);
-        _12 = Rev::<std::slice::Iter<'_, T>> { iter: copy _11 };
+        StorageLive(_12);
+        _12 = copy _11;
+        _13 = std::slice::Iter::<'_, T> { ptr: copy _8, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_12);
         StorageDead(_11);
-        StorageLive(_13);
-        _13 = copy _12;
+        StorageDead(_8);
+        StorageDead(_3);
+        _14 = Rev::<std::slice::Iter<'_, T>> { iter: copy _13 };
+        StorageDead(_13);
+        StorageLive(_15);
+        _15 = copy _14;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_15);
-        StorageLive(_14);
-        _14 = &mut (_13.0: std::slice::Iter<'_, T>);
-        _15 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind unreachable];
+        StorageLive(_17);
+        StorageLive(_16);
+        _16 = &mut (_15.0: std::slice::Iter<'_, T>);
+        _17 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _16) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        StorageDead(_14);
-        _16 = discriminant(_15);
-        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_16);
+        _18 = discriminant(_17);
+        switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
+        StorageDead(_17);
         StorageDead(_15);
-        StorageDead(_13);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -132,18 +140,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _17 = copy ((_15 as Some).0: &T);
-        StorageLive(_18);
-        _18 = &_2;
-        StorageLive(_19);
-        _19 = (copy _17,);
-        _20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind unreachable];
+        _19 = copy ((_17 as Some).0: &T);
+        StorageLive(_20);
+        _20 = &_2;
+        StorageLive(_21);
+        _21 = (copy _19,);
+        _22 = <impl Fn(&T) as Fn<(&T,)>>::call(move _20, move _21) -> [return: bb9, unwind unreachable];
     }
 
     bb9: {
-        StorageDead(_19);
-        StorageDead(_18);
-        StorageDead(_15);
+        StorageDead(_21);
+        StorageDead(_20);
+        StorageDead(_17);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
index df11c8e3b49..acd5323eb7a 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
@@ -4,34 +4,35 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _11: std::slice::Iter<'_, T>;
-    let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _13: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _15: std::option::Option<&T>;
-    let mut _16: isize;
-    let mut _18: &impl Fn(&T);
-    let mut _19: (&T,);
-    let _20: ();
+    let mut _13: std::slice::Iter<'_, T>;
+    let mut _14: std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _15: std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _17: std::option::Option<&T>;
+    let mut _18: isize;
+    let mut _20: &impl Fn(&T);
+    let mut _21: (&T,);
+    let _22: ();
     scope 1 {
-        debug iter => _13;
-        let _17: &T;
+        debug iter => _15;
+        let _19: &T;
         scope 2 {
-            debug x => _17;
+            debug x => _19;
         }
         scope 18 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            let mut _14: &mut std::slice::Iter<'_, T>;
+            let mut _16: &mut std::slice::Iter<'_, T>;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             let _3: usize;
-            let mut _7: *mut T;
-            let mut _8: *mut T;
-            let mut _10: *const T;
+            let mut _5: std::ptr::NonNull<[T]>;
+            let mut _9: *mut T;
+            let mut _10: *mut T;
+            let mut _12: *const T;
             scope 5 {
-                let _6: std::ptr::NonNull<T>;
+                let _8: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _9: *const T;
+                    let _11: *const T;
                     scope 7 {
                     }
                     scope 12 (inlined without_provenance::<T>) {
@@ -47,7 +48,8 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     }
                 }
                 scope 10 (inlined NonNull::<[T]>::cast::<T>) {
-                    let mut _5: *const T;
+                    let mut _6: *mut [T];
+                    let mut _7: *const T;
                     scope 11 (inlined NonNull::<[T]>::as_ptr) {
                     }
                 }
@@ -62,68 +64,74 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb0: {
-        StorageLive(_11);
+        StorageLive(_13);
         StorageLive(_3);
-        StorageLive(_6);
-        StorageLive(_4);
-        StorageLive(_5);
+        StorageLive(_8);
         _3 = PtrMetadata(copy _1);
+        StorageLive(_5);
+        StorageLive(_4);
         _4 = &raw const (*_1);
-        _5 = copy _4 as *const T (PtrToPtr);
-        _6 = NonNull::<T> { pointer: copy _5 };
-        StorageLive(_9);
+        _5 = NonNull::<[T]> { pointer: move _4 };
+        StorageDead(_4);
+        StorageLive(_6);
+        StorageLive(_7);
+        _6 = copy _5 as *mut [T] (Transmute);
+        _7 = copy _6 as *const T (PtrToPtr);
+        _8 = NonNull::<T> { pointer: move _7 };
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_5);
+        StorageLive(_11);
         switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_8);
-        StorageLive(_7);
-        _7 = copy _4 as *mut T (PtrToPtr);
-        _8 = Offset(copy _7, copy _3);
-        StorageDead(_7);
-        _9 = move _8 as *const T (PtrToPtr);
-        StorageDead(_8);
+        StorageLive(_10);
+        StorageLive(_9);
+        _9 = copy _8 as *mut T (Transmute);
+        _10 = Offset(copy _9, copy _3);
+        StorageDead(_9);
+        _11 = move _10 as *const T (PtrToPtr);
+        StorageDead(_10);
         goto -> bb3;
     }
 
     bb2: {
-        _9 = copy _3 as *const T (Transmute);
+        _11 = copy _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageLive(_10);
-        _10 = copy _9;
-        _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_10);
-        StorageDead(_9);
-        StorageDead(_5);
-        StorageDead(_4);
-        StorageDead(_6);
-        StorageDead(_3);
-        _12 = Rev::<std::slice::Iter<'_, T>> { iter: copy _11 };
+        StorageLive(_12);
+        _12 = copy _11;
+        _13 = std::slice::Iter::<'_, T> { ptr: copy _8, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_12);
         StorageDead(_11);
-        StorageLive(_13);
-        _13 = copy _12;
+        StorageDead(_8);
+        StorageDead(_3);
+        _14 = Rev::<std::slice::Iter<'_, T>> { iter: copy _13 };
+        StorageDead(_13);
+        StorageLive(_15);
+        _15 = copy _14;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_15);
-        StorageLive(_14);
-        _14 = &mut (_13.0: std::slice::Iter<'_, T>);
-        _15 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind: bb11];
+        StorageLive(_17);
+        StorageLive(_16);
+        _16 = &mut (_15.0: std::slice::Iter<'_, T>);
+        _17 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _16) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        StorageDead(_14);
-        _16 = discriminant(_15);
-        switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_16);
+        _18 = discriminant(_17);
+        switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
+        StorageDead(_17);
         StorageDead(_15);
-        StorageDead(_13);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -132,18 +140,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _17 = copy ((_15 as Some).0: &T);
-        StorageLive(_18);
-        _18 = &_2;
-        StorageLive(_19);
-        _19 = (copy _17,);
-        _20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind: bb11];
+        _19 = copy ((_17 as Some).0: &T);
+        StorageLive(_20);
+        _20 = &_2;
+        StorageLive(_21);
+        _21 = (copy _19,);
+        _22 = <impl Fn(&T) as Fn<(&T,)>>::call(move _20, move _21) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_19);
-        StorageDead(_18);
-        StorageDead(_15);
+        StorageDead(_21);
+        StorageDead(_20);
+        StorageDead(_17);
         goto -> bb4;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir
index f8b0e749bfc..22be48c47b2 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir
@@ -15,11 +15,11 @@ fn slice_iter_generic_is_empty(_1: &std::slice::Iter<'_, T>) -> bool {
             scope 4 {
                 scope 8 (inlined <NonNull<T> as PartialEq>::eq) {
                     let mut _5: std::ptr::NonNull<T>;
+                    let mut _6: *mut T;
+                    let mut _7: *mut T;
                     scope 9 (inlined NonNull::<T>::as_ptr) {
-                        let mut _6: *const T;
                     }
                     scope 10 (inlined NonNull::<T>::as_ptr) {
-                        let mut _7: *const T;
                     }
                 }
             }
@@ -48,13 +48,13 @@ fn slice_iter_generic_is_empty(_1: &std::slice::Iter<'_, T>) -> bool {
         _4 = copy (*_3);
         StorageDead(_3);
         StorageLive(_6);
-        StorageLive(_7);
         StorageLive(_5);
         _5 = copy ((*_1).0: std::ptr::NonNull<T>);
-        _6 = copy (_5.0: *const T);
+        _6 = copy _5 as *mut T (Transmute);
         StorageDead(_5);
-        _7 = copy (_4.0: *const T);
-        _0 = Eq(copy _6, copy _7);
+        StorageLive(_7);
+        _7 = copy _4 as *mut T (Transmute);
+        _0 = Eq(move _6, move _7);
         StorageDead(_7);
         StorageDead(_6);
         goto -> bb3;
diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir
index f8b0e749bfc..22be48c47b2 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir
@@ -15,11 +15,11 @@ fn slice_iter_generic_is_empty(_1: &std::slice::Iter<'_, T>) -> bool {
             scope 4 {
                 scope 8 (inlined <NonNull<T> as PartialEq>::eq) {
                     let mut _5: std::ptr::NonNull<T>;
+                    let mut _6: *mut T;
+                    let mut _7: *mut T;
                     scope 9 (inlined NonNull::<T>::as_ptr) {
-                        let mut _6: *const T;
                     }
                     scope 10 (inlined NonNull::<T>::as_ptr) {
-                        let mut _7: *const T;
                     }
                 }
             }
@@ -48,13 +48,13 @@ fn slice_iter_generic_is_empty(_1: &std::slice::Iter<'_, T>) -> bool {
         _4 = copy (*_3);
         StorageDead(_3);
         StorageLive(_6);
-        StorageLive(_7);
         StorageLive(_5);
         _5 = copy ((*_1).0: std::ptr::NonNull<T>);
-        _6 = copy (_5.0: *const T);
+        _6 = copy _5 as *mut T (Transmute);
         StorageDead(_5);
-        _7 = copy (_4.0: *const T);
-        _0 = Eq(copy _6, copy _7);
+        StorageLive(_7);
+        _7 = copy _4 as *mut T (Transmute);
+        _0 = Eq(move _6, move _7);
         StorageDead(_7);
         StorageDead(_6);
         goto -> bb3;
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 c3091bd4395..2efbb6d9904 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,16 +7,18 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         debug self => _1;
         scope 2 (inlined Vec::<u8>::as_slice) {
             debug self => _1;
-            let mut _7: usize;
+            let mut _9: *const u8;
+            let mut _10: usize;
             scope 3 (inlined Vec::<u8>::as_ptr) {
                 debug self => _1;
                 let mut _2: &alloc::raw_vec::RawVec<u8>;
+                let mut _8: *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 _6: std::ptr::NonNull<u8>;
+                        let mut _7: std::ptr::NonNull<u8>;
                         scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
                             debug self => _3;
                             let mut _4: std::ptr::NonNull<u8>;
@@ -25,27 +27,28 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                                 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;
                                     scope 9 (inlined NonNull::<u8>::as_ptr) {
                                         debug self => _4;
-                                        let mut _5: *const u8;
                                     }
                                 }
                             }
                             scope 10 (inlined Unique::<u8>::as_non_null_ptr) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _6;
+                                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 => _6;
+                            debug self => _7;
                         }
                     }
                 }
             }
             scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
-                debug data => _5;
-                debug len => _7;
-                let _8: *const [u8];
+                debug data => _9;
+                debug len => _10;
+                let _11: *const [u8];
                 scope 13 (inlined core::ub_checks::check_language_ub) {
                     scope 14 (inlined core::ub_checks::check_language_ub::runtime) {
                     }
@@ -55,11 +58,11 @@ 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 => _5;
-                    debug len => _7;
+                    debug data => _9;
+                    debug len => _10;
                     scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
-                        debug data_pointer => _5;
-                        debug metadata => _7;
+                        debug data_pointer => _9;
+                        debug metadata => _10;
                     }
                 }
             }
@@ -67,26 +70,37 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
     }
 
     bb0: {
+        StorageLive(_8);
+        StorageLive(_9);
         StorageLive(_2);
         _2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
         StorageLive(_3);
         _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
-        StorageLive(_6);
+        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>);
-        _5 = copy (_4.0: *const u8);
-        _6 = NonNull::<u8> { pointer: copy _5 };
-        StorageDead(_4);
+        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);
+        StorageDead(_4);
+        _8 = copy _7 as *mut u8 (Transmute);
+        StorageDead(_7);
         StorageDead(_3);
+        _9 = copy _8 as *const u8 (PtrToPtr);
         StorageDead(_2);
-        StorageLive(_7);
-        _7 = copy ((*_1).1: usize);
-        StorageLive(_8);
-        _8 = *const [u8] from (copy _5, copy _7);
-        _0 = &(*_8);
+        StorageLive(_10);
+        _10 = copy ((*_1).1: usize);
+        StorageLive(_11);
+        _11 = *const [u8] from (copy _9, copy _10);
+        _0 = &(*_11);
+        StorageDead(_11);
+        StorageDead(_10);
+        StorageDead(_9);
         StorageDead(_8);
-        StorageDead(_7);
         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 c3091bd4395..2efbb6d9904 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,16 +7,18 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         debug self => _1;
         scope 2 (inlined Vec::<u8>::as_slice) {
             debug self => _1;
-            let mut _7: usize;
+            let mut _9: *const u8;
+            let mut _10: usize;
             scope 3 (inlined Vec::<u8>::as_ptr) {
                 debug self => _1;
                 let mut _2: &alloc::raw_vec::RawVec<u8>;
+                let mut _8: *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 _6: std::ptr::NonNull<u8>;
+                        let mut _7: std::ptr::NonNull<u8>;
                         scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
                             debug self => _3;
                             let mut _4: std::ptr::NonNull<u8>;
@@ -25,27 +27,28 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                                 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;
                                     scope 9 (inlined NonNull::<u8>::as_ptr) {
                                         debug self => _4;
-                                        let mut _5: *const u8;
                                     }
                                 }
                             }
                             scope 10 (inlined Unique::<u8>::as_non_null_ptr) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _6;
+                                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 => _6;
+                            debug self => _7;
                         }
                     }
                 }
             }
             scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
-                debug data => _5;
-                debug len => _7;
-                let _8: *const [u8];
+                debug data => _9;
+                debug len => _10;
+                let _11: *const [u8];
                 scope 13 (inlined core::ub_checks::check_language_ub) {
                     scope 14 (inlined core::ub_checks::check_language_ub::runtime) {
                     }
@@ -55,11 +58,11 @@ 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 => _5;
-                    debug len => _7;
+                    debug data => _9;
+                    debug len => _10;
                     scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
-                        debug data_pointer => _5;
-                        debug metadata => _7;
+                        debug data_pointer => _9;
+                        debug metadata => _10;
                     }
                 }
             }
@@ -67,26 +70,37 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
     }
 
     bb0: {
+        StorageLive(_8);
+        StorageLive(_9);
         StorageLive(_2);
         _2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
         StorageLive(_3);
         _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
-        StorageLive(_6);
+        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>);
-        _5 = copy (_4.0: *const u8);
-        _6 = NonNull::<u8> { pointer: copy _5 };
-        StorageDead(_4);
+        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);
+        StorageDead(_4);
+        _8 = copy _7 as *mut u8 (Transmute);
+        StorageDead(_7);
         StorageDead(_3);
+        _9 = copy _8 as *const u8 (PtrToPtr);
         StorageDead(_2);
-        StorageLive(_7);
-        _7 = copy ((*_1).1: usize);
-        StorageLive(_8);
-        _8 = *const [u8] from (copy _5, copy _7);
-        _0 = &(*_8);
+        StorageLive(_10);
+        _10 = copy ((*_1).1: usize);
+        StorageLive(_11);
+        _11 = *const [u8] from (copy _9, copy _10);
+        _0 = &(*_11);
+        StorageDead(_11);
+        StorageDead(_10);
+        StorageDead(_9);
         StorageDead(_8);
-        StorageDead(_7);
         return;
     }
 }
diff --git a/tests/run-make/apple-deployment-target/rmake.rs b/tests/run-make/apple-deployment-target/rmake.rs
index fed6d310770..0ae95cb1f4b 100644
--- a/tests/run-make/apple-deployment-target/rmake.rs
+++ b/tests/run-make/apple-deployment-target/rmake.rs
@@ -24,21 +24,31 @@ fn minos(file: &str, version: &str) {
 
 fn main() {
     // These versions should generally be higher than the default versions
-    let (env_var, example_version, higher_example_version) = match apple_os() {
-        "macos" => ("MACOSX_DEPLOYMENT_TARGET", "12.0", "13.0"),
+    let (example_version, higher_example_version) = match apple_os() {
+        "macos" => ("12.0", "13.0"),
         // armv7s-apple-ios and i386-apple-ios only supports iOS 10.0
-        "ios" if target() == "armv7s-apple-ios" || target() == "i386-apple-ios" => {
-            ("IPHONEOS_DEPLOYMENT_TARGET", "10.0", "10.0")
-        }
-        "ios" => ("IPHONEOS_DEPLOYMENT_TARGET", "15.0", "16.0"),
-        "watchos" => ("WATCHOS_DEPLOYMENT_TARGET", "7.0", "9.0"),
-        "tvos" => ("TVOS_DEPLOYMENT_TARGET", "14.0", "15.0"),
-        "visionos" => ("XROS_DEPLOYMENT_TARGET", "1.1", "1.2"),
+        "ios" if target() == "armv7s-apple-ios" || target() == "i386-apple-ios" => ("10.0", "10.0"),
+        "ios" => ("15.0", "16.0"),
+        "watchos" => ("7.0", "9.0"),
+        "tvos" => ("14.0", "15.0"),
+        "visionos" => ("1.1", "1.2"),
         _ => unreachable!(),
     };
-    let default_version =
-        rustc().target(target()).env_remove(env_var).print("deployment-target").run().stdout_utf8();
-    let default_version = default_version.strip_prefix("deployment_target=").unwrap().trim();
+
+    // Remove env vars to get `rustc`'s default
+    let output = rustc()
+        .target(target())
+        .env_remove("MACOSX_DEPLOYMENT_TARGET")
+        .env_remove("IPHONEOS_DEPLOYMENT_TARGET")
+        .env_remove("WATCHOS_DEPLOYMENT_TARGET")
+        .env_remove("TVOS_DEPLOYMENT_TARGET")
+        .env_remove("XROS_DEPLOYMENT_TARGET")
+        .print("deployment-target")
+        .run()
+        .stdout_utf8();
+    let (env_var, default_version) = output.split_once('=').unwrap();
+    let env_var = env_var.trim();
+    let default_version = default_version.trim();
 
     // Test that version makes it to the object file.
     run_in_tmpdir(|| {
diff --git a/tests/run-make/apple-sdk-version/rmake.rs b/tests/run-make/apple-sdk-version/rmake.rs
index 6463ec00403..43e80577204 100644
--- a/tests/run-make/apple-sdk-version/rmake.rs
+++ b/tests/run-make/apple-sdk-version/rmake.rs
@@ -26,8 +26,7 @@ fn main() {
     // Fetch rustc's inferred deployment target.
     let current_deployment_target =
         rustc().target(target()).print("deployment-target").run().stdout_utf8();
-    let current_deployment_target =
-        current_deployment_target.strip_prefix("deployment_target=").unwrap().trim();
+    let current_deployment_target = current_deployment_target.split('=').last().unwrap().trim();
 
     // Fetch current SDK version via. xcrun.
     //
diff --git a/tests/run-make/libtest-thread-limit/rmake.rs b/tests/run-make/libtest-thread-limit/rmake.rs
index 5decd802b34..fe14d2c046c 100644
--- a/tests/run-make/libtest-thread-limit/rmake.rs
+++ b/tests/run-make/libtest-thread-limit/rmake.rs
@@ -38,7 +38,7 @@ fn main() {
     // If the process ID is 0, this is the child process responsible for running the test
     // program.
     if pid == 0 {
-        let test = CString::new("test").unwrap();
+        let test = c"test";
         // The argv array should be terminated with a NULL pointer.
         let argv = [test.as_ptr(), std::ptr::null()];
         // rlim_cur is soft limit, rlim_max is hard limit.
diff --git a/tests/rustdoc-json/impls/trait-for-dyn-trait.rs b/tests/rustdoc-json/impls/trait-for-dyn-trait.rs
new file mode 100644
index 00000000000..0fbb4df0028
--- /dev/null
+++ b/tests/rustdoc-json/impls/trait-for-dyn-trait.rs
@@ -0,0 +1,15 @@
+//@ set t1 = '$.index[*][?(@.name=="T1")].id'
+pub trait T1 {}
+
+//@ set t2 = '$.index[*][?(@.name=="T2")].id'
+pub trait T2 {}
+
+/// Fun impl
+impl T1 for dyn T2 {}
+
+//@ set impl = '$.index[*][?(@.docs=="Fun impl")].id'
+//@ is '$.index[*][?(@.name=="T1")].inner.trait.implementations[*]' $impl
+//@ is '$.index[*][?(@.name=="T2")].inner.trait.implementations' []
+
+//@ is '$.index[*][?(@.docs=="Fun impl")].inner.impl.trait.id' $t1
+//@ is '$.index[*][?(@.docs=="Fun impl")].inner.impl.for.dyn_trait.traits[*].trait.id' $t2
diff --git a/tests/rustdoc-json/statics/extern.rs b/tests/rustdoc-json/statics/extern.rs
new file mode 100644
index 00000000000..d38fdf1cd1c
--- /dev/null
+++ b/tests/rustdoc-json/statics/extern.rs
@@ -0,0 +1,39 @@
+// ignore-tidy-linelength
+//@ edition: 2021
+
+extern "C" {
+    //@ is '$.index[*][?(@.name=="A")].inner.static.is_unsafe'  true
+    //@ is '$.index[*][?(@.name=="A")].inner.static.is_mutable' false
+    pub static A: i32;
+    //@ is '$.index[*][?(@.name=="B")].inner.static.is_unsafe'  true
+    //@ is '$.index[*][?(@.name=="B")].inner.static.is_mutable' true
+    pub static mut B: i32;
+
+    // items in unadorned `extern` blocks cannot have safety qualifiers
+}
+
+unsafe extern "C" {
+    //@ is '$.index[*][?(@.name=="C")].inner.static.is_unsafe'  true
+    //@ is '$.index[*][?(@.name=="C")].inner.static.is_mutable' false
+    pub static C: i32;
+    //@ is '$.index[*][?(@.name=="D")].inner.static.is_unsafe'  true
+    //@ is '$.index[*][?(@.name=="D")].inner.static.is_mutable' true
+    pub static mut D: i32;
+
+    //@ is '$.index[*][?(@.name=="E")].inner.static.is_unsafe'  false
+    //@ is '$.index[*][?(@.name=="E")].inner.static.is_mutable' false
+    pub safe static E: i32;
+    //@ is '$.index[*][?(@.name=="F")].inner.static.is_unsafe'  false
+    //@ is '$.index[*][?(@.name=="F")].inner.static.is_mutable' true
+    pub safe static mut F: i32;
+
+    //@ is '$.index[*][?(@.name=="G")].inner.static.is_unsafe'  true
+    //@ is '$.index[*][?(@.name=="G")].inner.static.is_mutable' false
+    pub unsafe static G: i32;
+    //@ is '$.index[*][?(@.name=="H")].inner.static.is_unsafe'  true
+    //@ is '$.index[*][?(@.name=="H")].inner.static.is_mutable' true
+    pub unsafe static mut H: i32;
+}
+
+//@ ismany '$.index[*][?(@.inner.static)].inner.static.expr' '""' '""' '""' '""' '""' '""' '""' '""'
+//@ ismany '$.index[*][?(@.inner.static)].inner.static.type.primitive' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"'
diff --git a/tests/rustdoc-json/statics/statics.rs b/tests/rustdoc-json/statics/statics.rs
new file mode 100644
index 00000000000..a8af23cc87d
--- /dev/null
+++ b/tests/rustdoc-json/statics/statics.rs
@@ -0,0 +1,12 @@
+//@ is '$.index[*][?(@.name=="A")].inner.static.type.primitive' '"i32"'
+//@ is '$.index[*][?(@.name=="A")].inner.static.is_mutable' false
+//@ is '$.index[*][?(@.name=="A")].inner.static.expr' '"5"'
+//@ is '$.index[*][?(@.name=="A")].inner.static.is_unsafe' false
+pub static A: i32 = 5;
+
+//@ is '$.index[*][?(@.name=="B")].inner.static.type.primitive' '"u32"'
+//@ is '$.index[*][?(@.name=="B")].inner.static.is_mutable' true
+// Expr value isn't gaurenteed, it'd be fine to change it.
+//@ is '$.index[*][?(@.name=="B")].inner.static.expr' '"_"'
+//@ is '$.index[*][?(@.name=="B")].inner.static.is_unsafe' false
+pub static mut B: u32 = 2 + 3;
diff --git a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs
new file mode 100644
index 00000000000..b83e576076d
--- /dev/null
+++ b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs
@@ -0,0 +1,228 @@
+//@ run-pass
+//@ ignore-cross-compile
+
+// This test covers the AST pretty-printer's automatic insertion of parentheses
+// into unparenthesized syntax trees according to precedence and various grammar
+// restrictions and edge cases.
+//
+// For example if the following syntax tree represents the expression a*(b+c),
+// in which the parenthesis is necessary for precedence:
+//
+//     Binary('*', Path("a"), Paren(Binary('+', Path("b"), Path("c"))))
+//
+// then the pretty-printer needs to be able to print the following
+// unparenthesized syntax tree with an automatically inserted parenthesization.
+//
+//     Binary('*', Path("a"), Binary('+', Path("b"), Path("c")))
+//
+// Handling this correctly is relevant in real-world code when pretty-printing
+// macro-generated syntax trees, in which expressions can get interpolated into
+// one another without any parenthesization being visible in the syntax tree.
+//
+//     macro_rules! repro {
+//         ($rhs:expr) => {
+//             a * $rhs
+//         };
+//     }
+//
+//     let _ = repro!(b + c);
+
+#![feature(rustc_private)]
+
+extern crate rustc_ast;
+extern crate rustc_ast_pretty;
+extern crate rustc_driver;
+extern crate rustc_errors;
+extern crate rustc_parse;
+extern crate rustc_session;
+extern crate rustc_span;
+
+use std::mem;
+use std::process::ExitCode;
+
+use rustc_ast::ast::{DUMMY_NODE_ID, Expr, ExprKind};
+use rustc_ast::mut_visit::{self, DummyAstNode as _, MutVisitor};
+use rustc_ast::node_id::NodeId;
+use rustc_ast::ptr::P;
+use rustc_ast_pretty::pprust;
+use rustc_errors::Diag;
+use rustc_parse::parser::Recovery;
+use rustc_session::parse::ParseSess;
+use rustc_span::{DUMMY_SP, FileName, Span};
+
+// Every parenthesis in the following expressions is re-inserted by the
+// pretty-printer.
+//
+// FIXME: Some of them shouldn't be.
+static EXPRS: &[&str] = &[
+    // Straightforward binary operator precedence.
+    "2 * 2 + 2",
+    "2 + 2 * 2",
+    "(2 + 2) * 2",
+    "2 * (2 + 2)",
+    "2 + 2 + 2",
+    // Return has lower precedence than a binary operator.
+    "(return 2) + 2",
+    "2 + (return 2)", // FIXME: no parenthesis needed.
+    "(return) + 2",   // FIXME: no parenthesis needed.
+    // These mean different things.
+    "return - 2",
+    "(return) - 2",
+    // These mean different things.
+    "if let _ = true && false {}",
+    "if let _ = (true && false) {}",
+    // Conditions end at the first curly brace, so struct expressions need to be
+    // parenthesized. Except in a match guard, where conditions end at arrow.
+    "if let _ = (Struct {}) {}",
+    "match 2 { _ if let _ = Struct {} => {} }",
+    // Match arms terminate eagerly, so parenthesization is needed around some
+    // expressions.
+    "match 2 { _ => 1 - 1 }",
+    "match 2 { _ => ({ 1 }) - 1 }",
+    // Grammar restriction: break value starting with a labeled loop is not
+    // allowed, except if the break is also labeled.
+    "break 'outer 'inner: loop {} + 2",
+    "break ('inner: loop {} + 2)",
+    // Grammar restriction: the value in let-else is not allowed to end in a
+    // curly brace.
+    "{ let _ = 1 + 1 else {}; }",
+    "{ let _ = (loop {}) else {}; }",
+    "{ let _ = mac!() else {}; }",
+    "{ let _ = (mac! {}) else {}; }",
+    // Parentheses are necessary to prevent an eager statement boundary.
+    "{ 2 - 1 }",
+    "{ (match 2 {}) - 1 }",
+    "{ (match 2 {})() - 1 }",
+    "{ (match 2 {})[0] - 1 }",
+    "{ (loop {}) - 1 }",
+    // Angle bracket is eagerly parsed as a path's generic argument list.
+    "(2 as T) < U",
+    "(2 as T<U>) < V", // FIXME: no parentheses needed.
+    /*
+    // FIXME: pretty-printer produces invalid syntax. `2 + 2 as T < U`
+    "(2 + 2 as T) < U",
+    */
+    /*
+    // FIXME: pretty-printer produces invalid syntax. `if (let _ = () && Struct {}.x) {}`
+    "if let _ = () && (Struct {}).x {}",
+    */
+    /*
+    // FIXME: pretty-printer produces invalid syntax. `(1 < 2 == false) as usize`
+    "((1 < 2) == false) as usize",
+    */
+    /*
+    // FIXME: pretty-printer produces invalid syntax. `for _ in 1..{ 2 } {}`
+    "for _ in (1..{ 2 }) {}",
+    */
+    /*
+    // FIXME: pretty-printer loses the attribute. `{ let Struct { field } = s; }`
+    "{ let Struct { #[attr] field } = s; }",
+    */
+    /*
+    // FIXME: pretty-printer turns this into a range. `0..to_string()`
+    "(0.).to_string()",
+    "0. .. 1.",
+    */
+    /*
+    // FIXME: pretty-printer loses the dyn*. `i as Trait`
+    "i as dyn* Trait",
+    */
+];
+
+// Flatten the content of parenthesis nodes into their parent node. For example
+// this syntax tree representing the expression a*(b+c):
+//
+//     Binary('*', Path("a"), Paren(Binary('+', Path("b"), Path("c"))))
+//
+// would unparenthesize to:
+//
+//     Binary('*', Path("a"), Binary('+', Path("b"), Path("c")))
+struct Unparenthesize;
+
+impl MutVisitor for Unparenthesize {
+    fn visit_expr(&mut self, e: &mut P<Expr>) {
+        while let ExprKind::Paren(paren) = &mut e.kind {
+            **e = mem::replace(&mut *paren, Expr::dummy());
+        }
+        mut_visit::walk_expr(self, e);
+    }
+}
+
+// Erase Span information that could distinguish between identical expressions
+// parsed from different source strings.
+struct Normalize;
+
+impl MutVisitor for Normalize {
+    const VISIT_TOKENS: bool = true;
+
+    fn visit_id(&mut self, id: &mut NodeId) {
+        *id = DUMMY_NODE_ID;
+    }
+
+    fn visit_span(&mut self, span: &mut Span) {
+        *span = DUMMY_SP;
+    }
+}
+
+fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<P<Expr>> {
+    let parser = rustc_parse::unwrap_or_emit_fatal(rustc_parse::new_parser_from_source_str(
+        psess,
+        FileName::anon_source_code(source_code),
+        source_code.to_owned(),
+    ));
+
+    let mut expr = parser.recovery(Recovery::Forbidden).parse_expr().map_err(Diag::cancel).ok()?;
+    Normalize.visit_expr(&mut expr);
+    Some(expr)
+}
+
+fn main() -> ExitCode {
+    let mut status = ExitCode::SUCCESS;
+    let mut fail = |description: &str, before: &str, after: &str| {
+        status = ExitCode::FAILURE;
+        eprint!(
+            "{description}\n  BEFORE: {before}\n   AFTER: {after}\n\n",
+            before = before.replace('\n', "\n          "),
+            after = after.replace('\n', "\n          "),
+        );
+    };
+
+    rustc_span::create_default_session_globals_then(|| {
+        let psess = &ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE]);
+
+        for &source_code in EXPRS {
+            let expr = parse_expr(psess, source_code).unwrap();
+
+            // Check for FALSE POSITIVE: pretty-printer inserting parentheses where not needed.
+            // Pseudocode:
+            //   assert(expr == parse(print(expr)))
+            let printed = &pprust::expr_to_string(&expr);
+            let Some(expr2) = parse_expr(psess, printed) else {
+                fail("Pretty-printer produced invalid syntax", source_code, printed);
+                continue;
+            };
+            if format!("{expr:#?}") != format!("{expr2:#?}") {
+                fail("Pretty-printer inserted unnecessary parenthesis", source_code, printed);
+                continue;
+            }
+
+            // Check for FALSE NEGATIVE: pretty-printer failing to place necessary parentheses.
+            // Pseudocode:
+            //   assert(unparenthesize(expr) == unparenthesize(parse(print(unparenthesize(expr)))))
+            let mut expr = expr;
+            Unparenthesize.visit_expr(&mut expr);
+            let printed = &pprust::expr_to_string(&expr);
+            let Some(mut expr2) = parse_expr(psess, printed) else {
+                fail("Pretty-printer with no parens produced invalid syntax", source_code, printed);
+                continue;
+            };
+            Unparenthesize.visit_expr(&mut expr2);
+            if format!("{expr:#?}") != format!("{expr2:#?}") {
+                fail("Pretty-printer lost necessary parentheses", source_code, printed);
+                continue;
+            }
+        }
+    });
+
+    status
+}
diff --git a/tests/ui/README.md b/tests/ui/README.md
index c14d0ee78c8..aa36481ae06 100644
--- a/tests/ui/README.md
+++ b/tests/ui/README.md
@@ -6,9 +6,9 @@ This folder contains `rustc`'s
 ## Test Directives (Headers)
 
 Typically, a UI test will have some test directives / headers which are
-special comments that tell compiletest how to build and intepret a test.
+special comments that tell compiletest how to build and interpret a test.
 
-As part of an on-going effort to rewrite compiletest
+As part of an ongoing effort to rewrite compiletest
 (see <https://github.com/rust-lang/compiler-team/issues/536>), a major
 change proposal to change legacy compiletest-style headers `// <directive>`
 to [`ui_test`](https://github.com/oli-obk/ui_test)-style headers
@@ -30,6 +30,6 @@ but in `ui_test` style, the header would be written as
 
 compiletest is changed to accept only `//@` directives for UI tests
 (currently), and will reject and report an error if it encounters any
-comments `// <content>` that may be parsed as an legacy compiletest-style
+comments `// <content>` that may be parsed as a legacy compiletest-style
 test header. To fix this, you should migrate to the `ui_test`-style header
 `//@ <content>`.
diff --git a/tests/ui/associated-consts/associated-const-type-parameter-pattern.rs b/tests/ui/associated-consts/associated-const-type-parameter-pattern.rs
index b5798adc71c..e6c80a7e54e 100644
--- a/tests/ui/associated-consts/associated-const-type-parameter-pattern.rs
+++ b/tests/ui/associated-consts/associated-const-type-parameter-pattern.rs
@@ -18,17 +18,17 @@ impl Foo for Def {
 pub fn test<A: Foo, B: Foo>(arg: EFoo) {
     match arg {
         A::X => println!("A::X"),
-        //~^ error: constant pattern depends on a generic parameter
+        //~^ ERROR constant pattern cannot depend on generic parameters
         B::X => println!("B::X"),
-        //~^ error: constant pattern depends on a generic parameter
+        //~^ ERROR constant pattern cannot depend on generic parameters
         _ => (),
     }
 }
 
 pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
-    //~^ ERROR constant pattern depends on a generic parameter
+    //~^ ERROR constant pattern cannot depend on generic parameters
     let A::X = arg;
-    //~^ ERROR constant pattern depends on a generic parameter
+    //~^ ERROR constant pattern cannot depend on generic parameters
 }
 
 fn main() {
diff --git a/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr b/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr
index adc8f399207..a8256f775a6 100644
--- a/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr
+++ b/tests/ui/associated-consts/associated-const-type-parameter-pattern.stderr
@@ -1,26 +1,57 @@
-error[E0158]: constant pattern depends on a generic parameter
+error[E0158]: constant pattern cannot depend on generic parameters
   --> $DIR/associated-const-type-parameter-pattern.rs:20:9
    |
+LL | pub trait Foo {
+   | -------------
+LL |     const X: EFoo;
+   |     ------------- constant defined here
+...
+LL | pub fn test<A: Foo, B: Foo>(arg: EFoo) {
+   |             - constant depends on this generic parameter
+LL |     match arg {
 LL |         A::X => println!("A::X"),
-   |         ^^^^
+   |         ^^^^ `const` depends on a generic parameter
 
-error[E0158]: constant pattern depends on a generic parameter
+error[E0158]: constant pattern cannot depend on generic parameters
   --> $DIR/associated-const-type-parameter-pattern.rs:22:9
    |
+LL | pub trait Foo {
+   | -------------
+LL |     const X: EFoo;
+   |     ------------- constant defined here
+...
+LL | pub fn test<A: Foo, B: Foo>(arg: EFoo) {
+   |                     - constant depends on this generic parameter
+...
 LL |         B::X => println!("B::X"),
-   |         ^^^^
+   |         ^^^^ `const` depends on a generic parameter
 
-error[E0158]: constant pattern depends on a generic parameter
+error[E0158]: constant pattern cannot depend on generic parameters
   --> $DIR/associated-const-type-parameter-pattern.rs:30:9
    |
+LL | pub trait Foo {
+   | -------------
+LL |     const X: EFoo;
+   |     ------------- constant defined here
+...
+LL | pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
+   |                     - constant depends on this generic parameter
+LL |
 LL |     let A::X = arg;
-   |         ^^^^
+   |         ^^^^ `const` depends on a generic parameter
 
-error[E0158]: constant pattern depends on a generic parameter
+error[E0158]: constant pattern cannot depend on generic parameters
   --> $DIR/associated-const-type-parameter-pattern.rs:28:48
    |
+LL | pub trait Foo {
+   | -------------
+LL |     const X: EFoo;
+   |     ------------- constant defined here
+...
 LL | pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
-   |                                                ^^^^
+   |                     -                          ^^^^ `const` depends on a generic parameter
+   |                     |
+   |                     constant depends on this generic parameter
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs
index 5ed65425f34..8309cfbd58f 100644
--- a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs
+++ b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs
@@ -10,7 +10,7 @@ fn main() {
     block_on::block_on(async {
         let x = async || {};
 
-        async fn needs_async_fn_mut(mut x: impl async FnMut()) {
+        async fn needs_async_fn_mut(mut x: impl AsyncFnMut()) {
             x().await;
         }
         needs_async_fn_mut(x).await;
diff --git a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs
index be436465315..e7644e3dfe0 100644
--- a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs
+++ b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs
@@ -8,7 +8,7 @@ extern crate block_on;
 
 fn main() {
     block_on::block_on(async {
-        async fn needs_async_fn_once(x: impl async FnOnce()) {
+        async fn needs_async_fn_once(x: impl AsyncFnOnce()) {
             x().await;
         }
 
diff --git a/tests/ui/async-await/async-closures/auxiliary/foreign.rs b/tests/ui/async-await/async-closures/auxiliary/foreign.rs
index 2c935f5e1fa..33548a1b30d 100644
--- a/tests/ui/async-await/async-closures/auxiliary/foreign.rs
+++ b/tests/ui/async-await/async-closures/auxiliary/foreign.rs
@@ -2,6 +2,6 @@
 
 #![feature(async_closure)]
 
-pub fn closure() -> impl async Fn() {
+pub fn closure() -> impl AsyncFn() {
     async || { /* Don't really need to do anything here. */ }
 }
diff --git a/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs b/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs
index 4382a689e75..a72ff8e5dce 100644
--- a/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs
+++ b/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs
@@ -11,7 +11,7 @@ extern crate block_on;
 
 async fn empty() {}
 
-pub async fn call_once<F: async FnOnce()>(f: F) {
+pub async fn call_once<F: AsyncFnOnce()>(f: F) {
     f().await;
 }
 
diff --git a/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs b/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs
index 8b2de578b24..5ec1c5ee50e 100644
--- a/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs
+++ b/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs
@@ -16,7 +16,7 @@ impl Trait for (i32,) {
     }
 }
 
-async fn call_once(f: impl async FnOnce()) {
+async fn call_once(f: impl AsyncFnOnce()) {
     f().await;
 }
 
diff --git a/tests/ui/async-await/async-closures/brand.rs b/tests/ui/async-await/async-closures/brand.rs
index 5168f3696d7..db1f5d271c6 100644
--- a/tests/ui/async-await/async-closures/brand.rs
+++ b/tests/ui/async-await/async-closures/brand.rs
@@ -13,7 +13,7 @@ struct S;
 struct B<'b>(PhantomData<&'b mut &'b mut ()>);
 
 impl S {
-    async fn q<F: async Fn(B<'_>)>(self, f: F) {
+    async fn q<F: AsyncFn(B<'_>)>(self, f: F) {
         f(B(PhantomData)).await;
     }
 }
diff --git a/tests/ui/async-await/async-closures/captures.rs b/tests/ui/async-await/async-closures/captures.rs
index 0a9d0529bf5..2bd4b685997 100644
--- a/tests/ui/async-await/async-closures/captures.rs
+++ b/tests/ui/async-await/async-closures/captures.rs
@@ -13,11 +13,11 @@ fn main() {
     block_on::block_on(async_main());
 }
 
-async fn call<T>(f: &impl async Fn() -> T) -> T {
+async fn call<T>(f: &impl AsyncFn() -> T) -> T {
     f().await
 }
 
-async fn call_once<T>(f: impl async FnOnce() -> T) -> T {
+async fn call_once<T>(f: impl AsyncFnOnce() -> T) -> T {
     f().await
 }
 
@@ -80,7 +80,7 @@ async fn async_main() {
         call_once(c).await;
     }
 
-    fn force_fnonce<T>(f: impl async FnOnce() -> T) -> impl async FnOnce() -> T {
+    fn force_fnonce<T>(f: impl AsyncFnOnce() -> T) -> impl AsyncFnOnce() -> T {
         f
     }
 
diff --git a/tests/ui/async-await/async-closures/clone-closure.rs b/tests/ui/async-await/async-closures/clone-closure.rs
index 807897e3e03..a9e1d6bccc7 100644
--- a/tests/ui/async-await/async-closures/clone-closure.rs
+++ b/tests/ui/async-await/async-closures/clone-closure.rs
@@ -7,7 +7,7 @@
 
 extern crate block_on;
 
-async fn for_each(f: impl async FnOnce(&str) + Clone) {
+async fn for_each(f: impl AsyncFnOnce(&str) + Clone) {
     f.clone()("world").await;
     f.clone()("world2").await;
 }
diff --git a/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs b/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs
index 3b222d00bae..1acbf0311b3 100644
--- a/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs
+++ b/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs
@@ -6,7 +6,7 @@
 
 #![feature(async_closure)]
 
-fn constrain<T: async FnOnce()>(t: T) -> T {
+fn constrain<T: AsyncFnOnce()>(t: T) -> T {
     t
 }
 
@@ -14,7 +14,7 @@ fn call_once<T>(f: impl FnOnce() -> T) -> T {
     f()
 }
 
-async fn async_call_once<T>(f: impl async FnOnce() -> T) -> T {
+async fn async_call_once<T>(f: impl AsyncFnOnce() -> T) -> T {
     f().await
 }
 
diff --git a/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs b/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs
index 6f339f0c8ef..f71cc1ef537 100644
--- a/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs
+++ b/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs
@@ -7,7 +7,7 @@
 
 extern crate block_on;
 
-async fn call_once(f: impl async FnOnce()) {
+async fn call_once(f: impl AsyncFnOnce()) {
     f().await;
 }
 
diff --git a/tests/ui/async-await/async-closures/drop.rs b/tests/ui/async-await/async-closures/drop.rs
index 2884a20f244..9c99550e3b7 100644
--- a/tests/ui/async-await/async-closures/drop.rs
+++ b/tests/ui/async-await/async-closures/drop.rs
@@ -16,7 +16,7 @@ impl Drop for DropMe {
     }
 }
 
-async fn call_once(f: impl async FnOnce()) {
+async fn call_once(f: impl AsyncFnOnce()) {
     println!("before call");
     let fut = Box::pin(f());
     println!("after call");
diff --git a/tests/ui/async-await/async-closures/fn-exception-target-features.rs b/tests/ui/async-await/async-closures/fn-exception-target-features.rs
index de62fc8bf7e..eb554650b7c 100644
--- a/tests/ui/async-await/async-closures/fn-exception-target-features.rs
+++ b/tests/ui/async-await/async-closures/fn-exception-target-features.rs
@@ -10,7 +10,7 @@ use std::future::Future;
 #[target_feature(enable = "sse2")]
 fn target_feature()  -> Pin<Box<dyn Future<Output = ()> + 'static>> { todo!() }
 
-fn test(f: impl async Fn()) {}
+fn test(f: impl AsyncFn()) {}
 
 fn main() {
     test(target_feature); //~ ERROR the trait bound
diff --git a/tests/ui/async-await/async-closures/fn-exception-target-features.stderr b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr
index e965c40fb5b..db5895108bb 100644
--- a/tests/ui/async-await/async-closures/fn-exception-target-features.stderr
+++ b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr
@@ -9,8 +9,8 @@ LL |     test(target_feature);
 note: required by a bound in `test`
   --> $DIR/fn-exception-target-features.rs:13:17
    |
-LL | fn test(f: impl async Fn()) {}
-   |                 ^^^^^^^^^^ required by this bound in `test`
+LL | fn test(f: impl AsyncFn()) {}
+   |                 ^^^^^^^^^ required by this bound in `test`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/async-await/async-closures/fn-exception.rs b/tests/ui/async-await/async-closures/fn-exception.rs
index 0e06ebf48a4..36cb955cd5c 100644
--- a/tests/ui/async-await/async-closures/fn-exception.rs
+++ b/tests/ui/async-await/async-closures/fn-exception.rs
@@ -13,7 +13,7 @@ unsafe extern "C" {
     pub safe fn abi() -> Pin<Box<dyn Future<Output = ()> + 'static>>;
 }
 
-fn test(f: impl async Fn()) {}
+fn test(f: impl AsyncFn()) {}
 
 fn main() {
     test(unsafety); //~ ERROR the trait bound
diff --git a/tests/ui/async-await/async-closures/fn-exception.stderr b/tests/ui/async-await/async-closures/fn-exception.stderr
index 20132e42833..b3118664c15 100644
--- a/tests/ui/async-await/async-closures/fn-exception.stderr
+++ b/tests/ui/async-await/async-closures/fn-exception.stderr
@@ -9,8 +9,8 @@ LL |     test(unsafety);
 note: required by a bound in `test`
   --> $DIR/fn-exception.rs:16:17
    |
-LL | fn test(f: impl async Fn()) {}
-   |                 ^^^^^^^^^^ required by this bound in `test`
+LL | fn test(f: impl AsyncFn()) {}
+   |                 ^^^^^^^^^ required by this bound in `test`
 
 error[E0277]: the trait bound `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}: AsyncFn()` is not satisfied
   --> $DIR/fn-exception.rs:20:10
@@ -23,8 +23,8 @@ LL |     test(abi);
 note: required by a bound in `test`
   --> $DIR/fn-exception.rs:16:17
    |
-LL | fn test(f: impl async Fn()) {}
-   |                 ^^^^^^^^^^ required by this bound in `test`
+LL | fn test(f: impl AsyncFn()) {}
+   |                 ^^^^^^^^^ required by this bound in `test`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs b/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs
index 7ce210a33c3..c20e3664d8b 100644
--- a/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs
+++ b/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs
@@ -6,7 +6,7 @@
 
 extern crate block_on;
 
-fn force_fnonce<T: async FnOnce()>(t: T) -> T { t }
+fn force_fnonce<T: AsyncFnOnce()>(t: T) -> T { t }
 
 fn main() {
     block_on::block_on(async {
diff --git a/tests/ui/async-await/async-closures/foreign.rs b/tests/ui/async-await/async-closures/foreign.rs
index ab6fe06a3f4..a244eef4102 100644
--- a/tests/ui/async-await/async-closures/foreign.rs
+++ b/tests/ui/async-await/async-closures/foreign.rs
@@ -12,7 +12,7 @@ extern crate foreign;
 
 struct NoCopy;
 
-async fn call_once(f: impl async FnOnce()) {
+async fn call_once(f: impl AsyncFnOnce()) {
     f().await;
 }
 
diff --git a/tests/ui/async-await/async-closures/implements-fnmut.rs b/tests/ui/async-await/async-closures/implements-fnmut.rs
index 8e780ce9889..f49d1423c40 100644
--- a/tests/ui/async-await/async-closures/implements-fnmut.rs
+++ b/tests/ui/async-await/async-closures/implements-fnmut.rs
@@ -1,7 +1,7 @@
 //@ build-pass
 //@ edition: 2021
 
-// Demonstrates that an async closure may implement `FnMut` (not just `async FnMut`!)
+// Demonstrates that an async closure may implement `FnMut` (not just `AsyncFnMut`!)
 // if it has no self-borrows. In this case, `&Ty` is not borrowed from the closure env,
 // since it's fine to reborrow it with its original lifetime. See the doc comment on
 // `should_reborrow_from_env_of_parent_coroutine_closure` for more detail for when we
diff --git a/tests/ui/async-await/async-closures/inline-body.rs b/tests/ui/async-await/async-closures/inline-body.rs
index a842d98d1de..1bd2da6e899 100644
--- a/tests/ui/async-await/async-closures/inline-body.rs
+++ b/tests/ui/async-await/async-closures/inline-body.rs
@@ -24,7 +24,7 @@ pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
     }
 }
 
-async fn call_once<T>(f: impl async FnOnce() -> T) -> T {
+async fn call_once<T>(f: impl AsyncFnOnce() -> T) -> T {
     f().await
 }
 
diff --git a/tests/ui/async-await/async-closures/mangle.rs b/tests/ui/async-await/async-closures/mangle.rs
index a428905e40b..3032ca3c02b 100644
--- a/tests/ui/async-await/async-closures/mangle.rs
+++ b/tests/ui/async-await/async-closures/mangle.rs
@@ -13,11 +13,11 @@ use std::future::Future;
 use std::pin::pin;
 use std::task::*;
 
-async fn call_mut(f: &mut impl async FnMut()) {
+async fn call_mut(f: &mut impl AsyncFnMut()) {
     f().await;
 }
 
-async fn call_once(f: impl async FnOnce()) {
+async fn call_once(f: impl AsyncFnOnce()) {
     f().await;
 }
 
diff --git a/tests/ui/async-await/async-closures/moro-example.rs b/tests/ui/async-await/async-closures/moro-example.rs
index 5a8f42c7ca5..c331b8e5b5e 100644
--- a/tests/ui/async-await/async-closures/moro-example.rs
+++ b/tests/ui/async-await/async-closures/moro-example.rs
@@ -22,7 +22,7 @@ impl<'scope, 'env: 'scope> Scope<'scope, 'env> {
 
 fn scope_with_closure<'env, B>(_body: B) -> BoxFuture<'env, ()>
 where
-    for<'scope> B: async FnOnce(&'scope Scope<'scope, 'env>),
+    for<'scope> B: AsyncFnOnce(&'scope Scope<'scope, 'env>),
 {
     todo!()
 }
diff --git a/tests/ui/async-await/async-closures/move-is-async-fn.rs b/tests/ui/async-await/async-closures/move-is-async-fn.rs
index 79e2298f609..d0e2bc24b52 100644
--- a/tests/ui/async-await/async-closures/move-is-async-fn.rs
+++ b/tests/ui/async-await/async-closures/move-is-async-fn.rs
@@ -19,7 +19,7 @@ fn main() {
         is_static(&c);
 
         // Check that `<{async fn} as AsyncFnOnce>::CallOnceFuture` owns its captures.
-        fn call_once<F: async FnOnce()>(f: F) -> F::CallOnceFuture { f() }
+        fn call_once<F: AsyncFnOnce()>(f: F) -> F::CallOnceFuture { f() }
         is_static(&call_once(c));
     });
 }
diff --git a/tests/ui/async-await/async-closures/mut-ref-reborrow.rs b/tests/ui/async-await/async-closures/mut-ref-reborrow.rs
index 9f2cbd7ce1c..c37048398e9 100644
--- a/tests/ui/async-await/async-closures/mut-ref-reborrow.rs
+++ b/tests/ui/async-await/async-closures/mut-ref-reborrow.rs
@@ -9,7 +9,7 @@
 
 extern crate block_on;
 
-async fn call_once(f: impl async FnOnce()) { f().await; }
+async fn call_once(f: impl AsyncFnOnce()) { f().await; }
 
 pub async fn async_closure(x: &mut i32) {
     let c = async move || {
diff --git a/tests/ui/async-await/async-closures/no-borrow-from-env.rs b/tests/ui/async-await/async-closures/no-borrow-from-env.rs
index 3f9d26b9713..36b10c06dca 100644
--- a/tests/ui/async-await/async-closures/no-borrow-from-env.rs
+++ b/tests/ui/async-await/async-closures/no-borrow-from-env.rs
@@ -5,7 +5,7 @@
 
 fn outlives<'a>(_: impl Sized + 'a) {}
 
-async fn call_once(f: impl async FnOnce()) {
+async fn call_once(f: impl AsyncFnOnce()) {
     f().await;
 }
 
diff --git a/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs b/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs
index cd9d98d0799..cfb50dd5574 100644
--- a/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs
+++ b/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs
@@ -6,7 +6,7 @@
 
 extern crate block_on;
 
-fn wrapper(f: impl Fn(String)) -> impl async Fn(String) {
+fn wrapper(f: impl Fn(String)) -> impl AsyncFn(String) {
     async move |s| f(s)
 }
 
diff --git a/tests/ui/async-await/async-closures/overlapping-projs.rs b/tests/ui/async-await/async-closures/overlapping-projs.rs
index 6dd00b16103..f778534cfe2 100644
--- a/tests/ui/async-await/async-closures/overlapping-projs.rs
+++ b/tests/ui/async-await/async-closures/overlapping-projs.rs
@@ -7,7 +7,7 @@
 
 extern crate block_on;
 
-async fn call_once(f: impl async FnOnce()) {
+async fn call_once(f: impl AsyncFnOnce()) {
     f().await;
 }
 
diff --git a/tests/ui/async-await/async-closures/precise-captures.rs b/tests/ui/async-await/async-closures/precise-captures.rs
index c4c67df544f..7dcbf2595f0 100644
--- a/tests/ui/async-await/async-closures/precise-captures.rs
+++ b/tests/ui/async-await/async-closures/precise-captures.rs
@@ -5,7 +5,7 @@
 //@ revisions: call call_once force_once
 
 // call - Call the closure regularly.
-// call_once - Call the closure w/ `async FnOnce`, so exercising the by_move shim.
+// call_once - Call the closure w/ `AsyncFnOnce`, so exercising the by_move shim.
 // force_once - Force the closure mode to `FnOnce`, so exercising what was fixed
 //   in <https://github.com/rust-lang/rust/pull/123350>.
 
@@ -20,7 +20,7 @@ macro_rules! call {
 }
 
 #[cfg(call_once)]
-async fn call_once(f: impl async FnOnce()) {
+async fn call_once(f: impl AsyncFnOnce()) {
     f().await
 }
 
@@ -35,7 +35,7 @@ macro_rules! guidance {
 }
 
 #[cfg(force_once)]
-fn infer_fnonce(c: impl async FnOnce()) -> impl async FnOnce() { c }
+fn infer_fnonce(c: impl AsyncFnOnce()) -> impl AsyncFnOnce() { c }
 
 #[cfg(force_once)]
 macro_rules! guidance {
diff --git a/tests/ui/async-await/async-closures/refd.rs b/tests/ui/async-await/async-closures/refd.rs
index 0b8d3d7aff5..8c16ecb1531 100644
--- a/tests/ui/async-await/async-closures/refd.rs
+++ b/tests/ui/async-await/async-closures/refd.rs
@@ -10,15 +10,15 @@ struct NoCopy;
 
 fn main() {
     block_on::block_on(async {
-        async fn call_once(x: impl async Fn()) { x().await }
+        async fn call_once(x: impl AsyncFn()) { x().await }
 
-        // check that `&{async-closure}` implements `async Fn`.
+        // check that `&{async-closure}` implements `AsyncFn`.
         call_once(&async || {}).await;
 
-        // check that `&{closure}` implements `async Fn`.
+        // check that `&{closure}` implements `AsyncFn`.
         call_once(&|| async {}).await;
 
-        // check that `&fndef` implements `async Fn`.
+        // check that `&fndef` implements `AsyncFn`.
         async fn foo() {}
         call_once(&foo).await;
     });
diff --git a/tests/ui/async-await/async-closures/signature-deduction.rs b/tests/ui/async-await/async-closures/signature-deduction.rs
index 856f3963ee6..4e9a6747f1f 100644
--- a/tests/ui/async-await/async-closures/signature-deduction.rs
+++ b/tests/ui/async-await/async-closures/signature-deduction.rs
@@ -3,7 +3,7 @@
 
 #![feature(async_closure)]
 
-async fn foo(x: impl async Fn(&str) -> &str) {}
+async fn foo(x: impl AsyncFn(&str) -> &str) {}
 
 fn main() {
     foo(async |x| x);
diff --git a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs
index be3f032b8ff..19f366cc903 100644
--- a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs
+++ b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs
@@ -8,7 +8,7 @@
 
 fn outlives<'a>(_: impl Sized + 'a) {}
 
-async fn call_once(f: impl async FnOnce()) {
+async fn call_once(f: impl AsyncFnOnce()) {
     f().await;
 }
 
diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.rs b/tests/ui/async-await/async-closures/wrong-fn-kind.rs
index 3d6f856874f..a566b8aa663 100644
--- a/tests/ui/async-await/async-closures/wrong-fn-kind.rs
+++ b/tests/ui/async-await/async-closures/wrong-fn-kind.rs
@@ -2,7 +2,7 @@
 
 #![feature(async_closure)]
 
-fn needs_async_fn(_: impl async Fn()) {}
+fn needs_async_fn(_: impl AsyncFn()) {}
 
 fn a() {
     let mut x = 1;
@@ -15,7 +15,7 @@ fn a() {
 fn b() {
     let x = String::new();
     needs_async_fn(move || async move {
-        //~^ ERROR expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce`
+        //~^ ERROR expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnOnce`
         println!("{x}");
     });
 }
diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr
index 4b626c1bed6..d03b10ca2cc 100644
--- a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr
+++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr
@@ -1,29 +1,29 @@
-error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce`
+error[E0525]: expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnOnce`
   --> $DIR/wrong-fn-kind.rs:17:20
    |
 LL |       needs_async_fn(move || async move {
    |       -------------- -^^^^^^
    |       |              |
-   |  _____|______________this closure implements `async FnOnce`, not `async Fn`
+   |  _____|______________this closure implements `AsyncFnOnce`, not `AsyncFn`
    | |     |
    | |     required by a bound introduced by this call
 LL | |
 LL | |         println!("{x}");
-   | |                    - closure is `async FnOnce` because it moves the variable `x` out of its environment
+   | |                    - closure is `AsyncFnOnce` because it moves the variable `x` out of its environment
 LL | |     });
-   | |_____- the requirement to implement `async Fn` derives from here
+   | |_____- the requirement to implement `AsyncFn` derives from here
    |
 note: required by a bound in `needs_async_fn`
   --> $DIR/wrong-fn-kind.rs:5:27
    |
-LL | fn needs_async_fn(_: impl async Fn()) {}
-   |                           ^^^^^^^^^^ required by this bound in `needs_async_fn`
+LL | fn needs_async_fn(_: impl AsyncFn()) {}
+   |                           ^^^^^^^^^ required by this bound in `needs_async_fn`
 
 error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
   --> $DIR/wrong-fn-kind.rs:9:20
    |
-LL | fn needs_async_fn(_: impl async Fn()) {}
-   |                      --------------- change this to accept `FnMut` instead of `Fn`
+LL | fn needs_async_fn(_: impl AsyncFn()) {}
+   |                      -------------- change this to accept `FnMut` instead of `Fn`
 ...
 LL |     needs_async_fn(async || {
    |     -------------- ^^^^^^^^
diff --git a/tests/ui/async-await/async-fn/dyn-pos.rs b/tests/ui/async-await/async-fn/dyn-pos.rs
index a16b7c26f0d..129ea282936 100644
--- a/tests/ui/async-await/async-fn/dyn-pos.rs
+++ b/tests/ui/async-await/async-fn/dyn-pos.rs
@@ -2,7 +2,7 @@
 
 #![feature(async_closure)]
 
-fn foo(x: &dyn async Fn()) {}
+fn foo(x: &dyn AsyncFn()) {}
 //~^ ERROR the trait `AsyncFnMut` cannot be made into an object
 
 fn main() {}
diff --git a/tests/ui/async-await/async-fn/dyn-pos.stderr b/tests/ui/async-await/async-fn/dyn-pos.stderr
index a9abfc5e5c4..aaa8eb2634d 100644
--- a/tests/ui/async-await/async-fn/dyn-pos.stderr
+++ b/tests/ui/async-await/async-fn/dyn-pos.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `AsyncFnMut` cannot be made into an object
   --> $DIR/dyn-pos.rs:5:16
    |
-LL | fn foo(x: &dyn async Fn()) {}
-   |                ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object
+LL | fn foo(x: &dyn AsyncFn()) {}
+   |                ^^^^^^^^^ `AsyncFnMut` cannot be made into an object
    |
 note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
diff --git a/tests/ui/async-await/async-fn/edition-2015.rs b/tests/ui/async-await/async-fn/edition-2015.rs
index e38179758f6..7fc62a8dd93 100644
--- a/tests/ui/async-await/async-fn/edition-2015.rs
+++ b/tests/ui/async-await/async-fn/edition-2015.rs
@@ -1,8 +1,8 @@
 fn foo(x: impl async Fn()) -> impl async Fn() { x }
 //~^ ERROR `async` trait bounds are only allowed in Rust 2018 or later
 //~| ERROR `async` trait bounds are only allowed in Rust 2018 or later
-//~| ERROR async closures are unstable
-//~| ERROR async closures are unstable
+//~| ERROR `async` trait bounds are unstable
+//~| ERROR `async` trait bounds are unstable
 //~| ERROR use of unstable library feature `async_closure`
 //~| ERROR use of unstable library feature `async_closure`
 
diff --git a/tests/ui/async-await/async-fn/edition-2015.stderr b/tests/ui/async-await/async-fn/edition-2015.stderr
index 9fbceafd75d..96fb4c9e979 100644
--- a/tests/ui/async-await/async-fn/edition-2015.stderr
+++ b/tests/ui/async-await/async-fn/edition-2015.stderr
@@ -16,27 +16,27 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
    = help: pass `--edition 2024` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
-error[E0658]: async closures are unstable
+error[E0658]: `async` trait bounds are unstable
   --> $DIR/edition-2015.rs:1:16
    |
 LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
    |                ^^^^^
    |
    = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = help: add `#![feature(async_trait_bounds)]` 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: to use an async block, remove the `||`: `async {`
+   = help: use the desugared name of the async trait, such as `AsyncFn`
 
-error[E0658]: async closures are unstable
+error[E0658]: `async` trait bounds are unstable
   --> $DIR/edition-2015.rs:1:36
    |
 LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
    |                                    ^^^^^
    |
    = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = help: add `#![feature(async_trait_bounds)]` 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: to use an async block, remove the `||`: `async {`
+   = help: use the desugared name of the async trait, such as `AsyncFn`
 
 error[E0658]: use of unstable library feature `async_closure`
   --> $DIR/edition-2015.rs:1:42
diff --git a/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs
index f8da517213a..5d675921028 100644
--- a/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs
+++ b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs
@@ -15,7 +15,7 @@ async fn f(arg: &i32) {}
 
 async fn func<F>(f: F)
 where
-    F: for<'a> async Fn(&'a i32),
+    F: for<'a> AsyncFn(&'a i32),
 {
     let x: i32 = 0;
     f(&x).await;
diff --git a/tests/ui/async-await/async-fn/impl-trait.rs b/tests/ui/async-await/async-fn/impl-trait.rs
index 686addcb1a9..11faf9ac983 100644
--- a/tests/ui/async-await/async-fn/impl-trait.rs
+++ b/tests/ui/async-await/async-fn/impl-trait.rs
@@ -3,13 +3,13 @@
 
 #![feature(async_closure, type_alias_impl_trait)]
 
-type Tait = impl async Fn();
+type Tait = impl AsyncFn();
 fn tait() -> Tait {
     || async {}
 }
 
-fn foo(x: impl async Fn()) -> impl async Fn() { x }
+fn foo(x: impl AsyncFn()) -> impl AsyncFn() { x }
 
-fn param<T: async Fn()>() {}
+fn param<T: AsyncFn()>() {}
 
 fn main() {}
diff --git a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs
index abc429772fd..ea67831b68e 100644
--- a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs
+++ b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs
@@ -13,9 +13,9 @@ macro_rules! demo {
 }
 
 demo! { impl async Trait }
-//~^ ERROR async closures are unstable
+//~^ ERROR `async` trait bounds are unstable
 
 demo! { dyn async Trait }
-//~^ ERROR async closures are unstable
+//~^ ERROR `async` trait bounds are unstable
 
 fn main() {}
diff --git a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr
index 13b8e72b49d..a463944d113 100644
--- a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr
+++ b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr
@@ -20,27 +20,27 @@ LL | demo! { dyn async Trait }
    |
    = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0658]: async closures are unstable
+error[E0658]: `async` trait bounds are unstable
   --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:15:14
    |
 LL | demo! { impl async Trait }
    |              ^^^^^
    |
    = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = help: add `#![feature(async_trait_bounds)]` 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: to use an async block, remove the `||`: `async {`
+   = help: use the desugared name of the async trait, such as `AsyncFn`
 
-error[E0658]: async closures are unstable
+error[E0658]: `async` trait bounds are unstable
   --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:18:13
    |
 LL | demo! { dyn async Trait }
    |             ^^^^^
    |
    = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = help: add `#![feature(async_trait_bounds)]` 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: to use an async block, remove the `||`: `async {`
+   = help: use the desugared name of the async trait, such as `AsyncFn`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/async-await/async-fn/not-a-trait.rs b/tests/ui/async-await/async-fn/not-a-trait.rs
index 0d22cbd2c07..5cf23f2456a 100644
--- a/tests/ui/async-await/async-fn/not-a-trait.rs
+++ b/tests/ui/async-await/async-fn/not-a-trait.rs
@@ -1,6 +1,6 @@
 //@ edition:2018
 
-#![feature(async_closure)]
+#![feature(async_trait_bounds)]
 
 struct S;
 
diff --git a/tests/ui/async-await/async-fn/project.rs b/tests/ui/async-await/async-fn/project.rs
index 5cbdc378dda..b6068a916ae 100644
--- a/tests/ui/async-await/async-fn/project.rs
+++ b/tests/ui/async-await/async-fn/project.rs
@@ -6,7 +6,9 @@
 
 #![feature(async_closure, unboxed_closures, async_fn_traits)]
 
-fn project<F: async Fn<()>>(_: F) -> Option<F::Output> { None }
+use std::ops::AsyncFn;
+
+fn project<F: AsyncFn<()>>(_: F) -> Option<F::Output> { None }
 
 fn main() {
     let x: Option<i32> = project(|| async { 1i32 });
diff --git a/tests/ui/async-await/async-fn/sugar.rs b/tests/ui/async-await/async-fn/sugar.rs
index 29b6abc814a..0225b666ac5 100644
--- a/tests/ui/async-await/async-fn/sugar.rs
+++ b/tests/ui/async-await/async-fn/sugar.rs
@@ -1,7 +1,7 @@
 //@ edition: 2021
 //@ check-pass
 
-#![feature(async_closure)]
+#![feature(async_closure, async_trait_bounds)]
 
 async fn foo() {}
 
diff --git a/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs b/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs
index 329a1528e8b..654883966f4 100644
--- a/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs
+++ b/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs
@@ -6,7 +6,7 @@ macro_rules! x {
 
 x! {
     async fn foo() -> impl async Fn() { }
-    //~^ ERROR async closures are unstable
+    //~^ ERROR `async` trait bounds are unstable
 }
 
 fn main() {}
diff --git a/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr b/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr
index f68c09737db..259e13cd1fe 100644
--- a/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr
+++ b/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr
@@ -1,13 +1,13 @@
-error[E0658]: async closures are unstable
+error[E0658]: `async` trait bounds are unstable
   --> $DIR/trait-bounds-in-macro.rs:8:28
    |
 LL |     async fn foo() -> impl async Fn() { }
    |                            ^^^^^
    |
    = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = help: add `#![feature(async_trait_bounds)]` 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: to use an async block, remove the `||`: `async {`
+   = help: use the desugared name of the async trait, such as `AsyncFn`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/async-await/async-fn/wrong-trait.rs b/tests/ui/async-await/async-fn/wrong-trait.rs
index e6fb0b46712..38d6bb1d01a 100644
--- a/tests/ui/async-await/async-fn/wrong-trait.rs
+++ b/tests/ui/async-await/async-fn/wrong-trait.rs
@@ -1,6 +1,6 @@
 //@ edition:2018
 
-#![feature(async_closure)]
+#![feature(async_trait_bounds)]
 
 trait Foo {}
 
diff --git a/tests/ui/attributes/dump_def_parents.rs b/tests/ui/attributes/dump_def_parents.rs
index de0c88bb6c3..04a725f6c14 100644
--- a/tests/ui/attributes/dump_def_parents.rs
+++ b/tests/ui/attributes/dump_def_parents.rs
@@ -3,16 +3,17 @@
 
 fn bar() {
     fn foo() {
+        #[rustc_dump_def_parents]
         fn baz() {
-            #[rustc_dump_def_parents]
+            //~^ ERROR: rustc_dump_def_parents: DefId
             || {
-                //~^ ERROR: rustc_dump_def_parents: DefId
                 qux::<
                     {
                         //~^ ERROR: rustc_dump_def_parents: DefId
                         fn inhibits_dump() {
                             qux::<
                                 {
+                                    //~^ ERROR: rustc_dump_def_parents: DefId
                                     "hi";
                                     1
                                 },
diff --git a/tests/ui/attributes/dump_def_parents.stderr b/tests/ui/attributes/dump_def_parents.stderr
index b2cc32d09b0..a928e8e33a4 100644
--- a/tests/ui/attributes/dump_def_parents.stderr
+++ b/tests/ui/attributes/dump_def_parents.stderr
@@ -1,11 +1,50 @@
 error: rustc_dump_def_parents: DefId(..)
-  --> $DIR/dump_def_parents.rs:8:13
+  --> $DIR/dump_def_parents.rs:7:9
+   |
+LL |         fn baz() {
+   |         ^^^^^^^^
+   |
+note: DefId(..)
+  --> $DIR/dump_def_parents.rs:5:5
+   |
+LL |     fn foo() {
+   |     ^^^^^^^^
+note: DefId(..)
+  --> $DIR/dump_def_parents.rs:4:1
+   |
+LL | fn bar() {
+   | ^^^^^^^^
+note: DefId(..)
+  --> $DIR/dump_def_parents.rs:2:1
+   |
+LL | / #![feature(rustc_attrs)]
+LL | |
+LL | | fn bar() {
+LL | |     fn foo() {
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: rustc_dump_def_parents: DefId(..)
+  --> $DIR/dump_def_parents.rs:11:21
+   |
+LL | /                     {
+LL | |
+LL | |                         fn inhibits_dump() {
+LL | |                             qux::<
+...  |
+LL | |                         1
+LL | |                     },
+   | |_____________________^
+   |
+note: DefId(..)
+  --> $DIR/dump_def_parents.rs:9:13
    |
 LL |             || {
    |             ^^
-   |
 note: DefId(..)
-  --> $DIR/dump_def_parents.rs:6:9
+  --> $DIR/dump_def_parents.rs:7:9
    |
 LL |         fn baz() {
    |         ^^^^^^^^
@@ -32,6 +71,21 @@ LL | | fn main() {}
    | |____________^
 
 error: rustc_dump_def_parents: DefId(..)
+  --> $DIR/dump_def_parents.rs:15:33
+   |
+LL | / ...                   {
+LL | | ...
+LL | | ...                       "hi";
+LL | | ...                       1
+LL | | ...                   },
+   | |_______________________^
+   |
+note: DefId(..)
+  --> $DIR/dump_def_parents.rs:13:25
+   |
+LL |                         fn inhibits_dump() {
+   |                         ^^^^^^^^^^^^^^^^^^
+note: DefId(..)
   --> $DIR/dump_def_parents.rs:11:21
    |
 LL | /                     {
@@ -42,14 +96,13 @@ LL | |                             qux::<
 LL | |                         1
 LL | |                     },
    | |_____________________^
-   |
 note: DefId(..)
-  --> $DIR/dump_def_parents.rs:8:13
+  --> $DIR/dump_def_parents.rs:9:13
    |
 LL |             || {
    |             ^^
 note: DefId(..)
-  --> $DIR/dump_def_parents.rs:6:9
+  --> $DIR/dump_def_parents.rs:7:9
    |
 LL |         fn baz() {
    |         ^^^^^^^^
@@ -76,7 +129,7 @@ LL | | fn main() {}
    | |____________^
 
 error: rustc_dump_def_parents: DefId(..)
-  --> $DIR/dump_def_parents.rs:22:31
+  --> $DIR/dump_def_parents.rs:23:31
    |
 LL |                         qux::<{ 1 + 1 }>();
    |                               ^^^^^^^^^
@@ -93,12 +146,12 @@ LL | |                         1
 LL | |                     },
    | |_____________________^
 note: DefId(..)
-  --> $DIR/dump_def_parents.rs:8:13
+  --> $DIR/dump_def_parents.rs:9:13
    |
 LL |             || {
    |             ^^
 note: DefId(..)
-  --> $DIR/dump_def_parents.rs:6:9
+  --> $DIR/dump_def_parents.rs:7:9
    |
 LL |         fn baz() {
    |         ^^^^^^^^
@@ -124,5 +177,5 @@ LL | |
 LL | | fn main() {}
    | |____________^
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/binding/const-param.rs b/tests/ui/binding/const-param.rs
index 2d051808fe0..98bc90f508a 100644
--- a/tests/ui/binding/const-param.rs
+++ b/tests/ui/binding/const-param.rs
@@ -2,7 +2,7 @@
 
 fn check<const N: usize>() {
     match 1 {
-        N => {} //~ ERROR const parameters cannot be referenced in patterns
+        N => {} //~ ERROR constant parameters cannot be referenced in patterns
         _ => {}
     }
 }
diff --git a/tests/ui/binding/const-param.stderr b/tests/ui/binding/const-param.stderr
index e68893a59e4..b0b8108945c 100644
--- a/tests/ui/binding/const-param.stderr
+++ b/tests/ui/binding/const-param.stderr
@@ -1,8 +1,11 @@
-error[E0158]: const parameters cannot be referenced in patterns
+error[E0158]: constant parameters cannot be referenced in patterns
   --> $DIR/const-param.rs:5:9
    |
+LL | fn check<const N: usize>() {
+   |          -------------- constant defined here
+LL |     match 1 {
 LL |         N => {}
-   |         ^
+   |         ^ can't be used in patterns
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/binop/binary-op-on-fn-ptr-eq.rs b/tests/ui/binop/binary-op-on-fn-ptr-eq.rs
index a5ec63587f9..47b79f3855f 100644
--- a/tests/ui/binop/binary-op-on-fn-ptr-eq.rs
+++ b/tests/ui/binop/binary-op-on-fn-ptr-eq.rs
@@ -1,6 +1,9 @@
 //@ run-pass
 // Tests equality between supertype and subtype of a function
 // See the issue #91636
+
+#![allow(unpredictable_function_pointer_comparisons)]
+
 fn foo(_a: &str) {}
 
 fn main() {
diff --git a/tests/ui/box/unit/unique-ffi-symbols.rs b/tests/ui/box/unit/unique-ffi-symbols.rs
index 65a9a32b2bb..75877f8397e 100644
--- a/tests/ui/box/unit/unique-ffi-symbols.rs
+++ b/tests/ui/box/unit/unique-ffi-symbols.rs
@@ -1,6 +1,9 @@
 //@ run-pass
 // We used to have a __rust_abi shim that resulted in duplicated symbols
 // whenever the item path wasn't enough to disambiguate between them.
+
+#![allow(unpredictable_function_pointer_comparisons)]
+
 fn main() {
     let a = {
         extern "C" fn good() -> i32 { return 0; }
diff --git a/tests/ui/check-cfg/and-more-diagnostic.rs b/tests/ui/check-cfg/and-more-diagnostic.rs
new file mode 100644
index 00000000000..82867f3b435
--- /dev/null
+++ b/tests/ui/check-cfg/and-more-diagnostic.rs
@@ -0,0 +1,13 @@
+// This test makes sure that we don't emit a long list of possible values
+// but that we stop at a fix point and say "and X more".
+//
+//@ check-pass
+//@ no-auto-check-cfg
+//@ compile-flags: --check-cfg=cfg()
+//@ normalize-stderr-test: "and \d+ more" -> "and X more"
+//@ normalize-stderr-test: "`[a-zA-Z0-9_-]+`" -> "`xxx`"
+
+fn main() {
+    cfg!(target_feature = "zebra");
+    //~^ WARNING unexpected `cfg` condition value
+}
diff --git a/tests/ui/check-cfg/and-more-diagnostic.stderr b/tests/ui/check-cfg/and-more-diagnostic.stderr
new file mode 100644
index 00000000000..2ac80c84c37
--- /dev/null
+++ b/tests/ui/check-cfg/and-more-diagnostic.stderr
@@ -0,0 +1,12 @@
+warning: unexpected `xxx` condition value: `xxx`
+  --> $DIR/and-more-diagnostic.rs:11:10
+   |
+LL |     cfg!(target_feature = "zebra");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `xxx` are: `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, and `xxx` and X more
+   = 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
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/check-cfg/mix.rs b/tests/ui/check-cfg/mix.rs
index ac244f4fc09..e9a2de2f672 100644
--- a/tests/ui/check-cfg/mix.rs
+++ b/tests/ui/check-cfg/mix.rs
@@ -75,8 +75,6 @@ fn test_cfg_macro() {
     //~^ WARNING unexpected `cfg` condition value
     //~| WARNING unexpected `cfg` condition value
     //~| WARNING unexpected `cfg` condition value
-    cfg!(target_feature = "zebra");
-    //~^ WARNING unexpected `cfg` condition value
 }
 
 fn main() {}
diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr
index 32eb01c7018..231236799c6 100644
--- a/tests/ui/check-cfg/mix.stderr
+++ b/tests/ui/check-cfg/mix.stderr
@@ -245,14 +245,5 @@ LL |     cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("zebra"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
-warning: unexpected `cfg` condition value: `zebra`
-  --> $DIR/mix.rs:78:10
-   |
-LL |     cfg!(target_feature = "zebra");
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 252 more
-   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
-
-warning: 27 warnings emitted
+warning: 26 warnings emitted
 
diff --git a/tests/ui/check-cfg/target_feature.rs b/tests/ui/check-cfg/target_feature.rs
new file mode 100644
index 00000000000..6028dae66c4
--- /dev/null
+++ b/tests/ui/check-cfg/target_feature.rs
@@ -0,0 +1,18 @@
+// This test prints all the possible values for the `target_feature` cfg
+// as a way to assert the expected values and reflect on any changes made
+// to the `target_feature` cfg in the compiler.
+//
+// The output of this test  does not reflect the actual output seen by
+// users which will see a truncated list of possible values (at worst).
+//
+// In case of test output differences, just `--bless` the test.
+//
+//@ check-pass
+//@ no-auto-check-cfg
+//@ compile-flags: --check-cfg=cfg() -Zcheck-cfg-all-expected
+//@ normalize-stderr-test: "`, `" -> "`\n`"
+
+fn main() {
+    cfg!(target_feature = "_UNEXPECTED_VALUE");
+    //~^ WARNING unexpected `cfg` condition value
+}
diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr
new file mode 100644
index 00000000000..2674a97a551
--- /dev/null
+++ b/tests/ui/check-cfg/target_feature.stderr
@@ -0,0 +1,297 @@
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/target_feature.rs:16:10
+   |
+LL |     cfg!(target_feature = "_UNEXPECTED_VALUE");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `target_feature` are: `10e60`
+`2e3`
+`3e3r1`
+`3e3r2`
+`3e3r3`
+`3e7`
+`7e10`
+`a`
+`aclass`
+`adx`
+`aes`
+`altivec`
+`alu32`
+`amx-bf16`
+`amx-complex`
+`amx-fp16`
+`amx-int8`
+`amx-tile`
+`atomics`
+`avx`
+`avx2`
+`avx512bf16`
+`avx512bitalg`
+`avx512bw`
+`avx512cd`
+`avx512dq`
+`avx512f`
+`avx512fp16`
+`avx512ifma`
+`avx512vbmi`
+`avx512vbmi2`
+`avx512vl`
+`avx512vnni`
+`avx512vp2intersect`
+`avx512vpopcntdq`
+`avxifma`
+`avxneconvert`
+`avxvnni`
+`avxvnniint16`
+`avxvnniint8`
+`backchain`
+`bf16`
+`bmi1`
+`bmi2`
+`bti`
+`bulk-memory`
+`c`
+`cache`
+`cmpxchg16b`
+`crc`
+`crt-static`
+`cssc`
+`d`
+`d32`
+`dit`
+`doloop`
+`dotprod`
+`dpb`
+`dpb2`
+`dsp`
+`dsp1e2`
+`dspe60`
+`e`
+`e1`
+`e2`
+`ecv`
+`edsp`
+`elrw`
+`ermsb`
+`exception-handling`
+`extended-const`
+`f`
+`f16c`
+`f32mm`
+`f64mm`
+`faminmax`
+`fcma`
+`fdivdu`
+`fhm`
+`flagm`
+`flagm2`
+`float1e2`
+`float1e3`
+`float3e4`
+`float7e60`
+`floate1`
+`fma`
+`fp-armv8`
+`fp16`
+`fp64`
+`fp8`
+`fp8dot2`
+`fp8dot4`
+`fp8fma`
+`fpuv2_df`
+`fpuv2_sf`
+`fpuv3_df`
+`fpuv3_hf`
+`fpuv3_hi`
+`fpuv3_sf`
+`frecipe`
+`frintts`
+`fxsr`
+`gfni`
+`hard-float`
+`hard-float-abi`
+`hard-tp`
+`hbc`
+`high-registers`
+`hvx`
+`hvx-length128b`
+`hwdiv`
+`i8mm`
+`jsconv`
+`lahfsahf`
+`lasx`
+`lbt`
+`leoncasa`
+`lor`
+`lse`
+`lse128`
+`lse2`
+`lsx`
+`lut`
+`lvz`
+`lzcnt`
+`m`
+`mclass`
+`mops`
+`movbe`
+`mp`
+`mp1e2`
+`msa`
+`mte`
+`multivalue`
+`mutable-globals`
+`neon`
+`nontrapping-fptoint`
+`nvic`
+`paca`
+`pacg`
+`pan`
+`partword-atomics`
+`pauth-lr`
+`pclmulqdq`
+`pmuv3`
+`popcnt`
+`power10-vector`
+`power8-altivec`
+`power8-vector`
+`power9-altivec`
+`power9-vector`
+`prfchw`
+`quadword-atomics`
+`rand`
+`ras`
+`rclass`
+`rcpc`
+`rcpc2`
+`rcpc3`
+`rdm`
+`rdrand`
+`rdseed`
+`reference-types`
+`relax`
+`relaxed-simd`
+`reserve-x18`
+`rtm`
+`sb`
+`sha`
+`sha2`
+`sha3`
+`sha512`
+`sign-ext`
+`simd128`
+`sm3`
+`sm4`
+`sme`
+`sme-b16b16`
+`sme-f16f16`
+`sme-f64f64`
+`sme-f8f16`
+`sme-f8f32`
+`sme-fa64`
+`sme-i16i64`
+`sme-lutv2`
+`sme2`
+`sme2p1`
+`spe`
+`ssbs`
+`sse`
+`sse2`
+`sse3`
+`sse4.1`
+`sse4.2`
+`sse4a`
+`ssse3`
+`ssve-fp8dot2`
+`ssve-fp8dot4`
+`ssve-fp8fma`
+`sve`
+`sve-b16b16`
+`sve2`
+`sve2-aes`
+`sve2-bitperm`
+`sve2-sha3`
+`sve2-sm4`
+`sve2p1`
+`tail-call`
+`tbm`
+`thumb-mode`
+`thumb2`
+`tme`
+`trust`
+`trustzone`
+`ual`
+`unaligned-scalar-mem`
+`v`
+`v5te`
+`v6`
+`v6k`
+`v6t2`
+`v7`
+`v8`
+`v8.1a`
+`v8.2a`
+`v8.3a`
+`v8.4a`
+`v8.5a`
+`v8.6a`
+`v8.7a`
+`v8.8a`
+`v8.9a`
+`v8plus`
+`v9`
+`v9.1a`
+`v9.2a`
+`v9.3a`
+`v9.4a`
+`v9.5a`
+`v9a`
+`vaes`
+`vdsp2e60f`
+`vdspv1`
+`vdspv2`
+`vector`
+`vfp2`
+`vfp3`
+`vfp4`
+`vh`
+`virt`
+`virtualization`
+`vpclmulqdq`
+`vsx`
+`wfxt`
+`wide-arithmetic`
+`xop`
+`xsave`
+`xsavec`
+`xsaveopt`
+`xsaves`
+`zaamo`
+`zabha`
+`zalrsc`
+`zba`
+`zbb`
+`zbc`
+`zbkb`
+`zbkc`
+`zbkx`
+`zbs`
+`zdinx`
+`zfh`
+`zfhmin`
+`zfinx`
+`zhinx`
+`zhinxmin`
+`zk`
+`zkn`
+`zknd`
+`zkne`
+`zknh`
+`zkr`
+`zks`
+`zksed`
+`zksh`, and `zkt`
+   = 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
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs
index 1fda4b2089e..40b7b2db836 100644
--- a/tests/ui/check-cfg/well-known-values.rs
+++ b/tests/ui/check-cfg/well-known-values.rs
@@ -60,8 +60,8 @@
     //~^ WARN unexpected `cfg` condition value
     target_family = "_UNEXPECTED_VALUE",
     //~^ WARN unexpected `cfg` condition value
-    target_feature = "_UNEXPECTED_VALUE",
-    //~^ WARN unexpected `cfg` condition value
+    // target_feature = "_UNEXPECTED_VALUE",
+    // ^ tested in target_feature.rs
     target_has_atomic = "_UNEXPECTED_VALUE",
     //~^ WARN unexpected `cfg` condition value
     target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index 4d375d80e77..7c03d0570db 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -169,15 +169,6 @@ LL |     target_family = "_UNEXPECTED_VALUE",
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:63:5
-   |
-LL |     target_feature = "_UNEXPECTED_VALUE",
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `leoncasa`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pauth-lr`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `reserve-x18`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tail-call`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v8plus`, `v9`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `wide-arithmetic`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt`
-   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
-
-warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
   --> $DIR/well-known-values.rs:65:5
    |
 LL |     target_has_atomic = "_UNEXPECTED_VALUE",
@@ -297,5 +288,5 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
    = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
-warning: 30 warnings emitted
+warning: 29 warnings emitted
 
diff --git a/tests/ui/coercion/coerce-loop-issue-122561.rs b/tests/ui/coercion/coerce-loop-issue-122561.rs
index e08884ad6a4..50a2aacc91a 100644
--- a/tests/ui/coercion/coerce-loop-issue-122561.rs
+++ b/tests/ui/coercion/coerce-loop-issue-122561.rs
@@ -39,8 +39,7 @@ fn for_single_line() -> bool { for i in 0.. { return false; } }
 // b. format the suggestion correctly so
 //    that it's readable
 fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool {
-//~^ ERROR `for` is not allowed in a `const`
-//~| ERROR mismatched types
+    //~^ ERROR mismatched types
     true
 }
 
@@ -84,16 +83,14 @@ fn loop_() -> bool {
 
 const C: i32 = {
     for i in 0.. {
-    //~^ ERROR `for` is not allowed in a `const`
-    //~| ERROR mismatched types
+    //~^ ERROR mismatched types
     }
 };
 
 fn main() {
     let _ = [10; {
         for i in 0..5 {
-        //~^ ERROR `for` is not allowed in a `const`
-        //~| ERROR mismatched types
+        //~^ ERROR mismatched types
         }
     }];
 
@@ -105,6 +102,5 @@ fn main() {
 
 
     let _ = |a: &[(); for x in 0..2 {}]| {};
-    //~^ ERROR `for` is not allowed in a `const`
-    //~| ERROR mismatched types
+    //~^ ERROR mismatched types
 }
diff --git a/tests/ui/coercion/coerce-loop-issue-122561.stderr b/tests/ui/coercion/coerce-loop-issue-122561.stderr
index 0f77fd1364d..90e9f41c291 100644
--- a/tests/ui/coercion/coerce-loop-issue-122561.stderr
+++ b/tests/ui/coercion/coerce-loop-issue-122561.stderr
@@ -1,5 +1,5 @@
 warning: denote infinite loops with `loop { ... }`
-  --> $DIR/coerce-loop-issue-122561.rs:48:5
+  --> $DIR/coerce-loop-issue-122561.rs:47:5
    |
 LL |     while true {
    |     ^^^^^^^^^^ help: use `loop`
@@ -7,57 +7,11 @@ LL |     while true {
    = note: `#[warn(while_true)]` on by default
 
 warning: denote infinite loops with `loop { ... }`
-  --> $DIR/coerce-loop-issue-122561.rs:72:5
+  --> $DIR/coerce-loop-issue-122561.rs:71:5
    |
 LL |     while true {
    |     ^^^^^^^^^^ help: use `loop`
 
-error[E0658]: `for` is not allowed in a `const`
-  --> $DIR/coerce-loop-issue-122561.rs:41:24
-   |
-LL | fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool {
-   |                        ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
-   = help: add `#![feature(const_for)]` 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[E0658]: `for` is not allowed in a `const`
-  --> $DIR/coerce-loop-issue-122561.rs:86:5
-   |
-LL | /     for i in 0.. {
-LL | |
-LL | |
-LL | |     }
-   | |_____^
-   |
-   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
-   = help: add `#![feature(const_for)]` 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[E0658]: `for` is not allowed in a `const`
-  --> $DIR/coerce-loop-issue-122561.rs:94:9
-   |
-LL | /         for i in 0..5 {
-LL | |
-LL | |
-LL | |         }
-   | |_________^
-   |
-   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
-   = help: add `#![feature(const_for)]` 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[E0658]: `for` is not allowed in a `const`
-  --> $DIR/coerce-loop-issue-122561.rs:107:23
-   |
-LL |     let _ = |a: &[(); for x in 0..2 {}]| {};
-   |                       ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
-   = help: add `#![feature(const_for)]` 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[E0308]: mismatched types
   --> $DIR/coerce-loop-issue-122561.rs:41:24
    |
@@ -71,11 +25,10 @@ LL | fn for_in_arg(a: &[(); for x in 0..2 {} /* `usize` value */]) -> bool {
    |                                         +++++++++++++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-loop-issue-122561.rs:86:5
+  --> $DIR/coerce-loop-issue-122561.rs:85:5
    |
 LL | /     for i in 0.. {
 LL | |
-LL | |
 LL | |     }
    | |_____^ expected `i32`, found `()`
    |
@@ -174,7 +127,7 @@ LL | fn for_single_line() -> bool { for i in 0.. { return false; } /* `bool` val
    |                                                               ++++++++++++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-loop-issue-122561.rs:48:5
+  --> $DIR/coerce-loop-issue-122561.rs:47:5
    |
 LL |   fn while_inifinite() -> bool {
    |                           ---- expected `bool` because of return type
@@ -193,7 +146,7 @@ LL +     /* `bool` value */
    |
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-loop-issue-122561.rs:57:5
+  --> $DIR/coerce-loop-issue-122561.rs:56:5
    |
 LL |   fn while_finite() -> bool {
    |                        ---- expected `bool` because of return type
@@ -213,7 +166,7 @@ LL +     /* `bool` value */
    |
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-loop-issue-122561.rs:65:5
+  --> $DIR/coerce-loop-issue-122561.rs:64:5
    |
 LL |   fn while_zero_times() -> bool {
    |                            ---- expected `bool` because of return type
@@ -231,7 +184,7 @@ LL +     /* `bool` value */
    |
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-loop-issue-122561.rs:72:5
+  --> $DIR/coerce-loop-issue-122561.rs:71:5
    |
 LL |   fn while_never_type() -> ! {
    |                            - expected `!` because of return type
@@ -251,11 +204,10 @@ LL +     /* `loop {}` or `panic!("...")` */
    |
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-loop-issue-122561.rs:94:9
+  --> $DIR/coerce-loop-issue-122561.rs:92:9
    |
 LL | /         for i in 0..5 {
 LL | |
-LL | |
 LL | |         }
    | |_________^ expected `usize`, found `()`
    |
@@ -267,7 +219,7 @@ LL +         /* `usize` value */
    |
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-loop-issue-122561.rs:101:9
+  --> $DIR/coerce-loop-issue-122561.rs:98:9
    |
 LL | /         while false {
 LL | |
@@ -282,7 +234,7 @@ LL +         /* `usize` value */
    |
 
 error[E0308]: mismatched types
-  --> $DIR/coerce-loop-issue-122561.rs:107:23
+  --> $DIR/coerce-loop-issue-122561.rs:104:23
    |
 LL |     let _ = |a: &[(); for x in 0..2 {}]| {};
    |                       ^^^^^^^^^^^^^^^^ expected `usize`, found `()`
@@ -293,7 +245,6 @@ help: consider returning a value here
 LL |     let _ = |a: &[(); for x in 0..2 {} /* `usize` value */]| {};
    |                                        +++++++++++++++++++
 
-error: aborting due to 18 previous errors; 2 warnings emitted
+error: aborting due to 14 previous errors; 2 warnings emitted
 
-Some errors have detailed explanations: E0308, E0658.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/generic_arg_infer/array-repeat-expr-lib.rs b/tests/ui/const-generics/generic_arg_infer/array-repeat-expr-lib.rs
new file mode 100644
index 00000000000..c1f725db126
--- /dev/null
+++ b/tests/ui/const-generics/generic_arg_infer/array-repeat-expr-lib.rs
@@ -0,0 +1,12 @@
+//@ check-pass
+
+#![feature(generic_arg_infer)]
+#![crate_type = "lib"]
+
+// Test that encoding the hallucinated `DefId` for the `_` const argument doesn't
+// ICE (see #133468). This requires this to be a library crate.
+
+pub fn foo() {
+    let s: [u8; 10];
+    s = [0; _];
+}
diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
index 30a45ce377e..4eb374b2020 100644
--- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
@@ -72,6 +72,20 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
 LL + #![feature(adt_const_params)]
    |
 
+note: erroneous constant encountered
+  --> $DIR/unevaluated-const-ice-119731.rs:22:19
+   |
+LL |     impl v17<512, v0> {
+   |                   ^^
+
+note: erroneous constant encountered
+  --> $DIR/unevaluated-const-ice-119731.rs:22:19
+   |
+LL |     impl v17<512, v0> {
+   |                   ^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
   --> $DIR/unevaluated-const-ice-119731.rs:28:37
    |
diff --git a/tests/ui/const-generics/issues/cg-in-dyn-issue-128176.rs b/tests/ui/const-generics/issues/cg-in-dyn-issue-128176.rs
new file mode 100644
index 00000000000..5a67d34d6e5
--- /dev/null
+++ b/tests/ui/const-generics/issues/cg-in-dyn-issue-128176.rs
@@ -0,0 +1,18 @@
+//@ check-pass
+
+// Regression test for #128176. Previously we would call `type_of` on the `1` anon const
+// before the anon const had been lowered and had the `type_of` fed with a result.
+
+#![feature(generic_const_exprs)]
+#![feature(dyn_compatible_for_dispatch)]
+#![allow(incomplete_features)]
+
+trait X {
+    type Y<const N: i16>;
+}
+
+const _: () = {
+    fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {}
+};
+
+fn main() {}
diff --git a/tests/ui/const-generics/issues/issue-83765.stderr b/tests/ui/const-generics/issues/issue-83765.stderr
index cce62749912..6b62012c14f 100644
--- a/tests/ui/const-generics/issues/issue-83765.stderr
+++ b/tests/ui/const-generics/issues/issue-83765.stderr
@@ -10,11 +10,11 @@ note: ...which requires computing candidate for `<LazyUpdim<'_, T, <T as TensorD
 LL | trait TensorDimension {
    | ^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`, completing the cycle
-note: cycle used when computing candidate for `<LazyUpdim<'_, T, { T::DIM }, DIM> as TensorDimension>`
-  --> $DIR/issue-83765.rs:4:1
+note: cycle used when checking assoc item `<impl at $DIR/issue-83765.rs:50:1: 50:94>::size` is compatible with trait definition
+  --> $DIR/issue-83765.rs:51:5
    |
-LL | trait TensorDimension {
-   | ^^^^^^^^^^^^^^^^^^^^^
+LL |     fn size(&self) -> [usize; DIM] {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error[E0391]: cycle detected when resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`
diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs
index 09f7e2ba5b1..270496d45a6 100644
--- a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs
+++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs
@@ -12,8 +12,7 @@ impl Opcode2 {
 
 pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) {
     move |i| match msg_type {
-        Opcode2::OP2 => unimplemented!(),
-        //~^ ERROR: could not evaluate constant pattern
+        Opcode2::OP2 => unimplemented!(), // ok, `const` already emitted an error
     }
 }
 
diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr
index 9442eac0cf5..d95a8861230 100644
--- a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr
+++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr
@@ -17,13 +17,7 @@ help: you might be missing a type parameter
 LL | pub struct Opcode2<S>(&'a S);
    |                   +++
 
-error: could not evaluate constant pattern
-  --> $DIR/ice-type-mismatch-when-copying-112824.rs:15:9
-   |
-LL |         Opcode2::OP2 => unimplemented!(),
-   |         ^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0261, E0412.
 For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/consts/const-eval-fail-too-big.rs b/tests/ui/consts/const-eval-fail-too-big.rs
new file mode 100644
index 00000000000..4b5dbc1d7a4
--- /dev/null
+++ b/tests/ui/consts/const-eval-fail-too-big.rs
@@ -0,0 +1,12 @@
+//Error output test for #78834: Type is too big for the target architecture
+struct B<
+    A: Sized = [(); {
+                   let x = [0u8; !0usize];
+                   //~^ ERROR evaluation of constant value failed
+                   1
+               }],
+> {
+    a: A,
+}
+
+fn main() {}
diff --git a/tests/ui/consts/const-eval-fail-too-big.stderr b/tests/ui/consts/const-eval-fail-too-big.stderr
new file mode 100644
index 00000000000..ae666483233
--- /dev/null
+++ b/tests/ui/consts/const-eval-fail-too-big.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-eval-fail-too-big.rs:4:28
+   |
+LL |                    let x = [0u8; !0usize];
+   |                            ^^^^^^^^^^^^^^ values of the type `[u8; usize::MAX]` are too big for the target architecture
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/const-eval-overflow-2.rs b/tests/ui/consts/const-eval/const-eval-overflow-2.rs
index c19a0c443ec..bae8a7ce243 100644
--- a/tests/ui/consts/const-eval/const-eval-overflow-2.rs
+++ b/tests/ui/consts/const-eval/const-eval-overflow-2.rs
@@ -12,8 +12,7 @@ const NEG_NEG_128: i8 = -NEG_128; //~ ERROR constant
 
 fn main() {
     match -128i8 {
-        NEG_NEG_128 => println!("A"),
-        //~^ ERROR could not evaluate constant pattern
+        NEG_NEG_128 => println!("A"), // ok, `const` error already emitted
         _ => println!("B"),
     }
 }
diff --git a/tests/ui/consts/const-eval/const-eval-overflow-2.stderr b/tests/ui/consts/const-eval/const-eval-overflow-2.stderr
index fc0baf11051..5599ff931e8 100644
--- a/tests/ui/consts/const-eval/const-eval-overflow-2.stderr
+++ b/tests/ui/consts/const-eval/const-eval-overflow-2.stderr
@@ -4,12 +4,6 @@ error[E0080]: evaluation of constant value failed
 LL | const NEG_NEG_128: i8 = -NEG_128;
    |                         ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
 
-error: could not evaluate constant pattern
-  --> $DIR/const-eval-overflow-2.rs:15:9
-   |
-LL |         NEG_NEG_128 => println!("A"),
-   |         ^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr b/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr
index 8175fe6016a..18935626af1 100644
--- a/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr
+++ b/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr
@@ -7,12 +7,6 @@ LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
-error: could not evaluate constant pattern
-  --> $DIR/ref_to_int_match.rs:7:14
-   |
-LL |         10..=BAR => {},
-   |              ^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr b/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr
index 8175fe6016a..18935626af1 100644
--- a/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr
+++ b/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr
@@ -7,12 +7,6 @@ LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
-error: could not evaluate constant pattern
-  --> $DIR/ref_to_int_match.rs:7:14
-   |
-LL |         10..=BAR => {},
-   |              ^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/ref_to_int_match.rs b/tests/ui/consts/const-eval/ref_to_int_match.rs
index c627ad97bb0..be9420e0215 100644
--- a/tests/ui/consts/const-eval/ref_to_int_match.rs
+++ b/tests/ui/consts/const-eval/ref_to_int_match.rs
@@ -4,7 +4,7 @@ fn main() {
     let n: Int = 40;
     match n {
         0..=10 => {},
-        10..=BAR => {}, //~ ERROR could not evaluate constant pattern
+        10..=BAR => {}, // ok, `const` error already emitted
         _ => {},
     }
 }
diff --git a/tests/ui/consts/const-extern-function.rs b/tests/ui/consts/const-extern-function.rs
index acc438189cb..7629d63266a 100644
--- a/tests/ui/consts/const-extern-function.rs
+++ b/tests/ui/consts/const-extern-function.rs
@@ -1,5 +1,7 @@
 //@ run-pass
+
 #![allow(non_upper_case_globals)]
+#![allow(unpredictable_function_pointer_comparisons)]
 
 extern "C" fn foopy() {}
 
diff --git a/tests/ui/consts/const-fn-error.rs b/tests/ui/consts/const-fn-error.rs
index 42061ef0670..b7151782423 100644
--- a/tests/ui/consts/const-fn-error.rs
+++ b/tests/ui/consts/const-fn-error.rs
@@ -3,9 +3,8 @@ const X : usize = 2;
 const fn f(x: usize) -> usize {
     let mut sum = 0;
     for i in 0..x {
-        //~^ ERROR cannot convert
-        //~| ERROR `for` is not allowed in a `const fn`
-        //~| ERROR cannot call non-const fn
+        //~^ ERROR cannot use `for`
+        //~| ERROR cannot use `for`
         sum += i;
     }
     sum
diff --git a/tests/ui/consts/const-fn-error.stderr b/tests/ui/consts/const-fn-error.stderr
index 42a6f2704c9..3d4cf6539c8 100644
--- a/tests/ui/consts/const-fn-error.stderr
+++ b/tests/ui/consts/const-fn-error.stderr
@@ -1,37 +1,20 @@
-error[E0658]: `for` is not allowed in a `const fn`
-  --> $DIR/const-fn-error.rs:5:5
-   |
-LL | /     for i in 0..x {
-LL | |
-LL | |
-LL | |
-LL | |         sum += i;
-LL | |     }
-   | |_____^
-   |
-   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
-   = help: add `#![feature(const_for)]` 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[E0015]: cannot convert `std::ops::Range<usize>` into an iterator in constant functions
+error[E0015]: cannot use `for` loop on `std::ops::Range<usize>` in constant functions
   --> $DIR/const-fn-error.rs:5:14
    |
 LL |     for i in 0..x {
    |              ^^^^
    |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: cannot call non-const fn `<std::ops::Range<usize> as Iterator>::next` in constant functions
+error[E0015]: cannot use `for` loop on `std::ops::Range<usize>` in constant functions
   --> $DIR/const-fn-error.rs:5:14
    |
 LL |     for i in 0..x {
    |              ^^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0015, E0658.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/const-for-feature-gate.rs b/tests/ui/consts/const-for-feature-gate.rs
index d74178662b3..b643e63c096 100644
--- a/tests/ui/consts/const-for-feature-gate.rs
+++ b/tests/ui/consts/const-for-feature-gate.rs
@@ -2,9 +2,8 @@
 
 const _: () = {
     for _ in 0..5 {}
-    //~^ error: `for` is not allowed in a `const`
-    //~| ERROR: cannot convert
-    //~| ERROR: cannot call
+    //~^ ERROR cannot use `for`
+    //~| ERROR cannot use `for`
 };
 
 fn main() {}
diff --git a/tests/ui/consts/const-for-feature-gate.stderr b/tests/ui/consts/const-for-feature-gate.stderr
index 6e099a3159d..29db5d24ac8 100644
--- a/tests/ui/consts/const-for-feature-gate.stderr
+++ b/tests/ui/consts/const-for-feature-gate.stderr
@@ -1,32 +1,20 @@
-error[E0658]: `for` is not allowed in a `const`
-  --> $DIR/const-for-feature-gate.rs:4:5
-   |
-LL |     for _ in 0..5 {}
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
-   = help: add `#![feature(const_for)]` 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[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants
+error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants
   --> $DIR/const-for-feature-gate.rs:4:14
    |
 LL |     for _ in 0..5 {}
    |              ^^^^
    |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
+error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants
   --> $DIR/const-for-feature-gate.rs:4:14
    |
 LL |     for _ in 0..5 {}
    |              ^^^^
    |
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0015, E0658.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/const-for.rs b/tests/ui/consts/const-for.rs
index 4f8034e73f0..6f7895457c5 100644
--- a/tests/ui/consts/const-for.rs
+++ b/tests/ui/consts/const-for.rs
@@ -2,8 +2,8 @@
 
 const _: () = {
     for _ in 0..5 {}
-    //~^ error: cannot call
-    //~| error: cannot convert
+    //~^ ERROR cannot use `for`
+    //~| ERROR cannot use `for`
 };
 
 fn main() {}
diff --git a/tests/ui/consts/const-for.stderr b/tests/ui/consts/const-for.stderr
index 78336dc93e8..d1308a8dedc 100644
--- a/tests/ui/consts/const-for.stderr
+++ b/tests/ui/consts/const-for.stderr
@@ -1,20 +1,19 @@
-error[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants
+error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants
   --> $DIR/const-for.rs:4:14
    |
 LL |     for _ in 0..5 {}
    |              ^^^^
    |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
+error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants
   --> $DIR/const-for.rs:4:14
    |
 LL |     for _ in 0..5 {}
    |              ^^^^
    |
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/const-integer-bool-ops.stderr b/tests/ui/consts/const-integer-bool-ops.stderr
index 4e503e5a5c0..d58a8e93ff6 100644
--- a/tests/ui/consts/const-integer-bool-ops.stderr
+++ b/tests/ui/consts/const-integer-bool-ops.stderr
@@ -16,6 +16,12 @@ error[E0308]: mismatched types
 LL | const X: usize = 42 && 39;
    |                  ^^^^^^^^ expected `usize`, found `bool`
 
+note: erroneous constant encountered
+  --> $DIR/const-integer-bool-ops.rs:8:18
+   |
+LL | const ARR: [i32; X] = [99; 34];
+   |                  ^
+
 error[E0308]: mismatched types
   --> $DIR/const-integer-bool-ops.rs:10:19
    |
@@ -34,6 +40,12 @@ error[E0308]: mismatched types
 LL | const X1: usize = 42 || 39;
    |                   ^^^^^^^^ expected `usize`, found `bool`
 
+note: erroneous constant encountered
+  --> $DIR/const-integer-bool-ops.rs:17:19
+   |
+LL | const ARR1: [i32; X1] = [99; 47];
+   |                   ^^
+
 error[E0308]: mismatched types
   --> $DIR/const-integer-bool-ops.rs:19:19
    |
@@ -52,6 +64,12 @@ error[E0308]: mismatched types
 LL | const X2: usize = -42 || -39;
    |                   ^^^^^^^^^^ expected `usize`, found `bool`
 
+note: erroneous constant encountered
+  --> $DIR/const-integer-bool-ops.rs:26:19
+   |
+LL | const ARR2: [i32; X2] = [99; 18446744073709551607];
+   |                   ^^
+
 error[E0308]: mismatched types
   --> $DIR/const-integer-bool-ops.rs:28:19
    |
@@ -70,42 +88,84 @@ error[E0308]: mismatched types
 LL | const X3: usize = -42 && -39;
    |                   ^^^^^^^^^^ expected `usize`, found `bool`
 
+note: erroneous constant encountered
+  --> $DIR/const-integer-bool-ops.rs:35:19
+   |
+LL | const ARR3: [i32; X3] = [99; 6];
+   |                   ^^
+
 error[E0308]: mismatched types
   --> $DIR/const-integer-bool-ops.rs:37:18
    |
 LL | const Y: usize = 42.0 == 42.0;
    |                  ^^^^^^^^^^^^ expected `usize`, found `bool`
 
+note: erroneous constant encountered
+  --> $DIR/const-integer-bool-ops.rs:40:19
+   |
+LL | const ARRR: [i32; Y] = [99; 1];
+   |                   ^
+
 error[E0308]: mismatched types
   --> $DIR/const-integer-bool-ops.rs:42:19
    |
 LL | const Y1: usize = 42.0 >= 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
+note: erroneous constant encountered
+  --> $DIR/const-integer-bool-ops.rs:45:20
+   |
+LL | const ARRR1: [i32; Y1] = [99; 1];
+   |                    ^^
+
 error[E0308]: mismatched types
   --> $DIR/const-integer-bool-ops.rs:47:19
    |
 LL | const Y2: usize = 42.0 <= 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
+note: erroneous constant encountered
+  --> $DIR/const-integer-bool-ops.rs:50:20
+   |
+LL | const ARRR2: [i32; Y2] = [99; 1];
+   |                    ^^
+
 error[E0308]: mismatched types
   --> $DIR/const-integer-bool-ops.rs:52:19
    |
 LL | const Y3: usize = 42.0 > 42.0;
    |                   ^^^^^^^^^^^ expected `usize`, found `bool`
 
+note: erroneous constant encountered
+  --> $DIR/const-integer-bool-ops.rs:55:20
+   |
+LL | const ARRR3: [i32; Y3] = [99; 0];
+   |                    ^^
+
 error[E0308]: mismatched types
   --> $DIR/const-integer-bool-ops.rs:57:19
    |
 LL | const Y4: usize = 42.0 < 42.0;
    |                   ^^^^^^^^^^^ expected `usize`, found `bool`
 
+note: erroneous constant encountered
+  --> $DIR/const-integer-bool-ops.rs:60:20
+   |
+LL | const ARRR4: [i32; Y4] = [99; 0];
+   |                    ^^
+
 error[E0308]: mismatched types
   --> $DIR/const-integer-bool-ops.rs:62:19
    |
 LL | const Y5: usize = 42.0 != 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
+note: erroneous constant encountered
+  --> $DIR/const-integer-bool-ops.rs:65:20
+   |
+LL | const ARRR5: [i32; Y5] = [99; 0];
+   |                    ^^
+
 error: aborting due to 18 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/consts/const-mut-refs/issue-76510.stderr b/tests/ui/consts/const-mut-refs/issue-76510.stderr
index aff86e83578..a63be676fda 100644
--- a/tests/ui/consts/const-mut-refs/issue-76510.stderr
+++ b/tests/ui/consts/const-mut-refs/issue-76510.stderr
@@ -4,6 +4,12 @@ error[E0764]: mutable references are not allowed in the final value of constants
 LL | const S: &'static mut str = &mut " hello ";
    |                             ^^^^^^^^^^^^^^
 
+note: erroneous constant encountered
+  --> $DIR/issue-76510.rs:7:70
+   |
+LL |         let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
+   |                                                                      ^
+
 error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0764`.
diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs
index 4df3a793b4c..598904d3c44 100644
--- a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs
+++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs
@@ -1,6 +1,5 @@
 #![feature(extern_types)]
 #![feature(core_intrinsics)]
-#![feature(const_size_of_val, const_align_of_val)]
 
 use std::intrinsics::{min_align_of_val, size_of_val};
 
diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr
index ad2de0f4d31..4c0252123a4 100644
--- a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr
+++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr
@@ -1,11 +1,11 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:31
+  --> $DIR/const-size_of_val-align_of_val-extern-type.rs:10:31
    |
 LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:32
+  --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:32
    |
 LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout
diff --git a/tests/ui/consts/const-size_of_val-align_of_val.rs b/tests/ui/consts/const-size_of_val-align_of_val.rs
index ee9dfca0170..d4b5a903517 100644
--- a/tests/ui/consts/const-size_of_val-align_of_val.rs
+++ b/tests/ui/consts/const-size_of_val-align_of_val.rs
@@ -1,7 +1,6 @@
 //@ run-pass
 
-#![feature(const_size_of_val, const_align_of_val)]
-#![feature(const_size_of_val_raw, const_align_of_val_raw, layout_for_ptr)]
+#![feature(layout_for_ptr)]
 
 use std::{mem, ptr};
 
diff --git a/tests/ui/consts/const-try-feature-gate.rs b/tests/ui/consts/const-try-feature-gate.rs
index 1cc045bf612..09985079e8e 100644
--- a/tests/ui/consts/const-try-feature-gate.rs
+++ b/tests/ui/consts/const-try-feature-gate.rs
@@ -2,9 +2,8 @@
 
 const fn t() -> Option<()> {
     Some(())?;
-    //~^ error: `?` is not allowed in a `const fn`
-    //~| ERROR: cannot convert
-    //~| ERROR: cannot determine
+    //~^ ERROR `?` is not allowed
+    //~| ERROR `?` is not allowed
     None
 }
 
diff --git a/tests/ui/consts/const-try-feature-gate.stderr b/tests/ui/consts/const-try-feature-gate.stderr
index dc1dabc2f4f..0ad19d05b38 100644
--- a/tests/ui/consts/const-try-feature-gate.stderr
+++ b/tests/ui/consts/const-try-feature-gate.stderr
@@ -1,34 +1,19 @@
-error[E0658]: `?` is not allowed in a `const fn`
+error[E0015]: `?` is not allowed on `Option<()>` in constant functions
   --> $DIR/const-try-feature-gate.rs:4:5
    |
 LL |     Some(())?;
    |     ^^^^^^^^^
    |
-   = note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
-   = help: add `#![feature(const_try)]` 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[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions
-  --> $DIR/const-try-feature-gate.rs:4:5
-   |
-LL |     Some(())?;
-   |     ^^^^^^^^^
-   |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/option.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions
+error[E0015]: `?` is not allowed on `Option<()>` in constant functions
   --> $DIR/const-try-feature-gate.rs:4:5
    |
 LL |     Some(())?;
    |     ^^^^^^^^^
    |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/option.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0015, E0658.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/const-try.rs b/tests/ui/consts/const-try.rs
index d30b22accef..26aa9230a39 100644
--- a/tests/ui/consts/const-try.rs
+++ b/tests/ui/consts/const-try.rs
@@ -33,8 +33,8 @@ impl const Try for TryMe {
 
 const fn t() -> TryMe {
     TryMe?;
-    //~^ ERROR `?` cannot determine the branch of `TryMe` in constant functions
-    //~| ERROR `?` cannot convert from residual of `TryMe` in constant functions
+    //~^ ERROR `?` is not allowed on
+    //~| ERROR `?` is not allowed on
     TryMe
 }
 
diff --git a/tests/ui/consts/const-try.stderr b/tests/ui/consts/const-try.stderr
index 1f4f814cb93..abb03a74c82 100644
--- a/tests/ui/consts/const-try.stderr
+++ b/tests/ui/consts/const-try.stderr
@@ -16,7 +16,7 @@ LL | impl const Try for TryMe {
    = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
    = note: adding a non-const method body in the future would be a breaking change
 
-error[E0015]: `?` cannot determine the branch of `TryMe` in constant functions
+error[E0015]: `?` is not allowed on `TryMe` in constant functions
   --> $DIR/const-try.rs:35:5
    |
 LL |     TryMe?;
@@ -24,7 +24,7 @@ LL |     TryMe?;
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions
+error[E0015]: `?` is not allowed on `TryMe` in constant functions
   --> $DIR/const-try.rs:35:5
    |
 LL |     TryMe?;
diff --git a/tests/ui/consts/const-tup-index-span.stderr b/tests/ui/consts/const-tup-index-span.stderr
index 792e18aa8fd..2a3f0cfb06d 100644
--- a/tests/ui/consts/const-tup-index-span.stderr
+++ b/tests/ui/consts/const-tup-index-span.stderr
@@ -11,6 +11,12 @@ help: use a trailing comma to create a tuple with one element
 LL | const TUP: (usize,) = (5usize << 64,);
    |                       +            ++
 
+note: erroneous constant encountered
+  --> $DIR/const-tup-index-span.rs:6:18
+   |
+LL | const ARR: [i32; TUP.0] = [];
+   |                  ^^^
+
 error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/consts/const_in_pattern/cross-crate-fail.rs b/tests/ui/consts/const_in_pattern/cross-crate-fail.rs
index 163a47f4333..f02e780f30e 100644
--- a/tests/ui/consts/const_in_pattern/cross-crate-fail.rs
+++ b/tests/ui/consts/const_in_pattern/cross-crate-fail.rs
@@ -9,15 +9,13 @@ fn main() {
     let _ = Defaulted;
     match None {
         consts::SOME => panic!(),
-        //~^ must be annotated with `#[derive(PartialEq)]`
-
+        //~^ ERROR constant of non-structural type `CustomEq` in a pattern
         _ => {}
     }
 
     match None {
         <Defaulted as consts::AssocConst>::SOME  => panic!(),
-        //~^ must be annotated with `#[derive(PartialEq)]`
-
+        //~^ ERROR constant of non-structural type `CustomEq` in a pattern
         _ => {}
     }
 }
diff --git a/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr b/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr
index e0f97a9abd2..7cada883645 100644
--- a/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr
+++ b/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr
@@ -1,19 +1,33 @@
-error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq)]`
+error: constant of non-structural type `CustomEq` in a pattern
   --> $DIR/cross-crate-fail.rs:11:9
    |
 LL |         consts::SOME => panic!(),
-   |         ^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^ constant of non-structural type
+   |
+  ::: $DIR/auxiliary/consts.rs:1:1
+   |
+LL | pub struct CustomEq;
+   | ------------------- `CustomEq` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL | pub const SOME: Option<CustomEq> = Some(CustomEq);
+   | -------------------------------- constant defined here
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
-error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/cross-crate-fail.rs:18:9
+error: constant of non-structural type `CustomEq` in a pattern
+  --> $DIR/cross-crate-fail.rs:17:9
    |
 LL |         <Defaulted as consts::AssocConst>::SOME  => panic!(),
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
+   |
+  ::: $DIR/auxiliary/consts.rs:1:1
+   |
+LL | pub struct CustomEq;
+   | ------------------- `CustomEq` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     const SOME: Option<CustomEq> = Some(CustomEq);
+   |     ---------------------------- constant defined here
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr
index aa208341c13..0453a88e43d 100644
--- a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr
+++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr
@@ -1,26 +1,46 @@
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:9:9
    |
+LL | const C: *const u8 = &0;
+   | ------------------ constant defined here
+...
 LL |         C => {}
-   |         ^
+   |         ^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:16:9
    |
+LL | const C_INNER: (*const u8, u8) = (C, 0);
+   | ------------------------------ constant defined here
+...
 LL |         C_INNER => {}
-   |         ^^^^^^^
+   |         ^^^^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:27:9
    |
+LL | const D: *const [u8; 4] = b"abcd";
+   | ----------------------- constant defined here
+...
 LL |         D => {}
-   |         ^
+   |         ^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:32:9
    |
+LL | const STR: *const str = "abcd";
+   | --------------------- constant defined here
+...
 LL |         STR => {}
-   |         ^^^
+   |         ^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/consts/const_in_pattern/issue-44333.stderr b/tests/ui/consts/const_in_pattern/issue-44333.stderr
index d377bfd95f9..61b45377c76 100644
--- a/tests/ui/consts/const_in_pattern/issue-44333.stderr
+++ b/tests/ui/consts/const_in_pattern/issue-44333.stderr
@@ -1,14 +1,24 @@
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/issue-44333.rs:15:9
    |
+LL | const FOO: Func = foo;
+   | --------------- constant defined here
+...
 LL |         FOO => println!("foo"),
-   |         ^^^
+   |         ^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/issue-44333.rs:16:9
    |
+LL | const BAR: Func = bar;
+   | --------------- constant defined here
+...
 LL |         BAR => println!("bar"),
-   |         ^^^
+   |         ^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/const_in_pattern/issue-65466.rs b/tests/ui/consts/const_in_pattern/issue-65466.rs
index 62efce64876..82838657b02 100644
--- a/tests/ui/consts/const_in_pattern/issue-65466.rs
+++ b/tests/ui/consts/const_in_pattern/issue-65466.rs
@@ -11,7 +11,7 @@ const C: &[O<B>] = &[O::None];
 fn main() {
     let x = O::None;
     match &[x][..] {
-        C => (), //~ERROR: the type must implement `PartialEq`
+        C => (), //~ ERROR constant of non-structural type `&[O<B>]` in a pattern
         _ => (),
     }
 }
diff --git a/tests/ui/consts/const_in_pattern/issue-65466.stderr b/tests/ui/consts/const_in_pattern/issue-65466.stderr
index 7d5e5b5b0c6..511a38bbc00 100644
--- a/tests/ui/consts/const_in_pattern/issue-65466.stderr
+++ b/tests/ui/consts/const_in_pattern/issue-65466.stderr
@@ -1,8 +1,16 @@
-error: to use a constant of type `&[O<B>]` in a pattern, the type must implement `PartialEq`
+error: constant of non-structural type `&[O<B>]` in a pattern
   --> $DIR/issue-65466.rs:14:9
    |
+LL | struct B;
+   | -------- must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+LL |
+LL | const C: &[O<B>] = &[O::None];
+   | ---------------- constant defined here
+...
 LL |         C => (),
-   |         ^
+   |         ^ constant of non-structural type
+   |
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs
index cf013c1a790..91ef5ac5329 100644
--- a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs
+++ b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs
@@ -16,8 +16,7 @@ const BAR_BAZ: Foo = if 42 == 42 {
 
 fn main() {
     match Foo::Qux(NoEq) {
-        BAR_BAZ => panic!(),
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        BAR_BAZ => panic!(), //~ ERROR constant of non-structural type `Foo` in a pattern
         _ => {}
     }
 }
diff --git a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr
index 7766c6ce683..154c94c6d38 100644
--- a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr
+++ b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr
@@ -1,10 +1,15 @@
-error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq)]`
+error: constant of non-structural type `Foo` in a pattern
   --> $DIR/no-eq-branch-fail.rs:19:9
    |
+LL | enum Foo {
+   | -------- `Foo` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL | const BAR_BAZ: Foo = if 42 == 42 {
+   | ------------------ constant defined here
+...
 LL |         BAR_BAZ => panic!(),
-   |         ^^^^^^^
+   |         ^^^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs
index 645e1418912..e555ecfeb8f 100644
--- a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs
+++ b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs
@@ -26,7 +26,7 @@ fn main() {
 
     match None {
         NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"),
-        //~^ ERROR must implement `PartialEq`
+        //~^ ERROR constant of non-structural type `Option<NoPartialEq>` in a pattern
         _ => panic!("whoops"),
     }
 }
diff --git a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr
index ed531a1fead..43894f00886 100644
--- a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr
+++ b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr
@@ -1,8 +1,16 @@
-error: to use a constant of type `Option<NoPartialEq>` in a pattern, the type must implement `PartialEq`
+error: constant of non-structural type `Option<NoPartialEq>` in a pattern
   --> $DIR/reject_non_partial_eq.rs:28:9
    |
+LL | struct NoPartialEq(u32);
+   | ------------------ must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL | const NO_PARTIAL_EQ_NONE: Option<NoPartialEq> = None;
+   | --------------------------------------------- constant defined here
+...
 LL |         NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"),
-   |         ^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^ constant of non-structural type
+   |
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.rs b/tests/ui/consts/const_in_pattern/reject_non_structural.rs
index e3dcecec960..39e5f732a89 100644
--- a/tests/ui/consts/const_in_pattern/reject_non_structural.rs
+++ b/tests/ui/consts/const_in_pattern/reject_non_structural.rs
@@ -17,9 +17,29 @@ struct NoPartialEq;
 
 #[derive(Copy, Clone, Debug)]
 struct NoDerive;
+//~^ NOTE must be annotated with `#[derive(PartialEq)]`
+//~| NOTE must be annotated with `#[derive(PartialEq)]`
+//~| NOTE must be annotated with `#[derive(PartialEq)]`
+//~| NOTE must be annotated with `#[derive(PartialEq)]`
+//~| NOTE must be annotated with `#[derive(PartialEq)]`
+//~| NOTE must be annotated with `#[derive(PartialEq)]`
+//~| NOTE must be annotated with `#[derive(PartialEq)]`
+//~| NOTE must be annotated with `#[derive(PartialEq)]`
+//~| NOTE must be annotated with `#[derive(PartialEq)]`
+//~| NOTE must be annotated with `#[derive(PartialEq)]`
 
 // This impl makes `NoDerive` irreflexive.
 impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+//~^ NOTE StructuralPartialEq.html for details
+//~| NOTE StructuralPartialEq.html for details
+//~| NOTE StructuralPartialEq.html for details
+//~| NOTE StructuralPartialEq.html for details
+//~| NOTE StructuralPartialEq.html for details
+//~| NOTE StructuralPartialEq.html for details
+//~| NOTE StructuralPartialEq.html for details
+//~| NOTE StructuralPartialEq.html for details
+//~| NOTE StructuralPartialEq.html for details
+//~| NOTE StructuralPartialEq.html for details
 
 impl Eq for NoDerive { }
 
@@ -36,65 +56,55 @@ fn main() {
     #[derive(PartialEq, Eq, Debug)]
     enum Derive<X> { Some(X), None, }
 
-    const ENUM: Derive<NoDerive> = Derive::Some(NoDerive);
+    const ENUM: Derive<NoDerive> = Derive::Some(NoDerive); //~ NOTE constant defined here
     match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
-    //~^ ERROR must be annotated with `#[derive(PartialEq)]`
-    //~| NOTE the traits must be derived
-    //~| NOTE StructuralPartialEq.html for details
+    //~^ ERROR constant of non-structural type `NoDerive` in a pattern
+    //~| NOTE constant of non-structural type
 
-    const FIELD: OND = TrivialEq(Some(NoDerive)).0;
+    const FIELD: OND = TrivialEq(Some(NoDerive)).0; //~ NOTE constant defined here
     match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
-    //~^ ERROR must be annotated with `#[derive(PartialEq)]`
-    //~| NOTE the traits must be derived
-    //~| NOTE StructuralPartialEq.html for details
+    //~^ ERROR constant of non-structural type `NoDerive` in a pattern
+    //~| NOTE constant of non-structural type
 
     const NO_DERIVE_SOME: OND = Some(NoDerive);
-    const INDIRECT: OND = NO_DERIVE_SOME;
+    const INDIRECT: OND = NO_DERIVE_SOME; //~ NOTE constant defined here
     match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
-    //~^ ERROR must be annotated with `#[derive(PartialEq)]`
-    //~| NOTE the traits must be derived
-    //~| NOTE StructuralPartialEq.html for details
+    //~^ ERROR constant of non-structural type `NoDerive` in a pattern
+    //~| NOTE constant of non-structural type
 
-    const TUPLE: (OND, OND) = (None, Some(NoDerive));
+    const TUPLE: (OND, OND) = (None, Some(NoDerive)); //~ NOTE constant defined here
     match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
-    //~^ ERROR must be annotated with `#[derive(PartialEq)]`
-    //~| NOTE the traits must be derived
-    //~| NOTE StructuralPartialEq.html for details
+    //~^ ERROR constant of non-structural type `NoDerive` in a pattern
+    //~| NOTE constant of non-structural type
 
-    const TYPE_ASCRIPTION: OND = type_ascribe!(Some(NoDerive), OND);
+    const TYPE_ASCRIPTION: OND = type_ascribe!(Some(NoDerive), OND); //~ NOTE constant defined here
     match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), };
-    //~^ ERROR must be annotated with `#[derive(PartialEq)]`
-    //~| NOTE the traits must be derived
-    //~| NOTE StructuralPartialEq.html for details
+    //~^ ERROR constant of non-structural type `NoDerive` in a pattern
+    //~| NOTE constant of non-structural type
 
-    const ARRAY: [OND; 2] = [None, Some(NoDerive)];
+    const ARRAY: [OND; 2] = [None, Some(NoDerive)]; //~ NOTE constant defined here
     match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
-    //~^ ERROR must be annotated with `#[derive(PartialEq)]`
-    //~| NOTE the traits must be derived
-    //~| NOTE StructuralPartialEq.html for details
+    //~^ ERROR constant of non-structural type `NoDerive` in a pattern
+    //~| NOTE constant of non-structural type
 
-    const REPEAT: [OND; 2] = [Some(NoDerive); 2];
+    const REPEAT: [OND; 2] = [Some(NoDerive); 2]; //~ NOTE constant defined here
     match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
-    //~^ ERROR must be annotated with `#[derive(PartialEq)]`
-    //~| NOTE the traits must be derived
-    //~| NOTE StructuralPartialEq.html for details
+    //~^ ERROR constant of non-structural type `NoDerive` in a pattern
+    //~| NOTE constant of non-structural type
 
-    trait Trait: Sized { const ASSOC: Option<Self>; }
+    trait Trait: Sized { const ASSOC: Option<Self>; } //~ NOTE constant defined here
     impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
     match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
-    //~^ ERROR must be annotated with `#[derive(PartialEq)]`
-    //~| NOTE the traits must be derived
-    //~| NOTE StructuralPartialEq.html for details
+    //~^ ERROR constant of non-structural type `NoDerive` in a pattern
+    //~| NOTE constant of non-structural type
 
-    const BLOCK: OND = { NoDerive; Some(NoDerive) };
+    const BLOCK: OND = { NoDerive; Some(NoDerive) }; //~ NOTE constant defined here
     match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
-    //~^ ERROR must be annotated with `#[derive(PartialEq)]`
-    //~| NOTE the traits must be derived
-    //~| NOTE StructuralPartialEq.html for details
+    //~^ ERROR constant of non-structural type `NoDerive` in a pattern
+    //~| NOTE constant of non-structural type
 
-    const ADDR_OF: &OND = &Some(NoDerive);
+    const ADDR_OF: &OND = &Some(NoDerive); //~ NOTE constant defined here
     match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
-    //~^ ERROR must be annotated with `#[derive(PartialEq)]`
-    //~| NOTE the traits must be derived
-    //~| NOTE StructuralPartialEq.html for details
+    //~^ ERROR constant of non-structural type `NoDerive` in a pattern
+    //~| NOTE constant of non-structural type
 }
diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr
index c068db42e4d..fa16d0b06a7 100644
--- a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr
+++ b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr
@@ -1,92 +1,173 @@
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/reject_non_structural.rs:40:36
-   |
+error: constant of non-structural type `NoDerive` in a pattern
+  --> $DIR/reject_non_structural.rs:60:36
+   |
+LL | struct NoDerive;
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     const ENUM: Derive<NoDerive> = Derive::Some(NoDerive);
+   |     ---------------------------- constant defined here
 LL |     match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
-   |                                    ^^^^
+   |                                    ^^^^ constant of non-structural type
+   |
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/reject_non_structural.rs:32:1
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/reject_non_structural.rs:46:28
+error: constant of non-structural type `NoDerive` in a pattern
+  --> $DIR/reject_non_structural.rs:65:28
    |
+LL | struct NoDerive;
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     const FIELD: OND = TrivialEq(Some(NoDerive)).0;
+   |     ---------------- constant defined here
 LL |     match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
-   |                            ^^^^^
+   |                            ^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/reject_non_structural.rs:53:27
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/reject_non_structural.rs:32:1
    |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: constant of non-structural type `NoDerive` in a pattern
+  --> $DIR/reject_non_structural.rs:71:27
+   |
+LL | struct NoDerive;
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     const INDIRECT: OND = NO_DERIVE_SOME;
+   |     ------------------- constant defined here
 LL |     match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
-   |                           ^^^^^^^^
+   |                           ^^^^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/reject_non_structural.rs:59:36
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/reject_non_structural.rs:32:1
    |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: constant of non-structural type `NoDerive` in a pattern
+  --> $DIR/reject_non_structural.rs:76:36
+   |
+LL | struct NoDerive;
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     const TUPLE: (OND, OND) = (None, Some(NoDerive));
+   |     ----------------------- constant defined here
 LL |     match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
-   |                                    ^^^^^
+   |                                    ^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/reject_non_structural.rs:65:28
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/reject_non_structural.rs:32:1
    |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: constant of non-structural type `NoDerive` in a pattern
+  --> $DIR/reject_non_structural.rs:81:28
+   |
+LL | struct NoDerive;
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     const TYPE_ASCRIPTION: OND = type_ascribe!(Some(NoDerive), OND);
+   |     -------------------------- constant defined here
 LL |     match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), };
-   |                            ^^^^^^^^^^^^^^^
+   |                            ^^^^^^^^^^^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/reject_non_structural.rs:71:36
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/reject_non_structural.rs:32:1
    |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: constant of non-structural type `NoDerive` in a pattern
+  --> $DIR/reject_non_structural.rs:86:36
+   |
+LL | struct NoDerive;
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     const ARRAY: [OND; 2] = [None, Some(NoDerive)];
+   |     --------------------- constant defined here
 LL |     match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
-   |                                    ^^^^^
+   |                                    ^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/reject_non_structural.rs:77:33
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/reject_non_structural.rs:32:1
    |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: constant of non-structural type `NoDerive` in a pattern
+  --> $DIR/reject_non_structural.rs:91:33
+   |
+LL | struct NoDerive;
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     const REPEAT: [OND; 2] = [Some(NoDerive); 2];
+   |     ---------------------- constant defined here
 LL |     match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
-   |                                 ^^^^^^
+   |                                 ^^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/reject_non_structural.rs:84:28
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/reject_non_structural.rs:32:1
    |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: constant of non-structural type `NoDerive` in a pattern
+  --> $DIR/reject_non_structural.rs:97:28
+   |
+LL | struct NoDerive;
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     trait Trait: Sized { const ASSOC: Option<Self>; }
+   |     ------------------   ------------------------- constant defined here
+LL |     impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
 LL |     match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
-   |                            ^^^^^^^^^^^^^^^
+   |                            ^^^^^^^^^^^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/reject_non_structural.rs:90:28
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/reject_non_structural.rs:32:1
    |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: constant of non-structural type `NoDerive` in a pattern
+  --> $DIR/reject_non_structural.rs:102:28
+   |
+LL | struct NoDerive;
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     const BLOCK: OND = { NoDerive; Some(NoDerive) };
+   |     ---------------- constant defined here
 LL |     match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
-   |                            ^^^^^
+   |                            ^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/reject_non_structural.rs:96:29
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/reject_non_structural.rs:32:1
    |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: constant of non-structural type `NoDerive` in a pattern
+  --> $DIR/reject_non_structural.rs:107:29
+   |
+LL | struct NoDerive;
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     const ADDR_OF: &OND = &Some(NoDerive);
+   |     ------------------- constant defined here
 LL |     match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
-   |                             ^^^^^^^
+   |                             ^^^^^^^ constant of non-structural type
+   |
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/reject_non_structural.rs:32:1
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 10 previous errors
 
diff --git a/tests/ui/consts/const_refs_to_static_fail_invalid.rs b/tests/ui/consts/const_refs_to_static_fail_invalid.rs
index a160862a0fa..aa101cf9d8a 100644
--- a/tests/ui/consts/const_refs_to_static_fail_invalid.rs
+++ b/tests/ui/consts/const_refs_to_static_fail_invalid.rs
@@ -11,7 +11,7 @@ fn invalid() {
 
     // This must be rejected here (or earlier), since it's not a valid `&bool`.
     match &true {
-        C => {} //~ERROR: could not evaluate constant pattern
+        C => {} // ok, `const` already emitted an error
         _ => {}
     }
 }
@@ -27,7 +27,7 @@ fn extern_() {
 
     // This must be rejected here (or earlier), since the pattern cannot be read.
     match &0 {
-        C => {} //~ERROR: could not evaluate constant pattern
+        C => {} // ok, `const` already emitted an error
         _ => {}
     }
 }
@@ -42,7 +42,7 @@ fn mutable() {
     // This *must not build*, the constant we are matching against
     // could change its value!
     match &42 {
-        C => {} //~ERROR: could not evaluate constant pattern
+        C => {} // ok, `const` already emitted an error
         _ => {}
     }
 }
diff --git a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr
index 0153f501174..c9d5cb60bf7 100644
--- a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr
+++ b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr
@@ -31,24 +31,6 @@ LL |     const C: &i32 = unsafe { &S_MUT };
                HEX_DUMP
            }
 
-error: could not evaluate constant pattern
-  --> $DIR/const_refs_to_static_fail_invalid.rs:14:9
-   |
-LL |         C => {}
-   |         ^
-
-error: could not evaluate constant pattern
-  --> $DIR/const_refs_to_static_fail_invalid.rs:30:9
-   |
-LL |         C => {}
-   |         ^
-
-error: could not evaluate constant pattern
-  --> $DIR/const_refs_to_static_fail_invalid.rs:45:9
-   |
-LL |         C => {}
-   |         ^
-
-error: aborting due to 6 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/control-flow/loop.rs b/tests/ui/consts/control-flow/loop.rs
index f8d9f3ddb9b..b02c31c4c25 100644
--- a/tests/ui/consts/control-flow/loop.rs
+++ b/tests/ui/consts/control-flow/loop.rs
@@ -50,15 +50,15 @@ const _: i32 = {
 const _: i32 = {
     let mut x = 0;
 
-    for i in 0..4 { //~ ERROR `for` is not allowed in a `const`
-        //~^ ERROR: cannot call
-        //~| ERROR: cannot convert
+    for i in 0..4 {
+        //~^ ERROR: cannot use `for`
+        //~| ERROR: cannot use `for`
         x += i;
     }
 
-    for i in 0..4 { //~ ERROR `for` is not allowed in a `const`
-        //~^ ERROR: cannot call
-        //~| ERROR: cannot convert
+    for i in 0..4 {
+        //~^ ERROR: cannot use `for`
+        //~| ERROR: cannot use `for`
         x += i;
     }
 
diff --git a/tests/ui/consts/control-flow/loop.stderr b/tests/ui/consts/control-flow/loop.stderr
index 5e43c70e9df..b91371f9dc2 100644
--- a/tests/ui/consts/control-flow/loop.stderr
+++ b/tests/ui/consts/control-flow/loop.stderr
@@ -1,68 +1,37 @@
-error[E0658]: `for` is not allowed in a `const`
-  --> $DIR/loop.rs:53:5
-   |
-LL | /     for i in 0..4 {
-LL | |
-LL | |
-LL | |         x += i;
-LL | |     }
-   | |_____^
-   |
-   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
-   = help: add `#![feature(const_for)]` 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[E0658]: `for` is not allowed in a `const`
-  --> $DIR/loop.rs:59:5
-   |
-LL | /     for i in 0..4 {
-LL | |
-LL | |
-LL | |         x += i;
-LL | |     }
-   | |_____^
-   |
-   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
-   = help: add `#![feature(const_for)]` 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[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants
+error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants
   --> $DIR/loop.rs:53:14
    |
 LL |     for i in 0..4 {
    |              ^^^^
    |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
+error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants
   --> $DIR/loop.rs:53:14
    |
 LL |     for i in 0..4 {
    |              ^^^^
    |
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants
+error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants
   --> $DIR/loop.rs:59:14
    |
 LL |     for i in 0..4 {
    |              ^^^^
    |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
+error[E0015]: cannot use `for` loop on `std::ops::Range<i32>` in constants
   --> $DIR/loop.rs:59:14
    |
 LL |     for i in 0..4 {
    |              ^^^^
    |
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0015, E0658.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/control-flow/try.rs b/tests/ui/consts/control-flow/try.rs
index 5c6957df405..67083e1a39b 100644
--- a/tests/ui/consts/control-flow/try.rs
+++ b/tests/ui/consts/control-flow/try.rs
@@ -3,9 +3,9 @@
 
 const fn opt() -> Option<i32> {
     let x = Some(2);
-    x?; //~ ERROR `?` is not allowed in a `const fn`
-    //~^ ERROR: cannot convert
-    //~| ERROR: cannot determine
+    x?;
+    //~^ ERROR: `?` is not allowed
+    //~| ERROR: `?` is not allowed
     None
 }
 
diff --git a/tests/ui/consts/control-flow/try.stderr b/tests/ui/consts/control-flow/try.stderr
index 5e2c77318e7..62a3e3ce6bc 100644
--- a/tests/ui/consts/control-flow/try.stderr
+++ b/tests/ui/consts/control-flow/try.stderr
@@ -1,34 +1,19 @@
-error[E0658]: `?` is not allowed in a `const fn`
+error[E0015]: `?` is not allowed on `Option<i32>` in constant functions
   --> $DIR/try.rs:6:5
    |
 LL |     x?;
    |     ^^
    |
-   = note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
-   = help: add `#![feature(const_try)]` 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[E0015]: `?` cannot determine the branch of `Option<i32>` in constant functions
-  --> $DIR/try.rs:6:5
-   |
-LL |     x?;
-   |     ^^
-   |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/option.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: `?` cannot convert from residual of `Option<i32>` in constant functions
+error[E0015]: `?` is not allowed on `Option<i32>` in constant functions
   --> $DIR/try.rs:6:5
    |
 LL |     x?;
    |     ^^
    |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/option.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0015, E0658.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr
index 2e48837bdcd..b22f99f40d3 100644
--- a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr
+++ b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr
@@ -11,7 +11,7 @@ error: could not evaluate constant pattern
   --> $DIR/invalid-inline-const-in-match-arm.rs:5:9
    |
 LL |         const { (|| {})() } => {}
-   |         ^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^ could not evaluate constant
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/issue-43105.rs b/tests/ui/consts/issue-43105.rs
index 20b78d64209..a4ee34c0532 100644
--- a/tests/ui/consts/issue-43105.rs
+++ b/tests/ui/consts/issue-43105.rs
@@ -5,8 +5,7 @@ const NUM: u8 = xyz();
 
 fn main() {
     match 1 {
-        NUM => unimplemented!(),
-        //~^ ERROR could not evaluate constant pattern
+        NUM => unimplemented!(), // ok, the `const` already emitted an error
         _ => unimplemented!(),
     }
 }
diff --git a/tests/ui/consts/issue-43105.stderr b/tests/ui/consts/issue-43105.stderr
index 856a8f0dab6..0e08feb58de 100644
--- a/tests/ui/consts/issue-43105.stderr
+++ b/tests/ui/consts/issue-43105.stderr
@@ -6,12 +6,6 @@ LL | const NUM: u8 = xyz();
    |
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error: could not evaluate constant pattern
-  --> $DIR/issue-43105.rs:8:9
-   |
-LL |         NUM => unimplemented!(),
-   |         ^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/issue-54954.stderr b/tests/ui/consts/issue-54954.stderr
index b8c983eb7b8..ed6aa9c44a3 100644
--- a/tests/ui/consts/issue-54954.stderr
+++ b/tests/ui/consts/issue-54954.stderr
@@ -19,6 +19,24 @@ LL | |         core::mem::size_of::<T>()
 LL | |     }
    | |_____- `Tt::const_val` defined here
 
+note: erroneous constant encountered
+  --> $DIR/issue-54954.rs:11:15
+   |
+LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
+   |               ^^^^^^^
+
+note: erroneous constant encountered
+  --> $DIR/issue-54954.rs:11:34
+   |
+LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
+   |                                  ^^^^^^^
+
+note: erroneous constant encountered
+  --> $DIR/issue-54954.rs:16:22
+   |
+LL |     let _ = f([1f32; ARR_LEN]);
+   |                      ^^^^^^^
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0379, E0790.
diff --git a/tests/ui/consts/issue-73976-polymorphic.rs b/tests/ui/consts/issue-73976-polymorphic.rs
index 2c576d1f9ef..98b4005792d 100644
--- a/tests/ui/consts/issue-73976-polymorphic.rs
+++ b/tests/ui/consts/issue-73976-polymorphic.rs
@@ -18,7 +18,7 @@ impl<T: 'static> GetTypeId<T> {
 
 const fn check_type_id<T: 'static>() -> bool {
     matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE)
-    //~^ ERROR constant pattern depends on a generic parameter
+    //~^ ERROR constant pattern cannot depend on generic parameters
 }
 
 pub struct GetTypeNameLen<T>(T);
@@ -29,7 +29,7 @@ impl<T: 'static> GetTypeNameLen<T> {
 
 const fn check_type_name_len<T: 'static>() -> bool {
     matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
-    //~^ ERROR constant pattern depends on a generic parameter
+    //~^ ERROR constant pattern cannot depend on generic parameters
 }
 
 fn main() {
diff --git a/tests/ui/consts/issue-73976-polymorphic.stderr b/tests/ui/consts/issue-73976-polymorphic.stderr
index 8a44eb9854f..ec9512a2616 100644
--- a/tests/ui/consts/issue-73976-polymorphic.stderr
+++ b/tests/ui/consts/issue-73976-polymorphic.stderr
@@ -1,14 +1,28 @@
-error[E0158]: constant pattern depends on a generic parameter
+error[E0158]: constant pattern cannot depend on generic parameters
   --> $DIR/issue-73976-polymorphic.rs:20:37
    |
+LL | impl<T: 'static> GetTypeId<T> {
+   | -----------------------------
+LL |     pub const VALUE: TypeId = TypeId::of::<T>();
+   |     ----------------------- constant defined here
+...
+LL | const fn check_type_id<T: 'static>() -> bool {
+   |                        - constant depends on this generic parameter
 LL |     matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE)
-   |                                     ^^^^^^^^^^^^^^^^^^^^^
+   |                                     ^^^^^^^^^^^^^^^^^^^^^ `const` depends on a generic parameter
 
-error[E0158]: constant pattern depends on a generic parameter
+error[E0158]: constant pattern cannot depend on generic parameters
   --> $DIR/issue-73976-polymorphic.rs:31:42
    |
+LL | impl<T: 'static> GetTypeNameLen<T> {
+   | ----------------------------------
+LL |     pub const VALUE: usize = any::type_name::<T>().len();
+   |     ---------------------- constant defined here
+...
+LL | const fn check_type_name_len<T: 'static>() -> bool {
+   |                              - constant depends on this generic parameter
 LL |     matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^ `const` depends on a generic parameter
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/issue-78655.rs b/tests/ui/consts/issue-78655.rs
index cd95ee32c60..b0f862e8418 100644
--- a/tests/ui/consts/issue-78655.rs
+++ b/tests/ui/consts/issue-78655.rs
@@ -4,6 +4,5 @@ const FOO: *const u32 = {
 };
 
 fn main() {
-    let FOO = FOO;
-    //~^ ERROR could not evaluate constant pattern
+    let FOO = FOO; // ok, the `const` already emitted an error
 }
diff --git a/tests/ui/consts/issue-78655.stderr b/tests/ui/consts/issue-78655.stderr
index ccaed03b4c1..6a93c1a8cec 100644
--- a/tests/ui/consts/issue-78655.stderr
+++ b/tests/ui/consts/issue-78655.stderr
@@ -11,12 +11,6 @@ help: consider assigning a value
 LL |     let x = 42;
    |           ++++
 
-error: could not evaluate constant pattern
-  --> $DIR/issue-78655.rs:7:9
-   |
-LL |     let FOO = FOO;
-   |         ^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0381`.
diff --git a/tests/ui/consts/issue-79137-toogeneric.rs b/tests/ui/consts/issue-79137-toogeneric.rs
index a80c9f48d7b..43e06f3d676 100644
--- a/tests/ui/consts/issue-79137-toogeneric.rs
+++ b/tests/ui/consts/issue-79137-toogeneric.rs
@@ -10,7 +10,7 @@ impl<T> GetVariantCount<T> {
 
 const fn check_variant_count<T>() -> bool {
     matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
-    //~^ ERROR constant pattern depends on a generic parameter
+    //~^ ERROR constant pattern cannot depend on generic parameters
 }
 
 fn main() {
diff --git a/tests/ui/consts/issue-79137-toogeneric.stderr b/tests/ui/consts/issue-79137-toogeneric.stderr
index de81512ec6d..33e32a7d15d 100644
--- a/tests/ui/consts/issue-79137-toogeneric.stderr
+++ b/tests/ui/consts/issue-79137-toogeneric.stderr
@@ -1,8 +1,15 @@
-error[E0158]: constant pattern depends on a generic parameter
+error[E0158]: constant pattern cannot depend on generic parameters
   --> $DIR/issue-79137-toogeneric.rs:12:43
    |
+LL | impl<T> GetVariantCount<T> {
+   | --------------------------
+LL |     pub const VALUE: usize = std::mem::variant_count::<T>();
+   |     ---------------------- constant defined here
+...
+LL | const fn check_variant_count<T>() -> bool {
+   |                              - constant depends on this generic parameter
 LL |     matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `const` depends on a generic parameter
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/issue-87046.stderr b/tests/ui/consts/issue-87046.stderr
index 0f965e1ac3f..36e2564fae6 100644
--- a/tests/ui/consts/issue-87046.stderr
+++ b/tests/ui/consts/issue-87046.stderr
@@ -1,6 +1,9 @@
 error: cannot use unsized non-slice type `Username` in constant patterns
   --> $DIR/issue-87046.rs:28:13
    |
+LL | pub const ROOT_USER: &Username = Username::from_str("root");
+   | ------------------------------ constant defined here
+...
 LL |             ROOT_USER => true,
    |             ^^^^^^^^^
 
diff --git a/tests/ui/consts/issue-89088.rs b/tests/ui/consts/issue-89088.rs
index 02a786e7465..f6dbf8f0125 100644
--- a/tests/ui/consts/issue-89088.rs
+++ b/tests/ui/consts/issue-89088.rs
@@ -13,7 +13,7 @@ fn main() {
     let var = A::Field(Cow::Borrowed("bar"));
 
     match &var {
-        FOO => todo!(), //~ERROR derive(PartialEq)
+        FOO => todo!(), //~ ERROR constant of non-structural type `Cow<'_, str>` in a pattern
         _ => todo!()
     }
 }
diff --git a/tests/ui/consts/issue-89088.stderr b/tests/ui/consts/issue-89088.stderr
index 362c63a2a45..56025e0d9b2 100644
--- a/tests/ui/consts/issue-89088.stderr
+++ b/tests/ui/consts/issue-89088.stderr
@@ -1,10 +1,15 @@
-error: to use a constant of type `Cow<'_, str>` in a pattern, `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]`
+error: constant of non-structural type `Cow<'_, str>` in a pattern
   --> $DIR/issue-89088.rs:16:9
    |
+LL | const FOO: &A = &A::Field(Cow::Borrowed("foo"));
+   | ------------- constant defined here
+...
 LL |         FOO => todo!(),
-   |         ^^^
+   |         ^^^ constant of non-structural type
+  --> $SRC_DIR/alloc/src/borrow.rs:LL:COL
+   |
+   = note: `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/consts/match_ice.rs b/tests/ui/consts/match_ice.rs
index ed1fd78809b..477a2de09a4 100644
--- a/tests/ui/consts/match_ice.rs
+++ b/tests/ui/consts/match_ice.rs
@@ -8,8 +8,7 @@ struct T;
 fn main() {
     const C: &S = &S;
     match C {
-        C => {}
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        C => {} //~ ERROR constant of non-structural type `S` in a pattern
     }
     const K: &T = &T;
     match K {
diff --git a/tests/ui/consts/match_ice.stderr b/tests/ui/consts/match_ice.stderr
index 472c24a5cbe..95e96bbbd67 100644
--- a/tests/ui/consts/match_ice.stderr
+++ b/tests/ui/consts/match_ice.stderr
@@ -1,10 +1,15 @@
-error: to use a constant of type `S` in a pattern, `S` must be annotated with `#[derive(PartialEq)]`
+error: constant of non-structural type `S` in a pattern
   --> $DIR/match_ice.rs:11:9
    |
+LL | struct S;
+   | -------- `S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     const C: &S = &S;
+   |     ----------- constant defined here
+LL |     match C {
 LL |         C => {}
-   |         ^
+   |         ^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
index a6d75658c75..facb21a04ef 100644
--- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
+++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
@@ -37,16 +37,14 @@ const U8_MUT3: &u8 = {
 
 pub fn test(x: &[u8; 1]) -> bool {
     match x {
-        SLICE_MUT => true,
-        //~^ ERROR could not evaluate constant pattern
+        SLICE_MUT => true, // ok, `const` error already emitted
         &[1..] => false,
     }
 }
 
 pub fn test2(x: &u8) -> bool {
     match x {
-        U8_MUT => true,
-        //~^ ERROR could not evaluate constant pattern
+        U8_MUT => true, // ok, `const` error already emitted
         &(1..) => false,
     }
 }
@@ -55,15 +53,13 @@ pub fn test2(x: &u8) -> bool {
 // the errors above otherwise stop compilation too early?
 pub fn test3(x: &u8) -> bool {
     match x {
-        U8_MUT2 => true,
-        //~^ ERROR could not evaluate constant pattern
+        U8_MUT2 => true, // ok, `const` error already emitted
         &(1..) => false,
     }
 }
 pub fn test4(x: &u8) -> bool {
     match x {
-        U8_MUT3 => true,
-        //~^ ERROR could not evaluate constant pattern
+        U8_MUT3 => true, // ok, `const` error already emitted
         &(1..) => false,
     }
 }
diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr
index 147d3f238f7..8f8271cce38 100644
--- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr
+++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr
@@ -37,30 +37,6 @@ error[E0080]: evaluation of constant value failed
 LL |         match static_cross_crate::OPT_ZERO {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses mutable global memory
 
-error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:40:9
-   |
-LL |         SLICE_MUT => true,
-   |         ^^^^^^^^^
-
-error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:48:9
-   |
-LL |         U8_MUT => true,
-   |         ^^^^^^
-
-error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:58:9
-   |
-LL |         U8_MUT2 => true,
-   |         ^^^^^^^
-
-error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:65:9
-   |
-LL |         U8_MUT3 => true,
-   |         ^^^^^^^
-
-error: aborting due to 8 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/missing_assoc_const_type.rs b/tests/ui/consts/missing_assoc_const_type.rs
index 633998e9bc1..61042bfa96d 100644
--- a/tests/ui/consts/missing_assoc_const_type.rs
+++ b/tests/ui/consts/missing_assoc_const_type.rs
@@ -9,14 +9,13 @@ trait Range {
 
 struct TwoDigits;
 impl Range for TwoDigits {
-    const FIRST:  = 10;
-    //~^ ERROR: missing type for `const` item
+    const FIRST:  = 10; //~ ERROR missing type for `const` item
     const LAST: u8 = 99;
 }
 
 const fn digits(x: u8) -> usize {
     match x {
-        TwoDigits::FIRST..=TwoDigits::LAST => 0, //~ ERROR: could not evaluate constant pattern
+        TwoDigits::FIRST..=TwoDigits::LAST => 0, // ok, `const` error already emitted
         0..=9 | 100..=255 => panic!(),
     }
 }
diff --git a/tests/ui/consts/missing_assoc_const_type.stderr b/tests/ui/consts/missing_assoc_const_type.stderr
index ef7ff962d2d..28af1f0f321 100644
--- a/tests/ui/consts/missing_assoc_const_type.stderr
+++ b/tests/ui/consts/missing_assoc_const_type.stderr
@@ -4,11 +4,5 @@ error: missing type for `const` item
 LL |     const FIRST:  = 10;
    |                 ^ help: provide a type for the associated constant: `u8`
 
-error: could not evaluate constant pattern
-  --> $DIR/missing_assoc_const_type.rs:19:9
-   |
-LL |         TwoDigits::FIRST..=TwoDigits::LAST => 0,
-   |         ^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/missing_assoc_const_type2.stderr b/tests/ui/consts/missing_assoc_const_type2.stderr
index 1255ca2d102..3279a077464 100644
--- a/tests/ui/consts/missing_assoc_const_type2.stderr
+++ b/tests/ui/consts/missing_assoc_const_type2.stderr
@@ -4,5 +4,11 @@ error: missing type for `const` item
 LL |     const FIRST:  = 10;
    |                 ^ help: provide a type for the associated constant: `u8`
 
+note: erroneous constant encountered
+  --> $DIR/missing_assoc_const_type2.rs:18:5
+   |
+LL |     TwoDigits::FIRST as usize
+   |     ^^^^^^^^^^^^^^^^
+
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr
index 50e920f05f9..f5d767efceb 100644
--- a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr
+++ b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr
@@ -4,12 +4,6 @@ error[E0080]: evaluation of constant value failed
 LL | const _: &'static Data = &Data([0; (1 << 47) - 1]);
    |                                ^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler
 
-note: erroneous constant encountered
-  --> $DIR/promoted_running_out_of_memory_issue-130687.rs:8:26
-   |
-LL | const _: &'static Data = &Data([0; (1 << 47) - 1]);
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/promoted_size_overflow.rs b/tests/ui/consts/promoted_size_overflow.rs
new file mode 100644
index 00000000000..3d606905e78
--- /dev/null
+++ b/tests/ui/consts/promoted_size_overflow.rs
@@ -0,0 +1,7 @@
+//@ only-64bit
+pub struct Data([u8; usize::MAX >> 2]);
+const _: &'static [Data] = &[];
+//~^ERROR: evaluation of constant value failed
+//~| too big for the target architecture
+
+fn main() {}
diff --git a/tests/ui/consts/promoted_size_overflow.stderr b/tests/ui/consts/promoted_size_overflow.stderr
new file mode 100644
index 00000000000..cfb8260bed0
--- /dev/null
+++ b/tests/ui/consts/promoted_size_overflow.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/promoted_size_overflow.rs:3:29
+   |
+LL | const _: &'static [Data] = &[];
+   |                             ^^ values of the type `[u8; 4611686018427387903]` are too big for the target architecture
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.rs b/tests/ui/consts/transmute-size-mismatch-before-typeck.rs
index 44eac5b16cc..ffb143da2d4 100644
--- a/tests/ui/consts/transmute-size-mismatch-before-typeck.rs
+++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.rs
@@ -5,7 +5,7 @@
 
 fn main() {
     match &b""[..] {
-        ZST => {} //~ ERROR: could not evaluate constant pattern
+        ZST => {} // ok, `const` error already emitted
     }
 }
 
diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr
index e0d658db997..6bc7e7203aa 100644
--- a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr
+++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr
@@ -7,12 +7,6 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
    = note: source type: `usize` (word size)
    = note: target type: `&[u8]` (2 * word size)
 
-error: could not evaluate constant pattern
-  --> $DIR/transmute-size-mismatch-before-typeck.rs:8:9
-   |
-LL |         ZST => {}
-   |         ^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0512`.
diff --git a/tests/ui/consts/try-operator.stderr b/tests/ui/consts/try-operator.stderr
index 40d96ed3a10..fc37039d260 100644
--- a/tests/ui/consts/try-operator.stderr
+++ b/tests/ui/consts/try-operator.stderr
@@ -4,44 +4,36 @@ error[E0635]: unknown feature `const_convert`
 LL | #![feature(const_convert)]
    |            ^^^^^^^^^^^^^
 
-error[E0015]: `?` cannot determine the branch of `Result<(), ()>` in constant functions
+error[E0015]: `?` is not allowed on `Result<(), ()>` in constant functions
   --> $DIR/try-operator.rs:10:9
    |
 LL |         Err(())?;
    |         ^^^^^^^^
    |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: `?` cannot convert from residual of `Result<bool, ()>` in constant functions
+error[E0015]: `?` is not allowed on `Result<bool, ()>` in constant functions
   --> $DIR/try-operator.rs:10:9
    |
 LL |         Err(())?;
    |         ^^^^^^^^
    |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/result.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions
+error[E0015]: `?` is not allowed on `Option<()>` in constant functions
   --> $DIR/try-operator.rs:18:9
    |
 LL |         None?;
    |         ^^^^^
    |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/option.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions
+error[E0015]: `?` is not allowed on `Option<()>` in constant functions
   --> $DIR/try-operator.rs:18:9
    |
 LL |         None?;
    |         ^^^^^
    |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/option.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
 error: aborting due to 5 previous errors
diff --git a/tests/ui/consts/uninhabited-const-issue-61744.rs b/tests/ui/consts/uninhabited-const-issue-61744.rs
index 6168268bfed..19ee842c36b 100644
--- a/tests/ui/consts/uninhabited-const-issue-61744.rs
+++ b/tests/ui/consts/uninhabited-const-issue-61744.rs
@@ -5,15 +5,15 @@ pub const unsafe fn fake_type<T>() -> T {
 }
 
 pub const unsafe fn hint_unreachable() -> ! {
-    fake_type()
+    fake_type() //~ inside
 }
 
 trait Const {
-    const CONSTANT: i32 = unsafe { fake_type() };
+    const CONSTANT: i32 = unsafe { fake_type() }; //~ inside
 }
 
 impl<T> Const for T {}
 
 pub fn main() -> () {
-    dbg!(i32::CONSTANT); //~ constant
+    dbg!(i32::CONSTANT);
 }
diff --git a/tests/ui/consts/uninhabited-const-issue-61744.stderr b/tests/ui/consts/uninhabited-const-issue-61744.stderr
index c6dd11ee5db..7575ad730b3 100644
--- a/tests/ui/consts/uninhabited-const-issue-61744.stderr
+++ b/tests/ui/consts/uninhabited-const-issue-61744.stderr
@@ -645,20 +645,6 @@ note: inside `<i32 as Const>::CONSTANT`
 LL |     const CONSTANT: i32 = unsafe { fake_type() };
    |                                    ^^^^^^^^^^^
 
-note: erroneous constant encountered
-  --> $DIR/uninhabited-const-issue-61744.rs:18:10
-   |
-LL |     dbg!(i32::CONSTANT);
-   |          ^^^^^^^^^^^^^
-
-note: erroneous constant encountered
-  --> $DIR/uninhabited-const-issue-61744.rs:18:10
-   |
-LL |     dbg!(i32::CONSTANT);
-   |          ^^^^^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
 error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs
index 07c13239a2c..c98ec1de17e 100644
--- a/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs
+++ b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.rs
@@ -3,8 +3,6 @@
 trait X {
     fn test() -> Self::Assoc<{ async {} }>;
     //~^ ERROR associated type `Assoc` not found for `Self`
-    //~| ERROR associated type `Assoc` not found for `Self`
-
 }
 
 pub fn main() {}
diff --git a/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr
index 864c6556d79..58553728753 100644
--- a/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr
+++ b/tests/ui/coroutine/coroutine-in-orphaned-anon-const.stderr
@@ -4,14 +4,6 @@ error[E0220]: associated type `Assoc` not found for `Self`
 LL |     fn test() -> Self::Assoc<{ async {} }>;
    |                        ^^^^^ associated type `Assoc` not found
 
-error[E0220]: associated type `Assoc` not found for `Self`
-  --> $DIR/coroutine-in-orphaned-anon-const.rs:4:24
-   |
-LL |     fn test() -> Self::Assoc<{ async {} }>;
-   |                        ^^^^^ associated type `Assoc` not found
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/cross-crate/const-cross-crate-extern.rs b/tests/ui/cross-crate/const-cross-crate-extern.rs
index 8d48a6a5206..0ec8753c30f 100644
--- a/tests/ui/cross-crate/const-cross-crate-extern.rs
+++ b/tests/ui/cross-crate/const-cross-crate-extern.rs
@@ -1,6 +1,8 @@
 //@ run-pass
 //@ aux-build:cci_const.rs
+
 #![allow(non_upper_case_globals)]
+#![allow(unpredictable_function_pointer_comparisons)]
 
 extern crate cci_const;
 use cci_const::bar;
diff --git a/tests/ui/deriving/deriving-coerce-pointee-neg.rs b/tests/ui/deriving/deriving-coerce-pointee-neg.rs
index deef35cdf70..da25c854c54 100644
--- a/tests/ui/deriving/deriving-coerce-pointee-neg.rs
+++ b/tests/ui/deriving/deriving-coerce-pointee-neg.rs
@@ -29,7 +29,7 @@ struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
 struct NoGeneric<'a>(&'a u8);
 
 #[derive(CoercePointee)]
-//~^ ERROR: exactly one generic type parameter must be marked as #[pointee] to derive CoercePointee traits
+//~^ ERROR: exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits
 #[repr(transparent)]
 struct AmbiguousPointee<'a, T1: ?Sized, T2: ?Sized> {
     a: (&'a T1, &'a T2),
@@ -38,7 +38,7 @@ struct AmbiguousPointee<'a, T1: ?Sized, T2: ?Sized> {
 #[derive(CoercePointee)]
 #[repr(transparent)]
 struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &'a B));
-//~^ ERROR: only one type parameter can be marked as `#[pointee]` when deriving CoercePointee traits
+//~^ ERROR: only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits
 
 #[derive(CoercePointee)]
 //~^ ERROR: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
@@ -49,7 +49,7 @@ struct NotTransparent<'a, #[pointee] T: ?Sized> {
 #[derive(CoercePointee)]
 #[repr(transparent)]
 struct NoMaybeSized<'a, #[pointee] T> {
-    //~^ ERROR: `derive(CoercePointee)` requires T to be marked `?Sized`
+    //~^ ERROR: `derive(CoercePointee)` requires `T` to be marked `?Sized`
     ptr: &'a T,
 }
 
diff --git a/tests/ui/deriving/deriving-coerce-pointee-neg.stderr b/tests/ui/deriving/deriving-coerce-pointee-neg.stderr
index e590d636d0e..c1e8be49d37 100644
--- a/tests/ui/deriving/deriving-coerce-pointee-neg.stderr
+++ b/tests/ui/deriving/deriving-coerce-pointee-neg.stderr
@@ -30,7 +30,7 @@ LL | #[derive(CoercePointee)]
    |
    = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: exactly one generic type parameter must be marked as #[pointee] to derive CoercePointee traits
+error: exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits
   --> $DIR/deriving-coerce-pointee-neg.rs:31:10
    |
 LL | #[derive(CoercePointee)]
@@ -38,11 +38,11 @@ LL | #[derive(CoercePointee)]
    |
    = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: only one type parameter can be marked as `#[pointee]` when deriving CoercePointee traits
+error: only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits
   --> $DIR/deriving-coerce-pointee-neg.rs:40:39
    |
 LL | struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &'a B));
-   |                                       ^                     ^
+   |                                       ^                     - here another type parameter is marked as `#[pointee]`
 
 error: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
   --> $DIR/deriving-coerce-pointee-neg.rs:43:10
@@ -52,7 +52,7 @@ LL | #[derive(CoercePointee)]
    |
    = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: `derive(CoercePointee)` requires T to be marked `?Sized`
+error: `derive(CoercePointee)` requires `T` to be marked `?Sized`
   --> $DIR/deriving-coerce-pointee-neg.rs:51:36
    |
 LL | struct NoMaybeSized<'a, #[pointee] T> {
diff --git a/tests/ui/drop/lint-if-let-rescope.fixed b/tests/ui/drop/lint-if-let-rescope.fixed
index fec2e3b2ae7..182190aa323 100644
--- a/tests/ui/drop/lint-if-let-rescope.fixed
+++ b/tests/ui/drop/lint-if-let-rescope.fixed
@@ -14,7 +14,7 @@ impl Drop for Droppy {
     }
 }
 impl Droppy {
-    fn get(&self) -> Option<u8> {
+    const fn get(&self) -> Option<u8> {
         None
     }
 }
@@ -62,11 +62,10 @@ fn main() {
         //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
     }
 
-    if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } {
-        //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
-        //~| WARN: this changes meaning in Rust 2024
-        //~| HELP: the value is now dropped here in Edition 2024
-        //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
+    if let () = { if let Some(_value) = Droppy.get() {} } {
+        // This should not lint.
+        // This `if let` sits is a tail expression of a block.
+        // In Edition 2024, the temporaries are dropped before exiting the surrounding block.
     }
 
     #[rustfmt::skip]
@@ -94,4 +93,17 @@ fn main() {
         //~| HELP: the value is now dropped here in Edition 2024
         //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
     }
+
+    // We want to keep the `if let`s below as direct descendents of match arms,
+    // so the formatting is suppressed.
+    #[rustfmt::skip]
+    match droppy().get() {
+        _ => if let Some(_value) = droppy().get() {},
+        // Should not lint
+        // There is implicitly a block surrounding the `if let`.
+        // Given that it is a tail expression, the temporaries are dropped duly before
+        // the execution is exiting the `match`.
+    }
+
+    if let Some(_value) = droppy().get() {}
 }
diff --git a/tests/ui/drop/lint-if-let-rescope.rs b/tests/ui/drop/lint-if-let-rescope.rs
index ee184695b97..e1b38be0a0f 100644
--- a/tests/ui/drop/lint-if-let-rescope.rs
+++ b/tests/ui/drop/lint-if-let-rescope.rs
@@ -14,7 +14,7 @@ impl Drop for Droppy {
     }
 }
 impl Droppy {
-    fn get(&self) -> Option<u8> {
+    const fn get(&self) -> Option<u8> {
         None
     }
 }
@@ -63,10 +63,9 @@ fn main() {
     }
 
     if let () = { if let Some(_value) = Droppy.get() {} } {
-        //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
-        //~| WARN: this changes meaning in Rust 2024
-        //~| HELP: the value is now dropped here in Edition 2024
-        //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
+        // This should not lint.
+        // This `if let` sits is a tail expression of a block.
+        // In Edition 2024, the temporaries are dropped before exiting the surrounding block.
     }
 
     #[rustfmt::skip]
@@ -94,4 +93,17 @@ fn main() {
         //~| HELP: the value is now dropped here in Edition 2024
         //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
     }
+
+    // We want to keep the `if let`s below as direct descendents of match arms,
+    // so the formatting is suppressed.
+    #[rustfmt::skip]
+    match droppy().get() {
+        _ => if let Some(_value) = droppy().get() {},
+        // Should not lint
+        // There is implicitly a block surrounding the `if let`.
+        // Given that it is a tail expression, the temporaries are dropped duly before
+        // the execution is exiting the `match`.
+    }
+
+    if let Some(_value) = droppy().get() {}
 }
diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr
index ef60d141b79..cfb7070c097 100644
--- a/tests/ui/drop/lint-if-let-rescope.stderr
+++ b/tests/ui/drop/lint-if-let-rescope.stderr
@@ -112,27 +112,7 @@ LL |     if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ =
    |                        ~~~~~              +++++++++++++++++             ~~~~         +
 
 error: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/lint-if-let-rescope.rs:65:22
-   |
-LL |     if let () = { if let Some(_value) = Droppy.get() {} } {
-   |                      ^^^^^^^^^^^^^^^^^^^------^^^^^^
-   |                                         |
-   |                                         this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
-   |
-   = warning: this changes meaning in Rust 2024
-   = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
-help: the value is now dropped here in Edition 2024
-  --> $DIR/lint-if-let-rescope.rs:65:55
-   |
-LL |     if let () = { if let Some(_value) = Droppy.get() {} } {
-   |                                                       ^
-help: a `match` with a single arm can preserve the drop order up to Edition 2021
-   |
-LL |     if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } {
-   |                   ~~~~~              +++++++++++++++++    ++++++++
-
-error: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/lint-if-let-rescope.rs:73:12
+  --> $DIR/lint-if-let-rescope.rs:72:12
    |
 LL |     if (if let Some(_value) = droppy().get() { true } else { false }) {
    |            ^^^^^^^^^^^^^^^^^^^--------^^^^^^
@@ -142,7 +122,7 @@ LL |     if (if let Some(_value) = droppy().get() { true } else { false }) {
    = warning: this changes meaning in Rust 2024
    = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
 help: the value is now dropped here in Edition 2024
-  --> $DIR/lint-if-let-rescope.rs:73:53
+  --> $DIR/lint-if-let-rescope.rs:72:53
    |
 LL |     if (if let Some(_value) = droppy().get() { true } else { false }) {
    |                                                     ^
@@ -152,7 +132,7 @@ LL |     if (match droppy().get() { Some(_value) => { true } _ => { false }}) {
    |         ~~~~~                +++++++++++++++++          ~~~~          +
 
 error: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/lint-if-let-rescope.rs:79:21
+  --> $DIR/lint-if-let-rescope.rs:78:21
    |
 LL |     } else if (((if let Some(_value) = droppy().get() { true } else { false }))) {
    |                     ^^^^^^^^^^^^^^^^^^^--------^^^^^^
@@ -162,7 +142,7 @@ LL |     } else if (((if let Some(_value) = droppy().get() { true } else { false
    = warning: this changes meaning in Rust 2024
    = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
 help: the value is now dropped here in Edition 2024
-  --> $DIR/lint-if-let-rescope.rs:79:62
+  --> $DIR/lint-if-let-rescope.rs:78:62
    |
 LL |     } else if (((if let Some(_value) = droppy().get() { true } else { false }))) {
    |                                                              ^
@@ -172,7 +152,7 @@ LL |     } else if (((match droppy().get() { Some(_value) => { true } _ => { fal
    |                  ~~~~~                +++++++++++++++++          ~~~~          +
 
 error: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/lint-if-let-rescope.rs:91:15
+  --> $DIR/lint-if-let-rescope.rs:90:15
    |
 LL |     while (if let Some(_value) = droppy().get() { false } else { true }) {
    |               ^^^^^^^^^^^^^^^^^^^--------^^^^^^
@@ -182,7 +162,7 @@ LL |     while (if let Some(_value) = droppy().get() { false } else { true }) {
    = warning: this changes meaning in Rust 2024
    = note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
 help: the value is now dropped here in Edition 2024
-  --> $DIR/lint-if-let-rescope.rs:91:57
+  --> $DIR/lint-if-let-rescope.rs:90:57
    |
 LL |     while (if let Some(_value) = droppy().get() { false } else { true }) {
    |                                                         ^
@@ -191,5 +171,5 @@ help: a `match` with a single arm can preserve the drop order up to Edition 2021
 LL |     while (match droppy().get() { Some(_value) => { false } _ => { true }}) {
    |            ~~~~~                +++++++++++++++++           ~~~~         +
 
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/tests/ui/enum-discriminant/issue-41394.stderr b/tests/ui/enum-discriminant/issue-41394.stderr
index e81562df04f..9bf4fc79b1b 100644
--- a/tests/ui/enum-discriminant/issue-41394.stderr
+++ b/tests/ui/enum-discriminant/issue-41394.stderr
@@ -6,6 +6,12 @@ LL |     A = "" + 1
    |         |
    |         &str
 
+note: erroneous constant encountered
+  --> $DIR/issue-41394.rs:7:9
+   |
+LL |     A = Foo::A as isize
+   |         ^^^^^^^^^^^^^^^
+
 error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/error-codes/E0622.rs b/tests/ui/error-codes/E0622.rs
index ae7378a707e..08c6d171296 100644
--- a/tests/ui/error-codes/E0622.rs
+++ b/tests/ui/error-codes/E0622.rs
@@ -1,6 +1,6 @@
 #![feature(intrinsics)]
 extern "rust-intrinsic" {
-    pub static breakpoint : unsafe extern "rust-intrinsic" fn();
+    pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn();
     //~^ ERROR intrinsic must be a function [E0622]
 }
-fn main() { unsafe { breakpoint(); } }
+fn main() { unsafe { atomic_singlethreadfence_seqcst(); } }
diff --git a/tests/ui/error-codes/E0622.stderr b/tests/ui/error-codes/E0622.stderr
index c59776b211f..739ec984fc6 100644
--- a/tests/ui/error-codes/E0622.stderr
+++ b/tests/ui/error-codes/E0622.stderr
@@ -1,8 +1,8 @@
 error[E0622]: intrinsic must be a function
   --> $DIR/E0622.rs:3:5
    |
-LL |     pub static breakpoint : unsafe extern "rust-intrinsic" fn();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function
+LL |     pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/explicit-tail-calls/ctfe-id-unlimited.return.stderr b/tests/ui/explicit-tail-calls/ctfe-id-unlimited.return.stderr
index 4a1e50b4111..46769cdea8a 100644
--- a/tests/ui/explicit-tail-calls/ctfe-id-unlimited.return.stderr
+++ b/tests/ui/explicit-tail-calls/ctfe-id-unlimited.return.stderr
@@ -25,12 +25,6 @@ note: inside `ID_ED`
 LL | const ID_ED: u32 = rec_id(ORIGINAL);
    |                    ^^^^^^^^^^^^^^^^
 
-note: erroneous constant encountered
-  --> $DIR/ctfe-id-unlimited.rs:31:40
-   |
-LL | const ASSERT: () = assert!(ORIGINAL == ID_ED);
-   |                                        ^^^^^
-
 error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/extern/extern-compare-with-return-type.rs b/tests/ui/extern/extern-compare-with-return-type.rs
index 316e8b2fc73..7d1027d5e77 100644
--- a/tests/ui/extern/extern-compare-with-return-type.rs
+++ b/tests/ui/extern/extern-compare-with-return-type.rs
@@ -2,6 +2,7 @@
 
 // Tests that we can compare various kinds of extern fn signatures.
 #![allow(non_camel_case_types)]
+#![allow(unpredictable_function_pointer_comparisons)]
 
 // `dbg!()` differentiates these functions to ensure they won't be merged.
 extern "C" fn voidret1() { dbg!() }
diff --git a/tests/ui/extern/extern-take-value.rs b/tests/ui/extern/extern-take-value.rs
index 56ed3328614..f3df82b2610 100644
--- a/tests/ui/extern/extern-take-value.rs
+++ b/tests/ui/extern/extern-take-value.rs
@@ -1,6 +1,8 @@
 //@ run-pass
 //@ aux-build:extern-take-value.rs
 
+#![allow(unpredictable_function_pointer_comparisons)]
+
 extern crate extern_take_value;
 
 pub fn main() {
diff --git a/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs b/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs
new file mode 100644
index 00000000000..db5d7aa06d2
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs
@@ -0,0 +1,7 @@
+//@ edition: 2021
+
+fn test(_: impl async Fn()) {}
+//~^ ERROR `async` trait bounds are unstable
+//~| ERROR use of unstable library feature `async_closure`
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr b/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr
new file mode 100644
index 00000000000..abc7e37c45f
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr
@@ -0,0 +1,24 @@
+error[E0658]: `async` trait bounds are unstable
+  --> $DIR/feature-gate-async-trait-bounds.rs:3:17
+   |
+LL | fn test(_: impl async Fn()) {}
+   |                 ^^^^^
+   |
+   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
+   = help: add `#![feature(async_trait_bounds)]` 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: use the desugared name of the async trait, such as `AsyncFn`
+
+error[E0658]: use of unstable library feature `async_closure`
+  --> $DIR/feature-gate-async-trait-bounds.rs:3:23
+   |
+LL | fn test(_: impl async Fn()) {}
+   |                       ^^^^
+   |
+   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
+   = help: add `#![feature(async_closure)]` 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
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs b/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs
deleted file mode 100644
index 7842d44ac4f..00000000000
--- a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-// This feature doesn't *currently* fire on any specific code; it's just a
-// behavior change. Future changes might.
-#[rustc_error] //~ the
-fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr b/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr
deleted file mode 100644
index a5ab1b0d631..00000000000
--- a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
-  --> $DIR/feature-gate-generic_associated_types_extended.rs:3:1
-   |
-LL | #[rustc_error]
-   | ^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(rustc_attrs)]` 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/function-pointer/function-pointer-comparison-issue-54685.rs b/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs
index 2e1c863e0f4..3ec958f2ebf 100644
--- a/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs
+++ b/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs
@@ -1,6 +1,8 @@
 //@ compile-flags: -C opt-level=3
 //@ run-pass
 
+#![allow(unpredictable_function_pointer_comparisons)]
+
 fn foo(_i: i32) -> i32 {
     1
 }
diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.rs b/tests/ui/generic-associated-types/extended/lending_iterator.rs
index 7cd32413001..8d815f6dc78 100644
--- a/tests/ui/generic-associated-types/extended/lending_iterator.rs
+++ b/tests/ui/generic-associated-types/extended/lending_iterator.rs
@@ -1,9 +1,4 @@
-//@ revisions: base extended
-//@[base] check-fail
-//@[extended] check-pass
-
-#![cfg_attr(extended, feature(generic_associated_types_extended))]
-#![cfg_attr(extended, allow(incomplete_features))]
+//@ known-bug: #133805
 
 pub trait FromLendingIterator<A>: Sized {
     fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
@@ -11,7 +6,6 @@ pub trait FromLendingIterator<A>: Sized {
 
 impl<A> FromLendingIterator<A> for Vec<A> {
     fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self {
-        //[base]~^ impl has stricter
         let mut v = vec![];
         while let Some(item) = iter.next() {
             v.push(item);
@@ -32,7 +26,6 @@ pub trait LendingIterator {
         Self: for<'q> LendingIterator<Item<'q> = A>,
     {
         <B as FromLendingIterator<A>>::from_iter(self)
-        //[base]~^ ERROR: does not live long enough
     }
 }
 
diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator.stderr
index b19280b45c2..84f5ed07bda 100644
--- a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr
+++ b/tests/ui/generic-associated-types/extended/lending_iterator.stderr
@@ -1,5 +1,5 @@
 error[E0276]: impl has stricter requirements than trait
-  --> $DIR/lending_iterator.rs:13:45
+  --> $DIR/lending_iterator.rs:8:45
    |
 LL |     fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
    |     ------------------------------------------------------------------------ definition of `from_iter` from trait
@@ -8,7 +8,7 @@ LL |     fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) ->
    |                                             ^^^^^^^^^^^^ impl has extra requirement `I: 'x`
 
 error: `Self` does not live long enough
-  --> $DIR/lending_iterator.rs:34:9
+  --> $DIR/lending_iterator.rs:28:9
    |
 LL |         <B as FromLendingIterator<A>>::from_iter(self)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/generic-associated-types/extended/lending_iterator_2.rs b/tests/ui/generic-associated-types/extended/lending_iterator_2.rs
index f4b0dae0a91..0545d4d12bb 100644
--- a/tests/ui/generic-associated-types/extended/lending_iterator_2.rs
+++ b/tests/ui/generic-associated-types/extended/lending_iterator_2.rs
@@ -1,9 +1,4 @@
-//@ revisions: base extended
-//@[base] check-fail
-//@[extended] check-pass
-
-#![cfg_attr(extended, feature(generic_associated_types_extended))]
-#![cfg_attr(extended, allow(incomplete_features))]
+//@ known-bug: #133805
 
 pub trait FromLendingIterator<A>: Sized {
     fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
@@ -11,7 +6,6 @@ pub trait FromLendingIterator<A>: Sized {
 
 impl<A> FromLendingIterator<A> for Vec<A> {
     fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self {
-        //[base]~^ impl has stricter
         let mut v = vec![];
         while let Some(item) = iter.next() {
             v.push(item);
diff --git a/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator_2.stderr
index 717d867057e..47c32a28aea 100644
--- a/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr
+++ b/tests/ui/generic-associated-types/extended/lending_iterator_2.stderr
@@ -1,5 +1,5 @@
 error[E0276]: impl has stricter requirements than trait
-  --> $DIR/lending_iterator_2.rs:13:45
+  --> $DIR/lending_iterator_2.rs:8:45
    |
 LL |     fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
    |     ------------------------------------------------------------------------ definition of `from_iter` from trait
diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.rs b/tests/ui/generic-associated-types/gat-in-trait-path.rs
index 7eb0aabb333..cd759a73cf2 100644
--- a/tests/ui/generic-associated-types/gat-in-trait-path.rs
+++ b/tests/ui/generic-associated-types/gat-in-trait-path.rs
@@ -1,10 +1,6 @@
-//@ revisions: base extended
-//@[base] check-fail
-//@[extended] check-pass
+//@ check-fail
 
 #![feature(associated_type_defaults)]
-#![cfg_attr(extended, feature(generic_associated_types_extended))]
-#![cfg_attr(extended, allow(incomplete_features))]
 
 trait Foo {
     type A<'a> where Self: 'a;
@@ -24,12 +20,12 @@ impl<T> Foo for Fooer<T> {
 }
 
 fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
-//[base]~^ the trait `Foo` cannot be made into an object
+//~^ the trait `Foo` cannot be made into an object
 
 
 fn main() {
   let foo = Fooer(5);
   f(Box::new(foo));
-  //[base]~^ the trait `Foo` cannot be made into an object
-  //[base]~| the trait `Foo` cannot be made into an object
+  //~^ the trait `Foo` cannot be made into an object
+  //~| the trait `Foo` cannot be made into an object
 }
diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.stderr
new file mode 100644
index 00000000000..b2176fa6de3
--- /dev/null
+++ b/tests/ui/generic-associated-types/gat-in-trait-path.stderr
@@ -0,0 +1,58 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/gat-in-trait-path.rs:22:17
+   |
+LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/gat-in-trait-path.rs:6:10
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     type A<'a> where Self: 'a;
+   |          ^ ...because it contains the generic associated type `A`
+   = help: consider moving `A` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
+             Fooy
+             Fooer<T>
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/gat-in-trait-path.rs:28:5
+   |
+LL |   f(Box::new(foo));
+   |     ^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/gat-in-trait-path.rs:6:10
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     type A<'a> where Self: 'a;
+   |          ^ ...because it contains the generic associated type `A`
+   = help: consider moving `A` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
+             Fooy
+             Fooer<T>
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/gat-in-trait-path.rs:28:5
+   |
+LL |   f(Box::new(foo));
+   |     ^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/gat-in-trait-path.rs:6:10
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     type A<'a> where Self: 'a;
+   |          ^ ...because it contains the generic associated type `A`
+   = help: consider moving `A` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
+             Fooy
+             Fooer<T>
+   = note: required for the cast from `Box<Fooer<{integer}>>` to `Box<(dyn Foo<A<'a> = &'a ()> + 'static)>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/generic-associated-types/issue-67510-pass.rs b/tests/ui/generic-associated-types/issue-67510-pass.rs
index 1596f401bbc..a48d9c37cd4 100644
--- a/tests/ui/generic-associated-types/issue-67510-pass.rs
+++ b/tests/ui/generic-associated-types/issue-67510-pass.rs
@@ -1,15 +1,10 @@
-//@ revisions: base extended
-//@[base] check-fail
-//@[extended] check-pass
-
-#![cfg_attr(extended, feature(generic_associated_types_extended))]
-#![cfg_attr(extended, allow(incomplete_features))]
+//@ check-fail
 
 trait X {
     type Y<'a>;
 }
 
 fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
-//[base]~^ ERROR the trait `X` cannot be made into an object
+//~^ ERROR the trait `X` cannot be made into an object
 
 fn main() {}
diff --git a/tests/ui/generic-associated-types/issue-67510-pass.stderr b/tests/ui/generic-associated-types/issue-67510-pass.stderr
new file mode 100644
index 00000000000..5560cb0f64d
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-67510-pass.stderr
@@ -0,0 +1,18 @@
+error[E0038]: the trait `X` cannot be made into an object
+  --> $DIR/issue-67510-pass.rs:7:23
+   |
+LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
+   |                       ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-67510-pass.rs:4:10
+   |
+LL | trait X {
+   |       - this trait cannot be made into an object...
+LL |     type Y<'a>;
+   |          ^ ...because it contains the generic associated type `Y`
+   = help: consider moving `Y` to another trait
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/generic-associated-types/issue-76535.rs b/tests/ui/generic-associated-types/issue-76535.rs
index cf26b65c85f..9e18c82c7f1 100644
--- a/tests/ui/generic-associated-types/issue-76535.rs
+++ b/tests/ui/generic-associated-types/issue-76535.rs
@@ -1,8 +1,3 @@
-//@ revisions: base extended
-
-#![cfg_attr(extended, feature(generic_associated_types_extended))]
-#![cfg_attr(extended, allow(incomplete_features))]
-
 pub trait SubTrait {}
 
 pub trait SuperTrait {
@@ -38,6 +33,6 @@ impl SuperTrait for SuperStruct {
 fn main() {
     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
       //~^ ERROR missing generics for associated type
-      //[base]~^^ ERROR the trait
-      //[base]~| ERROR the trait
+      //~^^ ERROR the trait
+      //~| ERROR the trait
 }
diff --git a/tests/ui/generic-associated-types/issue-76535.stderr b/tests/ui/generic-associated-types/issue-76535.stderr
new file mode 100644
index 00000000000..613ded6f1ef
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-76535.stderr
@@ -0,0 +1,55 @@
+error[E0107]: missing generics for associated type `SuperTrait::SubType`
+  --> $DIR/issue-76535.rs:34:33
+   |
+LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
+   |                                 ^^^^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-76535.rs:4:10
+   |
+LL |     type SubType<'a>: SubTrait where Self: 'a;
+   |          ^^^^^^^ --
+help: add missing lifetime argument
+   |
+LL |     let sub: Box<dyn SuperTrait<SubType<'a> = SubStruct>> = Box::new(SuperStruct::new(0));
+   |                                        ++++
+
+error[E0038]: the trait `SuperTrait` cannot be made into an object
+  --> $DIR/issue-76535.rs:34:14
+   |
+LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-76535.rs:4:10
+   |
+LL | pub trait SuperTrait {
+   |           ---------- this trait cannot be made into an object...
+LL |     type SubType<'a>: SubTrait where Self: 'a;
+   |          ^^^^^^^ ...because it contains the generic associated type `SubType`
+   = help: consider moving `SubType` to another trait
+   = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead
+   = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
+
+error[E0038]: the trait `SuperTrait` cannot be made into an object
+  --> $DIR/issue-76535.rs:34:57
+   |
+LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-76535.rs:4:10
+   |
+LL | pub trait SuperTrait {
+   |           ---------- this trait cannot be made into an object...
+LL |     type SubType<'a>: SubTrait where Self: 'a;
+   |          ^^^^^^^ ...because it contains the generic associated type `SubType`
+   = help: consider moving `SubType` to another trait
+   = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead
+   = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
+   = note: required for the cast from `Box<SuperStruct>` to `Box<dyn SuperTrait<SubType<'_> = SubStruct<'_>>>`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/generic-associated-types/issue-78671.rs b/tests/ui/generic-associated-types/issue-78671.rs
index ce4c040644a..0871def1731 100644
--- a/tests/ui/generic-associated-types/issue-78671.rs
+++ b/tests/ui/generic-associated-types/issue-78671.rs
@@ -1,15 +1,10 @@
-//@ revisions: base extended
-
-#![cfg_attr(extended, feature(generic_associated_types_extended))]
-#![cfg_attr(extended, allow(incomplete_features))]
-
 trait CollectionFamily {
     type Member<T>;
 }
 fn floatify() {
     Box::new(Family) as &dyn CollectionFamily<Member=usize>
     //~^ ERROR: missing generics for associated type
-    //[base]~^^ ERROR: the trait `CollectionFamily` cannot be made into an object
+    //~| ERROR: the trait `CollectionFamily` cannot be made into an object
 }
 
 struct Family;
diff --git a/tests/ui/generic-associated-types/issue-78671.stderr b/tests/ui/generic-associated-types/issue-78671.stderr
new file mode 100644
index 00000000000..fbd76c73895
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-78671.stderr
@@ -0,0 +1,35 @@
+error[E0107]: missing generics for associated type `CollectionFamily::Member`
+  --> $DIR/issue-78671.rs:5:47
+   |
+LL |     Box::new(Family) as &dyn CollectionFamily<Member=usize>
+   |                                               ^^^^^^ expected 1 generic argument
+   |
+note: associated type defined here, with 1 generic parameter: `T`
+  --> $DIR/issue-78671.rs:2:10
+   |
+LL |     type Member<T>;
+   |          ^^^^^^ -
+help: add missing generic argument
+   |
+LL |     Box::new(Family) as &dyn CollectionFamily<Member<T>=usize>
+   |                                                     +++
+
+error[E0038]: the trait `CollectionFamily` cannot be made into an object
+  --> $DIR/issue-78671.rs:5:25
+   |
+LL |     Box::new(Family) as &dyn CollectionFamily<Member=usize>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-78671.rs:2:10
+   |
+LL | trait CollectionFamily {
+   |       ---------------- this trait cannot be made into an object...
+LL |     type Member<T>;
+   |          ^^^^^^ ...because it contains the generic associated type `Member`
+   = help: consider moving `Member` to another trait
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/generic-associated-types/issue-79422.rs b/tests/ui/generic-associated-types/issue-79422.rs
index bf61dcaee3a..fba7a86990e 100644
--- a/tests/ui/generic-associated-types/issue-79422.rs
+++ b/tests/ui/generic-associated-types/issue-79422.rs
@@ -1,8 +1,3 @@
-//@ revisions: base extended
-
-#![cfg_attr(extended, feature(generic_associated_types_extended))]
-#![cfg_attr(extended, allow(incomplete_features))]
-
 trait RefCont<'a, T> {
     fn t(&'a self) -> &'a T;
 }
@@ -42,9 +37,8 @@ impl<K, V: Default> MapLike<K, V> for Source {
 
 fn main() {
     let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
-    //[base]~^ ERROR the trait
-    //[extended]~^^ type mismatch
+    //~^ ERROR the trait
         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
       //~^ ERROR missing generics for associated type
-      //[base]~^^ ERROR the trait
+      //~| ERROR the trait
 }
diff --git a/tests/ui/generic-associated-types/issue-79422.stderr b/tests/ui/generic-associated-types/issue-79422.stderr
new file mode 100644
index 00000000000..26567e5e927
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-79422.stderr
@@ -0,0 +1,57 @@
+error[E0107]: missing generics for associated type `MapLike::VRefCont`
+  --> $DIR/issue-79422.rs:41:36
+   |
+LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
+   |                                    ^^^^^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-79422.rs:18:10
+   |
+LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
+   |          ^^^^^^^^ --
+help: add missing lifetime argument
+   |
+LL |         as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>;
+   |                                            ++++
+
+error[E0038]: the trait `MapLike` cannot be made into an object
+  --> $DIR/issue-79422.rs:41:12
+   |
+LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-79422.rs:18:10
+   |
+LL | trait MapLike<K, V> {
+   |       ------- this trait cannot be made into an object...
+LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
+   |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
+   = help: consider moving `VRefCont` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead:
+             std::collections::BTreeMap<K, V>
+             Source
+
+error[E0038]: the trait `MapLike` cannot be made into an object
+  --> $DIR/issue-79422.rs:39:13
+   |
+LL |     let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-79422.rs:18:10
+   |
+LL | trait MapLike<K, V> {
+   |       ------- this trait cannot be made into an object...
+LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
+   |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
+   = help: consider moving `VRefCont` to another trait
+   = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead:
+             std::collections::BTreeMap<K, V>
+             Source
+   = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont<'_> = (dyn RefCont<'_, u8> + 'static)>>`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/generic-associated-types/trait-objects.rs b/tests/ui/generic-associated-types/trait-objects.rs
index 743a3df0acc..bad9289ee5e 100644
--- a/tests/ui/generic-associated-types/trait-objects.rs
+++ b/tests/ui/generic-associated-types/trait-objects.rs
@@ -1,8 +1,3 @@
-//@ revisions: base extended
-
-#![cfg_attr(extended, feature(generic_associated_types_extended))]
-#![cfg_attr(extended, allow(incomplete_features))]
-
 trait StreamingIterator {
     type Item<'a> where Self: 'a;
     fn size_hint(&self) -> (usize, Option<usize>);
@@ -11,11 +6,10 @@ trait StreamingIterator {
 }
 
 fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
-    //[base]~^ the trait `StreamingIterator` cannot be made into an object
+    //~^ the trait `StreamingIterator` cannot be made into an object
     x.size_hint().0
-    //[extended]~^ borrowed data escapes
-    //[base]~^^ the trait `StreamingIterator` cannot be made into an object
-    //[base]~| the trait `StreamingIterator` cannot be made into an object
+    //~^ the trait `StreamingIterator` cannot be made into an object
+    //~| the trait `StreamingIterator` cannot be made into an object
 }
 
 fn main() {}
diff --git a/tests/ui/generic-associated-types/trait-objects.stderr b/tests/ui/generic-associated-types/trait-objects.stderr
new file mode 100644
index 00000000000..3e74776f999
--- /dev/null
+++ b/tests/ui/generic-associated-types/trait-objects.stderr
@@ -0,0 +1,48 @@
+error[E0038]: the trait `StreamingIterator` cannot be made into an object
+  --> $DIR/trait-objects.rs:8:21
+   |
+LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/trait-objects.rs:2:10
+   |
+LL | trait StreamingIterator {
+   |       ----------------- this trait cannot be made into an object...
+LL |     type Item<'a> where Self: 'a;
+   |          ^^^^ ...because it contains the generic associated type `Item`
+   = help: consider moving `Item` to another trait
+
+error[E0038]: the trait `StreamingIterator` cannot be made into an object
+  --> $DIR/trait-objects.rs:10:7
+   |
+LL |     x.size_hint().0
+   |       ^^^^^^^^^ `StreamingIterator` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/trait-objects.rs:2:10
+   |
+LL | trait StreamingIterator {
+   |       ----------------- this trait cannot be made into an object...
+LL |     type Item<'a> where Self: 'a;
+   |          ^^^^ ...because it contains the generic associated type `Item`
+   = help: consider moving `Item` to another trait
+
+error[E0038]: the trait `StreamingIterator` cannot be made into an object
+  --> $DIR/trait-objects.rs:10:5
+   |
+LL |     x.size_hint().0
+   |     ^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
+   |
+note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/trait-objects.rs:2:10
+   |
+LL | trait StreamingIterator {
+   |       ----------------- this trait cannot be made into an object...
+LL |     type Item<'a> where Self: 'a;
+   |          ^^^^ ...because it contains the generic associated type `Item`
+   = help: consider moving `Item` to another trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/higher-ranked/structually-relate-aliases.rs b/tests/ui/higher-ranked/structually-relate-aliases.rs
index 73c2cd23d86..1ed3767643a 100644
--- a/tests/ui/higher-ranked/structually-relate-aliases.rs
+++ b/tests/ui/higher-ranked/structually-relate-aliases.rs
@@ -12,6 +12,5 @@ impl<T> Overlap<T> for T {}
 
 impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
 //~^ ERROR the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
-//~| ERROR the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
 
 fn main() {}
diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr
index e9d91e45e21..cf3e4cc85b9 100644
--- a/tests/ui/higher-ranked/structually-relate-aliases.stderr
+++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr
@@ -10,17 +10,6 @@ help: consider restricting type parameter `T`
 LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
    |       ++++++++++++++++++++
 
-error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
-  --> $DIR/structually-relate-aliases.rs:13:17
-   |
-LL | impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T`
-   |
-help: consider restricting type parameter `T`
-   |
-LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
-   |       ++++++++++++++++++++
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr
index 72646b7bc76..9e04e90a98a 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr
@@ -1,5 +1,5 @@
 error[E0284]: type annotations needed: cannot satisfy `Foo == _`
-  --> $DIR/norm-before-method-resolution-opaque-type.rs:16:19
+  --> $DIR/norm-before-method-resolution-opaque-type.rs:15:19
    |
 LL | fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
    |                   ^ cannot satisfy `Foo == _`
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr
index dbd0d5dc733..479f5984355 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr
@@ -1,5 +1,5 @@
 error: item does not constrain `Foo::{opaque#0}`, but has it in its signature
-  --> $DIR/norm-before-method-resolution-opaque-type.rs:16:4
+  --> $DIR/norm-before-method-resolution-opaque-type.rs:15:4
    |
 LL | fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
    |    ^^^^^^^^^^^
@@ -11,16 +11,8 @@ note: this opaque type is in the signature
 LL | type Foo = impl Sized;
    |            ^^^^^^^^^^
 
-error: unconstrained opaque type
-  --> $DIR/norm-before-method-resolution-opaque-type.rs:13:12
-   |
-LL | type Foo = impl Sized;
-   |            ^^^^^^^^^^
-   |
-   = note: `Foo` must be used in combination with a concrete type within the same module
-
 error[E0507]: cannot move out of `*x` which is behind a shared reference
-  --> $DIR/norm-before-method-resolution-opaque-type.rs:23:13
+  --> $DIR/norm-before-method-resolution-opaque-type.rs:22:13
    |
 LL |     let x = *x;
    |             ^^ move occurs because `*x` has type `<X as Trait<'_>>::Out<Foo>`, which does not implement the `Copy` trait
@@ -31,6 +23,6 @@ LL -     let x = *x;
 LL +     let x = x;
    |
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs
index cf752f814c9..ffbfc622bb0 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs
@@ -11,7 +11,6 @@ impl<'a, T> Trait<'a> for T {
 }
 
 type Foo = impl Sized;
-//[old]~^ ERROR: unconstrained opaque type
 
 fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
 //[old]~^ ERROR: item does not constrain
diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr
index 79581066a3a..1cfc2a6d944 100644
--- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr
+++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr
@@ -8,10 +8,10 @@ LL | #![feature(lazy_type_alias)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0277]: the trait bound `usize: Foo` is not satisfied
-  --> $DIR/alias-bounds-when-not-wf.rs:16:13
+  --> $DIR/alias-bounds-when-not-wf.rs:16:15
    |
 LL | fn hello(_: W<A<usize>>) {}
-   |             ^^^^^^^^^^^ the trait `Foo` is not implemented for `usize`
+   |               ^^^^^^^^ the trait `Foo` is not implemented for `usize`
    |
 help: this trait has no implementations, consider adding one
   --> $DIR/alias-bounds-when-not-wf.rs:6:1
diff --git a/tests/ui/impl-trait/issues/issue-86800.rs b/tests/ui/impl-trait/issues/issue-86800.rs
index 5a6959ad7e6..ff1d273ae48 100644
--- a/tests/ui/impl-trait/issues/issue-86800.rs
+++ b/tests/ui/impl-trait/issues/issue-86800.rs
@@ -23,7 +23,6 @@ struct Context {
 type TransactionResult<O> = Result<O, ()>;
 
 type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
-//~^ ERROR unconstrained opaque type
 
 fn execute_transaction_fut<'f, F, O>(
     //~^ ERROR: item does not constrain
diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr
index 095f648143c..fd9b8e7ac99 100644
--- a/tests/ui/impl-trait/issues/issue-86800.stderr
+++ b/tests/ui/impl-trait/issues/issue-86800.stderr
@@ -1,5 +1,5 @@
 error: item does not constrain `TransactionFuture::{opaque#0}`, but has it in its signature
-  --> $DIR/issue-86800.rs:28:4
+  --> $DIR/issue-86800.rs:27:4
    |
 LL | fn execute_transaction_fut<'f, F, O>(
    |    ^^^^^^^^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@ LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResu
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item does not constrain `TransactionFuture::{opaque#0}`, but has it in its signature
-  --> $DIR/issue-86800.rs:40:14
+  --> $DIR/issue-86800.rs:39:14
    |
 LL |     async fn do_transaction<O>(
    |              ^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@ LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResu
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item does not constrain `TransactionFuture::{opaque#0}`, but has it in its signature
-  --> $DIR/issue-86800.rs:44:5
+  --> $DIR/issue-86800.rs:43:5
    |
 LL | /     {
 LL | |
@@ -43,16 +43,8 @@ note: this opaque type is in the signature
 LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: unconstrained opaque type
-  --> $DIR/issue-86800.rs:25:34
-   |
-LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `TransactionFuture` must be used in combination with a concrete type within the same module
-
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/issue-86800.rs:35:5
+  --> $DIR/issue-86800.rs:34:5
    |
 LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                        --- this generic parameter must be used with a generic lifetime parameter
@@ -61,7 +53,7 @@ LL |     f
    |     ^
 
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/issue-86800.rs:44:5
+  --> $DIR/issue-86800.rs:43:5
    |
 LL |   type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                          --- this generic parameter must be used with a generic lifetime parameter
@@ -75,6 +67,6 @@ LL | |         f(&mut transaction).await
 LL | |     }
    | |_____^
 
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs
index 46121308fa0..cac5ae177d2 100644
--- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs
+++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs
@@ -7,7 +7,7 @@ fn polarity() -> impl Sized + ?use<> {}
 fn asyncness() -> impl Sized + async use<> {}
 //~^ ERROR expected identifier, found keyword `use`
 //~| ERROR cannot find trait `r#use` in this scope
-//~| ERROR async closures are unstable
+//~| ERROR `async` trait bounds are unstable
 
 fn constness() -> impl Sized + const use<> {}
 //~^ ERROR expected identifier, found keyword `use`
diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
index 16e7470debf..d4b5b47b41b 100644
--- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
+++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
@@ -46,16 +46,16 @@ error[E0405]: cannot find trait `r#use` in this scope
 LL | fn binder() -> impl Sized + for<'a> use<> {}
    |                                     ^^^ not found in this scope
 
-error[E0658]: async closures are unstable
+error[E0658]: `async` trait bounds are unstable
   --> $DIR/bound-modifiers.rs:7:32
    |
 LL | fn asyncness() -> impl Sized + async use<> {}
    |                                ^^^^^
    |
    = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = help: add `#![feature(async_trait_bounds)]` 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: to use an async block, remove the `||`: `async {`
+   = help: use the desugared name of the async trait, such as `AsyncFn`
 
 error[E0658]: const trait impls are experimental
   --> $DIR/bound-modifiers.rs:12:32
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
index dc9424c3ca7..3f41c5984b4 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
@@ -2,7 +2,6 @@
 
 mod a {
     type Foo = impl PartialEq<(Foo, i32)>;
-    //~^ ERROR: unconstrained opaque type
 
     struct Bar;
 
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
index 6485aa20710..b127bf41800 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -1,5 +1,5 @@
 error[E0053]: method `eq` has an incompatible type for trait
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:30
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:9:30
    |
 LL |     type Foo = impl PartialEq<(Foo, i32)>;
    |                -------------------------- the found opaque type
@@ -15,7 +15,7 @@ LL |         fn eq(&self, _other: &(a::Bar, i32)) -> bool {
    |                              ~~~~~~~~~~~~~~
 
 error: item does not constrain `a::Foo::{opaque#0}`, but has it in its signature
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:12
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:9:12
    |
 LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
    |            ^^
@@ -27,16 +27,8 @@ note: this opaque type is in the signature
 LL |     type Foo = impl PartialEq<(Foo, i32)>;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: unconstrained opaque type
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16
-   |
-LL |     type Foo = impl PartialEq<(Foo, i32)>;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `Foo` must be used in combination with a concrete type within the same module
-
 error[E0053]: method `eq` has an incompatible type for trait
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:25:30
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:30
    |
 LL |     type Foo = impl PartialEq<(Foo, i32)>;
    |                -------------------------- the expected opaque type
@@ -47,7 +39,7 @@ LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
    = note: expected signature `fn(&b::Bar, &(b::Foo, _)) -> _`
               found signature `fn(&b::Bar, &(b::Bar, _)) -> _`
 note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:25:12
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:12
    |
 LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
    |            ^^
@@ -57,13 +49,13 @@ LL |         fn eq(&self, _other: &(b::Foo, i32)) -> bool {
    |                              ~~~~~~~~~~~~~~
 
 error: unconstrained opaque type
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:19:16
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16
    |
 LL |     type Foo = impl PartialEq<(Foo, i32)>;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `Foo` must be used in combination with a concrete type within the same module
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr
index b70676ece0e..7d02a0606fc 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr
@@ -11,14 +11,6 @@ note: this opaque type is in the signature
 LL | type A = impl Foo;
    |          ^^^^^^^^
 
-error: unconstrained opaque type
-  --> $DIR/two_tait_defining_each_other2.rs:6:10
-   |
-LL | type A = impl Foo;
-   |          ^^^^^^^^
-   |
-   = note: `A` must be used in combination with a concrete type within the same module
-
 error: opaque type's hidden type cannot be another opaque type from the same scope
   --> $DIR/two_tait_defining_each_other2.rs:14:5
    |
@@ -36,5 +28,5 @@ note: opaque type being used as hidden type
 LL | type A = impl Foo;
    |          ^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.rs b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
index 3311c556568..1681b019418 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.rs
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
@@ -3,7 +3,7 @@
 //@[next] compile-flags: -Znext-solver
 #![feature(type_alias_impl_trait)]
 
-type A = impl Foo; //[current]~ ERROR unconstrained opaque type
+type A = impl Foo;
 type B = impl Foo;
 
 trait Foo {}
diff --git a/tests/ui/inline-const/const-match-pat-generic.rs b/tests/ui/inline-const/const-match-pat-generic.rs
index 9d76fc2ad65..889c015e9ac 100644
--- a/tests/ui/inline-const/const-match-pat-generic.rs
+++ b/tests/ui/inline-const/const-match-pat-generic.rs
@@ -5,7 +5,7 @@
 fn foo<const V: usize>() {
     match 0 {
         const { V } => {},
-        //~^ ERROR constant pattern depends on a generic parameter
+        //~^ ERROR constant pattern cannot depend on generic parameters
         _ => {},
     }
 }
@@ -17,7 +17,7 @@ const fn f(x: usize) -> usize {
 fn bar<const V: usize>() {
     match 0 {
         const { f(V) } => {},
-        //~^ ERROR constant pattern depends on a generic parameter
+        //~^ ERROR constant pattern cannot depend on generic parameters
         _ => {},
     }
 }
diff --git a/tests/ui/inline-const/const-match-pat-generic.stderr b/tests/ui/inline-const/const-match-pat-generic.stderr
index 26f72b34eca..7d9e1d9e407 100644
--- a/tests/ui/inline-const/const-match-pat-generic.stderr
+++ b/tests/ui/inline-const/const-match-pat-generic.stderr
@@ -1,14 +1,14 @@
-error[E0158]: constant pattern depends on a generic parameter
+error[E0158]: constant pattern cannot depend on generic parameters
   --> $DIR/const-match-pat-generic.rs:7:9
    |
 LL |         const { V } => {},
-   |         ^^^^^^^^^^^
+   |         ^^^^^^^^^^^ `const` depends on a generic parameter
 
-error[E0158]: constant pattern depends on a generic parameter
+error[E0158]: constant pattern cannot depend on generic parameters
   --> $DIR/const-match-pat-generic.rs:19:9
    |
 LL |         const { f(V) } => {},
-   |         ^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^ `const` depends on a generic parameter
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/inline-const/pat-match-fndef.stderr b/tests/ui/inline-const/pat-match-fndef.stderr
index b189ec51ade..220437a0491 100644
--- a/tests/ui/inline-const/pat-match-fndef.stderr
+++ b/tests/ui/inline-const/pat-match-fndef.stderr
@@ -1,8 +1,8 @@
-error: `fn() {uwu}` cannot be used in patterns
+error: fn item `fn() {uwu}` cannot be used in patterns
   --> $DIR/pat-match-fndef.rs:8:9
    |
 LL |         const { uwu } => {}
-   |         ^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^ fn item can't be used in patterns
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-50582.rs b/tests/ui/issues/issue-50582.rs
index 2d5c9358752..1358e0bde4c 100644
--- a/tests/ui/issues/issue-50582.rs
+++ b/tests/ui/issues/issue-50582.rs
@@ -1,5 +1,4 @@
 fn main() {
     Vec::<[(); 1 + for x in 0..1 {}]>::new();
     //~^ ERROR cannot add
-    //~| ERROR `for` is not allowed in a `const`
 }
diff --git a/tests/ui/issues/issue-50582.stderr b/tests/ui/issues/issue-50582.stderr
index af7a36f62fb..168f5894fb0 100644
--- a/tests/ui/issues/issue-50582.stderr
+++ b/tests/ui/issues/issue-50582.stderr
@@ -1,13 +1,3 @@
-error[E0658]: `for` is not allowed in a `const`
-  --> $DIR/issue-50582.rs:2:20
-   |
-LL |     Vec::<[(); 1 + for x in 0..1 {}]>::new();
-   |                    ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
-   = help: add `#![feature(const_for)]` 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[E0277]: cannot add `()` to `{integer}`
   --> $DIR/issue-50582.rs:2:18
    |
@@ -26,7 +16,6 @@ LL |     Vec::<[(); 1 + for x in 0..1 {}]>::new();
              `&f64` implements `Add`
            and 56 others
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0277, E0658.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/issues/issue-50585.rs b/tests/ui/issues/issue-50585.rs
index a2f11c98d5a..ca2ece8d53b 100644
--- a/tests/ui/issues/issue-50585.rs
+++ b/tests/ui/issues/issue-50585.rs
@@ -1,5 +1,4 @@
 fn main() {
     |y: Vec<[(); for x in 0..2 {}]>| {};
     //~^ ERROR mismatched types
-    //~| ERROR `for` is not allowed in a `const`
 }
diff --git a/tests/ui/issues/issue-50585.stderr b/tests/ui/issues/issue-50585.stderr
index e7f13e63475..7e83ea35fbb 100644
--- a/tests/ui/issues/issue-50585.stderr
+++ b/tests/ui/issues/issue-50585.stderr
@@ -1,13 +1,3 @@
-error[E0658]: `for` is not allowed in a `const`
-  --> $DIR/issue-50585.rs:2:18
-   |
-LL |     |y: Vec<[(); for x in 0..2 {}]>| {};
-   |                  ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
-   = help: add `#![feature(const_for)]` 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[E0308]: mismatched types
   --> $DIR/issue-50585.rs:2:18
    |
@@ -20,7 +10,6 @@ help: consider returning a value here
 LL |     |y: Vec<[(); for x in 0..2 {} /* `usize` value */]>| {};
    |                                   +++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0308, E0658.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/issues/issue-54696.rs b/tests/ui/issues/issue-54696.rs
index 75b1824f0b3..63ffbe42bcc 100644
--- a/tests/ui/issues/issue-54696.rs
+++ b/tests/ui/issues/issue-54696.rs
@@ -1,5 +1,7 @@
 //@ run-pass
 
+#![allow(unpredictable_function_pointer_comparisons)]
+
 fn main() {
     // We shouldn't promote this
     let _ = &(main as fn() == main as fn());
diff --git a/tests/ui/layout/base-layout-is-sized-ice-123078.stderr b/tests/ui/layout/base-layout-is-sized-ice-123078.stderr
index 455bd2cbf8b..ee7f5162552 100644
--- a/tests/ui/layout/base-layout-is-sized-ice-123078.stderr
+++ b/tests/ui/layout/base-layout-is-sized-ice-123078.stderr
@@ -25,6 +25,12 @@ LL | const C: S = unsafe { std::mem::transmute(()) };
    = note: source type: `()` (0 bits)
    = note: target type: `S` (size can vary because of [u8])
 
+note: erroneous constant encountered
+  --> $DIR/base-layout-is-sized-ice-123078.rs:13:5
+   |
+LL |     C;
+   |     ^
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0512.
diff --git a/tests/ui/limits/issue-55878.stderr b/tests/ui/limits/issue-55878.stderr
index 0a5f17be804..51c4837f458 100644
--- a/tests/ui/limits/issue-55878.stderr
+++ b/tests/ui/limits/issue-55878.stderr
@@ -11,23 +11,6 @@ note: inside `main`
 LL |     println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-note: erroneous constant encountered
-  --> $DIR/issue-55878.rs:7:26
-   |
-LL |     println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: this note 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)
-
-note: erroneous constant encountered
-  --> $DIR/issue-55878.rs:7:26
-   |
-LL |     println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-   = note: this note 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: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/lint/fn-ptr-comparisons-weird.rs b/tests/ui/lint/fn-ptr-comparisons-weird.rs
new file mode 100644
index 00000000000..171fbfb8727
--- /dev/null
+++ b/tests/ui/lint/fn-ptr-comparisons-weird.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+
+fn main() {
+    let f: fn() = main;
+    let g: fn() = main;
+
+    let _ = f > g;
+    //~^ WARN function pointer comparisons
+    let _ = f >= g;
+    //~^ WARN function pointer comparisons
+    let _ = f <= g;
+    //~^ WARN function pointer comparisons
+    let _ = f < g;
+    //~^ WARN function pointer comparisons
+}
diff --git a/tests/ui/lint/fn-ptr-comparisons-weird.stderr b/tests/ui/lint/fn-ptr-comparisons-weird.stderr
new file mode 100644
index 00000000000..f2371663922
--- /dev/null
+++ b/tests/ui/lint/fn-ptr-comparisons-weird.stderr
@@ -0,0 +1,43 @@
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons-weird.rs:7:13
+   |
+LL |     let _ = f > g;
+   |             ^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+   = note: `#[warn(unpredictable_function_pointer_comparisons)]` on by default
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons-weird.rs:9:13
+   |
+LL |     let _ = f >= g;
+   |             ^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons-weird.rs:11:13
+   |
+LL |     let _ = f <= g;
+   |             ^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons-weird.rs:13:13
+   |
+LL |     let _ = f < g;
+   |             ^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+
+warning: 4 warnings emitted
+
diff --git a/tests/ui/lint/fn-ptr-comparisons.fixed b/tests/ui/lint/fn-ptr-comparisons.fixed
new file mode 100644
index 00000000000..22f16177a04
--- /dev/null
+++ b/tests/ui/lint/fn-ptr-comparisons.fixed
@@ -0,0 +1,58 @@
+//@ check-pass
+//@ run-rustfix
+
+extern "C" {
+    fn test();
+}
+
+fn a() {}
+
+extern "C" fn c() {}
+
+extern "C" fn args(_a: i32) -> i32 { 0 }
+
+#[derive(PartialEq, Eq)]
+struct A {
+    f: fn(),
+}
+
+fn main() {
+    let f: fn() = a;
+    let g: fn() = f;
+
+    let a1 = A { f };
+    let a2 = A { f };
+
+    let _ = std::ptr::fn_addr_eq(f, a as fn());
+    //~^ WARN function pointer comparisons
+    let _ = !std::ptr::fn_addr_eq(f, a as fn());
+    //~^ WARN function pointer comparisons
+    let _ = std::ptr::fn_addr_eq(f, g);
+    //~^ WARN function pointer comparisons
+    let _ = std::ptr::fn_addr_eq(f, f);
+    //~^ WARN function pointer comparisons
+    let _ = std::ptr::fn_addr_eq(g, g);
+    //~^ WARN function pointer comparisons
+    let _ = std::ptr::fn_addr_eq(g, g);
+    //~^ WARN function pointer comparisons
+    let _ = std::ptr::fn_addr_eq(g, g);
+    //~^ WARN function pointer comparisons
+    let _ = std::ptr::fn_addr_eq(a as fn(), g);
+    //~^ WARN function pointer comparisons
+
+    let cfn: extern "C" fn() = c;
+    let _ = std::ptr::fn_addr_eq(cfn, c as extern "C" fn());
+    //~^ WARN function pointer comparisons
+
+    let argsfn: extern "C" fn(i32) -> i32 = args;
+    let _ = std::ptr::fn_addr_eq(argsfn, args as extern "C" fn(i32) -> i32);
+    //~^ WARN function pointer comparisons
+
+    let t: unsafe extern "C" fn() = test;
+    let _ = std::ptr::fn_addr_eq(t, test as unsafe extern "C" fn());
+    //~^ WARN function pointer comparisons
+
+    let _ = a1 == a2; // should not warn
+    let _ = std::ptr::fn_addr_eq(a1.f, a2.f);
+    //~^ WARN function pointer comparisons
+}
diff --git a/tests/ui/lint/fn-ptr-comparisons.rs b/tests/ui/lint/fn-ptr-comparisons.rs
new file mode 100644
index 00000000000..90a8ab5c926
--- /dev/null
+++ b/tests/ui/lint/fn-ptr-comparisons.rs
@@ -0,0 +1,58 @@
+//@ check-pass
+//@ run-rustfix
+
+extern "C" {
+    fn test();
+}
+
+fn a() {}
+
+extern "C" fn c() {}
+
+extern "C" fn args(_a: i32) -> i32 { 0 }
+
+#[derive(PartialEq, Eq)]
+struct A {
+    f: fn(),
+}
+
+fn main() {
+    let f: fn() = a;
+    let g: fn() = f;
+
+    let a1 = A { f };
+    let a2 = A { f };
+
+    let _ = f == a;
+    //~^ WARN function pointer comparisons
+    let _ = f != a;
+    //~^ WARN function pointer comparisons
+    let _ = f == g;
+    //~^ WARN function pointer comparisons
+    let _ = f == f;
+    //~^ WARN function pointer comparisons
+    let _ = g == g;
+    //~^ WARN function pointer comparisons
+    let _ = g == g;
+    //~^ WARN function pointer comparisons
+    let _ = &g == &g;
+    //~^ WARN function pointer comparisons
+    let _ = a as fn() == g;
+    //~^ WARN function pointer comparisons
+
+    let cfn: extern "C" fn() = c;
+    let _ = cfn == c;
+    //~^ WARN function pointer comparisons
+
+    let argsfn: extern "C" fn(i32) -> i32 = args;
+    let _ = argsfn == args;
+    //~^ WARN function pointer comparisons
+
+    let t: unsafe extern "C" fn() = test;
+    let _ = t == test;
+    //~^ WARN function pointer comparisons
+
+    let _ = a1 == a2; // should not warn
+    let _ = a1.f == a2.f;
+    //~^ WARN function pointer comparisons
+}
diff --git a/tests/ui/lint/fn-ptr-comparisons.stderr b/tests/ui/lint/fn-ptr-comparisons.stderr
new file mode 100644
index 00000000000..eaba23a461a
--- /dev/null
+++ b/tests/ui/lint/fn-ptr-comparisons.stderr
@@ -0,0 +1,171 @@
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons.rs:26:13
+   |
+LL |     let _ = f == a;
+   |             ^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+   = note: `#[warn(unpredictable_function_pointer_comparisons)]` on by default
+help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
+   |
+LL |     let _ = std::ptr::fn_addr_eq(f, a as fn());
+   |             +++++++++++++++++++++ ~   ++++++++
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons.rs:28:13
+   |
+LL |     let _ = f != a;
+   |             ^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
+   |
+LL |     let _ = !std::ptr::fn_addr_eq(f, a as fn());
+   |             ++++++++++++++++++++++ ~   ++++++++
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons.rs:30:13
+   |
+LL |     let _ = f == g;
+   |             ^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
+   |
+LL |     let _ = std::ptr::fn_addr_eq(f, g);
+   |             +++++++++++++++++++++ ~  +
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons.rs:32:13
+   |
+LL |     let _ = f == f;
+   |             ^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
+   |
+LL |     let _ = std::ptr::fn_addr_eq(f, f);
+   |             +++++++++++++++++++++ ~  +
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons.rs:34:13
+   |
+LL |     let _ = g == g;
+   |             ^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
+   |
+LL |     let _ = std::ptr::fn_addr_eq(g, g);
+   |             +++++++++++++++++++++ ~  +
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons.rs:36:13
+   |
+LL |     let _ = g == g;
+   |             ^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
+   |
+LL |     let _ = std::ptr::fn_addr_eq(g, g);
+   |             +++++++++++++++++++++ ~  +
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons.rs:38:13
+   |
+LL |     let _ = &g == &g;
+   |             ^^^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
+   |
+LL |     let _ = std::ptr::fn_addr_eq(g, g);
+   |             ~~~~~~~~~~~~~~~~~~~~~ ~  +
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons.rs:40:13
+   |
+LL |     let _ = a as fn() == g;
+   |             ^^^^^^^^^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
+   |
+LL |     let _ = std::ptr::fn_addr_eq(a as fn(), g);
+   |             +++++++++++++++++++++         ~  +
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons.rs:44:13
+   |
+LL |     let _ = cfn == c;
+   |             ^^^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
+   |
+LL |     let _ = std::ptr::fn_addr_eq(cfn, c as extern "C" fn());
+   |             +++++++++++++++++++++   ~   +++++++++++++++++++
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons.rs:48:13
+   |
+LL |     let _ = argsfn == args;
+   |             ^^^^^^^^^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
+   |
+LL |     let _ = std::ptr::fn_addr_eq(argsfn, args as extern "C" fn(i32) -> i32);
+   |             +++++++++++++++++++++      ~      +++++++++++++++++++++++++++++
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons.rs:52:13
+   |
+LL |     let _ = t == test;
+   |             ^^^^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
+   |
+LL |     let _ = std::ptr::fn_addr_eq(t, test as unsafe extern "C" fn());
+   |             +++++++++++++++++++++ ~      ++++++++++++++++++++++++++
+
+warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
+  --> $DIR/fn-ptr-comparisons.rs:56:13
+   |
+LL |     let _ = a1.f == a2.f;
+   |             ^^^^^^^^^^^^
+   |
+   = note: the address of the same function can vary between different codegen units
+   = note: furthermore, different functions could have the same address after being merged together
+   = note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
+help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
+   |
+LL |     let _ = std::ptr::fn_addr_eq(a1.f, a2.f);
+   |             +++++++++++++++++++++    ~     +
+
+warning: 12 warnings emitted
+
diff --git a/tests/ui/lint/forbid-group-group-2.stderr b/tests/ui/lint/forbid-group-group-2.stderr
index 80e2f566eb8..b075a521cc9 100644
--- a/tests/ui/lint/forbid-group-group-2.stderr
+++ b/tests/ui/lint/forbid-group-group-2.stderr
@@ -43,3 +43,57 @@ LL | #[allow(nonstandard_style)]
 
 error: aborting due to 3 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: allow(nonstandard_style) incompatible with previous forbid
+  --> $DIR/forbid-group-group-2.rs:7:9
+   |
+LL | #![forbid(warnings)]
+   |           -------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/forbid-group-group-2.rs:5:9
+   |
+LL | #![deny(forbidden_lint_groups)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(nonstandard_style) incompatible with previous forbid
+  --> $DIR/forbid-group-group-2.rs:7:9
+   |
+LL | #![forbid(warnings)]
+   |           -------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/forbid-group-group-2.rs:5:9
+   |
+LL | #![deny(forbidden_lint_groups)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(nonstandard_style) incompatible with previous forbid
+  --> $DIR/forbid-group-group-2.rs:7:9
+   |
+LL | #![forbid(warnings)]
+   |           -------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/forbid-group-group-2.rs:5:9
+   |
+LL | #![deny(forbidden_lint_groups)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/lint/forbid-group-member.stderr b/tests/ui/lint/forbid-group-member.stderr
index 8794591bd31..2e0147693f3 100644
--- a/tests/ui/lint/forbid-group-member.stderr
+++ b/tests/ui/lint/forbid-group-member.stderr
@@ -13,3 +13,17 @@ LL | #[allow(unused_variables)]
 
 warning: 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: allow(unused_variables) incompatible with previous forbid
+  --> $DIR/forbid-group-member.rs:8:9
+   |
+LL | #![forbid(unused)]
+   |           ------ `forbid` level set here
+LL |
+LL | #[allow(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+   = note: `#[warn(forbidden_lint_groups)]` on by default
+
diff --git a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr
index 407eaf1c60a..77c8d1eab58 100644
--- a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr
+++ b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr
@@ -17,3 +17,399 @@ LL | #![forbid(forbidden_lint_groups)]
 
 error: aborting due to 1 previous error
 
+Future incompatibility report: Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: warn(unused) incompatible with previous forbid
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
+   |
+LL |     #![forbid(unused)]
+   |               ------ `forbid` level set here
+LL |     #![deny(unused)]
+LL |     #![warn(unused)]
+   |             ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/lint/outer-forbid.stderr b/tests/ui/lint/outer-forbid.stderr
index a47877980a0..64a1077462a 100644
--- a/tests/ui/lint/outer-forbid.stderr
+++ b/tests/ui/lint/outer-forbid.stderr
@@ -39,3 +39,417 @@ LL | #[allow(nonstandard_style)]
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
+Future incompatibility report: Future breakage diagnostic:
+error: allow(unused_variables) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:20:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: allow(unused) incompatible with previous forbid
+  --> $DIR/outer-forbid.rs:25:9
+   |
+LL | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+...
+LL | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
+   |
+   = 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
+note: the lint level is defined here
+  --> $DIR/outer-forbid.rs:18:11
+   |
+LL | #![forbid(forbidden_lint_groups)]
+   |           ^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/match/issue-70972-dyn-trait.stderr b/tests/ui/match/issue-70972-dyn-trait.stderr
index b0af50f8599..cec9c8539f4 100644
--- a/tests/ui/match/issue-70972-dyn-trait.stderr
+++ b/tests/ui/match/issue-70972-dyn-trait.stderr
@@ -1,8 +1,11 @@
-error: `dyn Send` cannot be used in patterns
+error: trait object `dyn Send` cannot be used in patterns
   --> $DIR/issue-70972-dyn-trait.rs:6:9
    |
+LL | const F: &'static dyn Send = &7u32;
+   | -------------------------- constant defined here
+...
 LL |         F => panic!(),
-   |         ^
+   |         ^ trait object can't be used in patterns
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/match/issue-72896-non-partial-eq-const.rs b/tests/ui/match/issue-72896-non-partial-eq-const.rs
index f15eae83896..e4fc1ac057d 100644
--- a/tests/ui/match/issue-72896-non-partial-eq-const.rs
+++ b/tests/ui/match/issue-72896-non-partial-eq-const.rs
@@ -16,7 +16,7 @@ const CONST_SET: EnumSet<Enum8> = EnumSet { __enumset_underlying: 3 };
 
 fn main() {
     match CONST_SET {
-        CONST_SET => { /* ok */ } //~ERROR: must implement `PartialEq`
+        CONST_SET => { /* ok */ } //~ ERROR constant of non-structural type `EnumSet<Enum8>` in a pattern
         _ => panic!("match fell through?"),
     }
 }
diff --git a/tests/ui/match/issue-72896-non-partial-eq-const.stderr b/tests/ui/match/issue-72896-non-partial-eq-const.stderr
index 4155586c160..1f82d3e822a 100644
--- a/tests/ui/match/issue-72896-non-partial-eq-const.stderr
+++ b/tests/ui/match/issue-72896-non-partial-eq-const.stderr
@@ -1,8 +1,16 @@
-error: to use a constant of type `EnumSet<Enum8>` in a pattern, the type must implement `PartialEq`
+error: constant of non-structural type `EnumSet<Enum8>` in a pattern
   --> $DIR/issue-72896-non-partial-eq-const.rs:19:9
    |
+LL | enum Enum8 { }
+   | ---------- must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL | const CONST_SET: EnumSet<Enum8> = EnumSet { __enumset_underlying: 3 };
+   | ------------------------------- constant defined here
+...
 LL |         CONST_SET => { /* ok */ }
-   |         ^^^^^^^^^
+   |         ^^^^^^^^^ constant of non-structural type
+   |
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs b/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs
index 44b7fae351c..45d519739eb 100644
--- a/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs
+++ b/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs
@@ -1,6 +1,8 @@
 //@ check-pass
 //@ compile-flags: -Zvalidate-mir
 
+#![allow(unpredictable_function_pointer_comparisons)]
+
 fn foo(_a: &str) {}
 
 fn main() {
diff --git a/tests/ui/never_type/issue-52443.rs b/tests/ui/never_type/issue-52443.rs
index dcda2b9536a..b112842030e 100644
--- a/tests/ui/never_type/issue-52443.rs
+++ b/tests/ui/never_type/issue-52443.rs
@@ -7,7 +7,6 @@ fn main() {
     //~^ WARN denote infinite loops with
 
     [(); { for _ in 0usize.. {}; 0}];
-    //~^ ERROR `for` is not allowed in a `const`
-    //~| ERROR cannot convert
-    //~| ERROR cannot call
+    //~^ ERROR cannot use `for`
+    //~| ERROR cannot use `for`
 }
diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr
index 2207ceb5033..1c5a0d65142 100644
--- a/tests/ui/never_type/issue-52443.stderr
+++ b/tests/ui/never_type/issue-52443.stderr
@@ -6,16 +6,6 @@ LL |     [(); {while true {break}; 0}];
    |
    = note: `#[warn(while_true)]` on by default
 
-error[E0658]: `for` is not allowed in a `const`
-  --> $DIR/issue-52443.rs:9:12
-   |
-LL |     [(); { for _ in 0usize.. {}; 0}];
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
-   = help: add `#![feature(const_for)]` 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[E0308]: mismatched types
   --> $DIR/issue-52443.rs:2:10
    |
@@ -41,25 +31,24 @@ help: give the `break` a value of the expected type
 LL |     [(); loop { break 42 }];
    |                       ++
 
-error[E0015]: cannot convert `RangeFrom<usize>` into an iterator in constants
+error[E0015]: cannot use `for` loop on `RangeFrom<usize>` in constants
   --> $DIR/issue-52443.rs:9:21
    |
 LL |     [(); { for _ in 0usize.. {}; 0}];
    |                     ^^^^^^^^
    |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: cannot call non-const fn `<RangeFrom<usize> as Iterator>::next` in constants
+error[E0015]: cannot use `for` loop on `RangeFrom<usize>` in constants
   --> $DIR/issue-52443.rs:9:21
    |
 LL |     [(); { for _ in 0usize.. {}; 0}];
    |                     ^^^^^^^^
    |
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 5 previous errors; 1 warning emitted
+error: aborting due to 4 previous errors; 1 warning emitted
 
-Some errors have detailed explanations: E0015, E0308, E0658.
+Some errors have detailed explanations: E0015, E0308.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/nll/closure-requirements/thread_scope_correct_implied_bound.rs b/tests/ui/nll/closure-requirements/thread_scope_correct_implied_bound.rs
new file mode 100644
index 00000000000..e2b3b051ea8
--- /dev/null
+++ b/tests/ui/nll/closure-requirements/thread_scope_correct_implied_bound.rs
@@ -0,0 +1,23 @@
+// This example broke while refactoring the way closure
+// requirements are handled. The setup here matches
+// `thread::scope`.
+
+//@ check-pass
+
+struct Outlives<'hr, 'scope: 'hr>(*mut (&'scope (), &'hr ()));
+impl<'hr, 'scope> Outlives<'hr, 'scope> {
+    fn outlives_hr<T: 'hr>(self) {}
+}
+
+fn takes_closure_implied_bound<'scope>(f: impl for<'hr> FnOnce(Outlives<'hr, 'scope>)) {}
+
+fn requires_external_outlives_hr<T>() {
+    // implied bounds:
+    // - `T: 'scope` as `'scope` is local to this function
+    // - `'scope: 'hr` as it's an implied bound of `Outlives`
+    //
+    // need to prove `T: 'hr` :>
+    takes_closure_implied_bound(|proof| proof.outlives_hr::<T>());
+}
+
+fn main() {}
diff --git a/tests/ui/nll/closure-requirements/thread_scope_incorrect_implied_bound.rs b/tests/ui/nll/closure-requirements/thread_scope_incorrect_implied_bound.rs
new file mode 100644
index 00000000000..cfc8980410a
--- /dev/null
+++ b/tests/ui/nll/closure-requirements/thread_scope_incorrect_implied_bound.rs
@@ -0,0 +1,21 @@
+// This example incorrectly compiled while refactoring the way
+// closure requirements are handled.
+
+struct Outlives<'hr: 'scope, 'scope>(*mut (&'scope (), &'hr ()));
+impl<'hr, 'scope> Outlives<'hr, 'scope> {
+    fn outlives_hr<T: 'hr>(self) {}
+}
+
+fn takes_closure_implied_bound<'scope>(f: impl for<'hr> FnOnce(Outlives<'hr, 'scope>)) {}
+
+fn requires_external_outlives_hr<T>() {
+    // implied bounds:
+    // - `T: 'scope` as `'scope` is local to this function
+    // - `'hr: 'scope` as it's an implied bound of `Outlives`
+    //
+    // need to prove `T: 'hr` :<
+    takes_closure_implied_bound(|proof| proof.outlives_hr::<T>());
+    //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/nll/closure-requirements/thread_scope_incorrect_implied_bound.stderr b/tests/ui/nll/closure-requirements/thread_scope_incorrect_implied_bound.stderr
new file mode 100644
index 00000000000..e22673c249f
--- /dev/null
+++ b/tests/ui/nll/closure-requirements/thread_scope_incorrect_implied_bound.stderr
@@ -0,0 +1,17 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/thread_scope_incorrect_implied_bound.rs:17:47
+   |
+LL |     takes_closure_implied_bound(|proof| proof.outlives_hr::<T>());
+   |                                               ^^^^^^^^^^^
+   |                                               |
+   |                                               the parameter type `T` must be valid for the static lifetime...
+   |                                               ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | fn requires_external_outlives_hr<T: 'static>() {
+   |                                   +++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/nll/ty-outlives/projection-implied-bounds.rs b/tests/ui/nll/ty-outlives/projection-implied-bounds.rs
index 7d983adfe88..c6572d60bb0 100644
--- a/tests/ui/nll/ty-outlives/projection-implied-bounds.rs
+++ b/tests/ui/nll/ty-outlives/projection-implied-bounds.rs
@@ -1,8 +1,6 @@
 // Test that we can deduce when projections like `T::Item` outlive the
 // function body. Test that this does not imply that `T: 'a` holds.
 
-//@ compile-flags:-Zverbose-internals
-
 use std::cell::Cell;
 
 fn twice<F, T>(mut value: T, mut f: F)
diff --git a/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr b/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr
index 2aab03ee7b7..5d5b890151d 100644
--- a/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr
+++ b/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr
@@ -1,5 +1,5 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/projection-implied-bounds.rs:30:36
+  --> $DIR/projection-implied-bounds.rs:28:36
    |
 LL |     twice(value, |value_ref, item| invoke2(value_ref, item));
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/parser/bad-recover-kw-after-impl.rs b/tests/ui/parser/bad-recover-kw-after-impl.rs
index 15c0b377c8a..964d32c55bc 100644
--- a/tests/ui/parser/bad-recover-kw-after-impl.rs
+++ b/tests/ui/parser/bad-recover-kw-after-impl.rs
@@ -12,6 +12,6 @@ macro_rules! impl_primitive {
 
 impl_primitive!(impl async);
 //~^ ERROR expected identifier, found `<eof>`
-//~| ERROR async closures are unstable
+//~| ERROR `async` trait bounds are unstable
 
 fn main() {}
diff --git a/tests/ui/parser/bad-recover-kw-after-impl.stderr b/tests/ui/parser/bad-recover-kw-after-impl.stderr
index f617cf65498..7a8979db165 100644
--- a/tests/ui/parser/bad-recover-kw-after-impl.stderr
+++ b/tests/ui/parser/bad-recover-kw-after-impl.stderr
@@ -7,16 +7,16 @@ LL |     ($ty:ty) => {
 LL | impl_primitive!(impl async);
    |                      ^^^^^ expected identifier
 
-error[E0658]: async closures are unstable
+error[E0658]: `async` trait bounds are unstable
   --> $DIR/bad-recover-kw-after-impl.rs:13:22
    |
 LL | impl_primitive!(impl async);
    |                      ^^^^^
    |
    = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = help: add `#![feature(async_trait_bounds)]` 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: to use an async block, remove the `||`: `async {`
+   = help: use the desugared name of the async trait, such as `AsyncFn`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/typed-self-param.rs b/tests/ui/parser/typed-self-param.rs
new file mode 100644
index 00000000000..e3d85ab891b
--- /dev/null
+++ b/tests/ui/parser/typed-self-param.rs
@@ -0,0 +1,14 @@
+struct S;
+
+impl S {
+    fn a(&self: Self) {}
+    //~^ ERROR type not allowed for shorthand `self` parameter
+    fn b(&mut self: Self) {}
+    //~^ ERROR type not allowed for shorthand `self` parameter
+    fn c<'c>(&'c mut self: Self) {}
+    //~^ ERROR type not allowed for shorthand `self` parameter
+    fn d<'d>(&'d self: Self) {}
+    //~^ ERROR type not allowed for shorthand `self` parameter
+}
+
+fn main() {}
diff --git a/tests/ui/parser/typed-self-param.stderr b/tests/ui/parser/typed-self-param.stderr
new file mode 100644
index 00000000000..c1ecd3b7fef
--- /dev/null
+++ b/tests/ui/parser/typed-self-param.stderr
@@ -0,0 +1,50 @@
+error: type not allowed for shorthand `self` parameter
+  --> $DIR/typed-self-param.rs:4:17
+   |
+LL |     fn a(&self: Self) {}
+   |                 ^^^^
+   |
+help: move the modifiers on `self` to the type
+   |
+LL -     fn a(&self: Self) {}
+LL +     fn a(self: &Self) {}
+   |
+
+error: type not allowed for shorthand `self` parameter
+  --> $DIR/typed-self-param.rs:6:21
+   |
+LL |     fn b(&mut self: Self) {}
+   |                     ^^^^
+   |
+help: move the modifiers on `self` to the type
+   |
+LL -     fn b(&mut self: Self) {}
+LL +     fn b(self: &mut Self) {}
+   |
+
+error: type not allowed for shorthand `self` parameter
+  --> $DIR/typed-self-param.rs:8:28
+   |
+LL |     fn c<'c>(&'c mut self: Self) {}
+   |                            ^^^^
+   |
+help: move the modifiers on `self` to the type
+   |
+LL -     fn c<'c>(&'c mut self: Self) {}
+LL +     fn c<'c>(self: &'c mut Self) {}
+   |
+
+error: type not allowed for shorthand `self` parameter
+  --> $DIR/typed-self-param.rs:10:24
+   |
+LL |     fn d<'d>(&'d self: Self) {}
+   |                        ^^^^
+   |
+help: move the modifiers on `self` to the type
+   |
+LL -     fn d<'d>(&'d self: Self) {}
+LL +     fn d<'d>(self: &'d Self) {}
+   |
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/pattern/issue-115599.rs b/tests/ui/pattern/issue-115599.rs
index 1521d728d95..47fe6b87da9 100644
--- a/tests/ui/pattern/issue-115599.rs
+++ b/tests/ui/pattern/issue-115599.rs
@@ -3,5 +3,5 @@ const CONST_STRING: String = String::new();
 fn main() {
     let empty_str = String::from("");
     if let CONST_STRING = empty_str {}
-    //~^ ERROR to use a constant of type `Vec<u8>` in a pattern, `Vec<u8>` must be annotated with `#[derive(PartialEq)]`
+    //~^ ERROR constant of non-structural type `Vec<u8>` in a pattern
 }
diff --git a/tests/ui/pattern/issue-115599.stderr b/tests/ui/pattern/issue-115599.stderr
index adab4e4d241..69d10728ccd 100644
--- a/tests/ui/pattern/issue-115599.stderr
+++ b/tests/ui/pattern/issue-115599.stderr
@@ -1,10 +1,15 @@
-error: to use a constant of type `Vec<u8>` in a pattern, `Vec<u8>` must be annotated with `#[derive(PartialEq)]`
+error: constant of non-structural type `Vec<u8>` in a pattern
   --> $DIR/issue-115599.rs:5:12
    |
+LL | const CONST_STRING: String = String::new();
+   | -------------------------- constant defined here
+...
 LL |     if let CONST_STRING = empty_str {}
-   |            ^^^^^^^^^^^^
+   |            ^^^^^^^^^^^^ constant of non-structural type
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+   |
+   = note: `Vec<u8>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/pattern/issue-72565.stderr b/tests/ui/pattern/issue-72565.stderr
index b503a17fe84..e2927ada0f7 100644
--- a/tests/ui/pattern/issue-72565.stderr
+++ b/tests/ui/pattern/issue-72565.stderr
@@ -1,8 +1,11 @@
-error: `dyn PartialEq<u32>` cannot be used in patterns
+error: trait object `dyn PartialEq<u32>` cannot be used in patterns
   --> $DIR/issue-72565.rs:6:9
    |
+LL | const F: &'static dyn PartialEq<u32> = &7u32;
+   | ------------------------------------ constant defined here
+...
 LL |         F => panic!(),
-   |         ^
+   |         ^ trait object can't be used in patterns
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/pattern/non-constant-in-const-path.stderr b/tests/ui/pattern/non-constant-in-const-path.stderr
index 53c3974f780..2ba4963e6dc 100644
--- a/tests/ui/pattern/non-constant-in-const-path.stderr
+++ b/tests/ui/pattern/non-constant-in-const-path.stderr
@@ -2,25 +2,31 @@ error[E0080]: runtime values cannot be referenced in patterns
   --> $DIR/non-constant-in-const-path.rs:8:15
    |
 LL |     let 0u8..=x = 0;
-   |               ^
+   |               ^ references a runtime value
 
 error[E0158]: statics cannot be referenced in patterns
   --> $DIR/non-constant-in-const-path.rs:10:15
    |
+LL | static FOO: u8 = 10;
+   | -------------- `static` defined here
+...
 LL |     let 0u8..=FOO = 0;
-   |               ^^^
+   |               ^^^ can't be used in patterns
 
 error[E0080]: runtime values cannot be referenced in patterns
   --> $DIR/non-constant-in-const-path.rs:13:15
    |
 LL |         0 ..= x => {}
-   |               ^
+   |               ^ references a runtime value
 
 error[E0158]: statics cannot be referenced in patterns
   --> $DIR/non-constant-in-const-path.rs:15:15
    |
+LL | static FOO: u8 = 10;
+   | -------------- `static` defined here
+...
 LL |         0 ..= FOO => {}
-   |               ^^^
+   |               ^^^ can't be used in patterns
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr
index 9075cf40dda..3588751bf66 100644
--- a/tests/ui/pattern/non-structural-match-types.stderr
+++ b/tests/ui/pattern/non-structural-match-types.stderr
@@ -1,14 +1,14 @@
-error: `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used in patterns
+error: closure `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used in patterns
   --> $DIR/non-structural-match-types.rs:9:9
    |
 LL |         const { || {} } => {}
-   |         ^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^ closure can't be used in patterns
 
-error: `{async block@$DIR/non-structural-match-types.rs:12:17: 12:22}` cannot be used in patterns
+error: `async` block `{async block@$DIR/non-structural-match-types.rs:12:17: 12:22}` cannot be used in patterns
   --> $DIR/non-structural-match-types.rs:12:9
    |
 LL |         const { async {} } => {}
-   |         ^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^ `async` block can't be used in patterns
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs
index f34093ef149..f09dcf8498f 100644
--- a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs
+++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs
@@ -12,7 +12,7 @@ const CONSTANT: &&MyType = &&MyType;
 
 fn main() {
     if let CONSTANT = &&MyType {
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        //~^ ERROR constant of non-structural type `MyType` in a pattern
         println!("did match!");
     }
 }
diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr
index 0b4d9972758..f9da0430f2e 100644
--- a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr
+++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr
@@ -1,11 +1,20 @@
-error: to use a constant of type `MyType` in a pattern, `MyType` must be annotated with `#[derive(PartialEq)]`
+error: constant of non-structural type `MyType` in a pattern
   --> $DIR/const-partial_eq-fallback-ice.rs:14:12
    |
+LL | struct MyType;
+   | ------------- `MyType` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL | const CONSTANT: &&MyType = &&MyType;
+   | ------------------------ constant defined here
+...
 LL |     if let CONSTANT = &&MyType {
-   |            ^^^^^^^^
+   |            ^^^^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/const-partial_eq-fallback-ice.rs:5:1
+   |
+LL | impl PartialEq<usize> for MyType {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr
index 32d385eecb4..d52451d9438 100644
--- a/tests/ui/pattern/usefulness/consts-opaque.stderr
+++ b/tests/ui/pattern/usefulness/consts-opaque.stderr
@@ -1,50 +1,90 @@
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/consts-opaque.rs:96:9
    |
+LL |     const QUUX: Quux = quux;
+   |     ---------------- constant defined here
+...
 LL |         QUUX => {}
-   |         ^^^^
+   |         ^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/consts-opaque.rs:97:9
    |
+LL |     const QUUX: Quux = quux;
+   |     ---------------- constant defined here
+...
 LL |         QUUX => {}
-   |         ^^^^
+   |         ^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/consts-opaque.rs:106:9
    |
+LL |     const WRAPQUUX: Wrap<Quux> = Wrap(quux);
+   |     -------------------------- constant defined here
+...
 LL |         WRAPQUUX => {}
-   |         ^^^^^^^^
+   |         ^^^^^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/consts-opaque.rs:107:9
    |
+LL |     const WRAPQUUX: Wrap<Quux> = Wrap(quux);
+   |     -------------------------- constant defined here
+...
 LL |         WRAPQUUX => {}
-   |         ^^^^^^^^
+   |         ^^^^^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/consts-opaque.rs:113:9
    |
+LL |     const WRAPQUUX: Wrap<Quux> = Wrap(quux);
+   |     -------------------------- constant defined here
+...
 LL |         WRAPQUUX => {}
-   |         ^^^^^^^^
+   |         ^^^^^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/consts-opaque.rs:121:9
    |
+LL |     const WRAPQUUX: Wrap<Quux> = Wrap(quux);
+   |     -------------------------- constant defined here
+...
 LL |         WRAPQUUX => {}
-   |         ^^^^^^^^
+   |         ^^^^^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/consts-opaque.rs:132:9
    |
+LL |     const WHOKNOWSQUUX: WhoKnows<Quux> = WhoKnows::Yay(quux);
+   |     ---------------------------------- constant defined here
+...
 LL |         WHOKNOWSQUUX => {}
-   |         ^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/consts-opaque.rs:134:9
    |
+LL |     const WHOKNOWSQUUX: WhoKnows<Quux> = WhoKnows::Yay(quux);
+   |     ---------------------------------- constant defined here
+...
 LL |         WHOKNOWSQUUX => {}
-   |         ^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:48:9
diff --git a/tests/ui/print-request/macos-target.rs b/tests/ui/print-request/macos-target.rs
index 197edd02474..af74babbed4 100644
--- a/tests/ui/print-request/macos-target.rs
+++ b/tests/ui/print-request/macos-target.rs
@@ -1,5 +1,6 @@
 //@ only-apple
 //@ compile-flags: --print deployment-target
+//@ normalize-stdout-test: "\w*_DEPLOYMENT_TARGET" -> "$$OS_DEPLOYMENT_TARGET"
 //@ normalize-stdout-test: "\d+\." -> "$$CURRENT_MAJOR_VERSION."
 //@ normalize-stdout-test: "\d+" -> "$$CURRENT_MINOR_VERSION"
 //@ check-pass
diff --git a/tests/ui/print-request/macos-target.stdout b/tests/ui/print-request/macos-target.stdout
index f55ef568ed6..34ade570969 100644
--- a/tests/ui/print-request/macos-target.stdout
+++ b/tests/ui/print-request/macos-target.stdout
@@ -1 +1 @@
-deployment_target=$CURRENT_MAJOR_VERSION.$CURRENT_MINOR_VERSION
+$OS_DEPLOYMENT_TARGET=$CURRENT_MAJOR_VERSION.$CURRENT_MINOR_VERSION
diff --git a/tests/ui/process/env-funky-keys.rs b/tests/ui/process/env-funky-keys.rs
index 314ccaea015..a4a71c94020 100644
--- a/tests/ui/process/env-funky-keys.rs
+++ b/tests/ui/process/env-funky-keys.rs
@@ -1,4 +1,5 @@
 //@ run-pass
+//@ edition: 2021
 // Ignore this test on Android, because it segfaults there.
 
 //@ ignore-android
@@ -32,10 +33,9 @@ fn main() {
                                        .unwrap()
                                        .as_os_str()
                                        .as_bytes()).unwrap();
-    let new_env_var = CString::new("FOOBAR").unwrap();
     let filename: *const c_char = current_exe.as_ptr();
     let argv: &[*const c_char] = &[filename, filename, ptr::null()];
-    let envp: &[*const c_char] = &[new_env_var.as_ptr(), ptr::null()];
+    let envp: &[*const c_char] = &[c"FOOBAR".as_ptr(), ptr::null()];
     unsafe {
         execve(filename, &argv[0], &envp[0]);
     }
diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr
index fbb9ede8aa1..c7e9df10d41 100644
--- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr
+++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr
@@ -29,6 +29,20 @@ LL |     const _: u32 = T::C;
    |
    = note: a `const` is a separate item from the item that contains it
 
+note: erroneous constant encountered
+  --> $DIR/generic-params-from-outer-item-in-const-item.rs:22:9
+   |
+LL |         I
+   |         ^
+
+note: erroneous constant encountered
+  --> $DIR/generic-params-from-outer-item-in-const-item.rs:22:9
+   |
+LL |         I
+   |         ^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0401`.
diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr
index 60aa94038c3..64c436d3ceb 100644
--- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr
+++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr
@@ -35,6 +35,20 @@ LL |     const _: u32 = T::C;
    |
    = note: a `const` is a separate item from the item that contains it
 
+note: erroneous constant encountered
+  --> $DIR/generic-params-from-outer-item-in-const-item.rs:22:9
+   |
+LL |         I
+   |         ^
+
+note: erroneous constant encountered
+  --> $DIR/generic-params-from-outer-item-in-const-item.rs:22:9
+   |
+LL |         I
+   |         ^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0401`.
diff --git a/tests/ui/resolve/issue-50599.stderr b/tests/ui/resolve/issue-50599.stderr
index 24fb3d580b8..427dc9f2049 100644
--- a/tests/ui/resolve/issue-50599.stderr
+++ b/tests/ui/resolve/issue-50599.stderr
@@ -20,6 +20,12 @@ LL -     const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize;
 LL +     const M: usize = (f64::from(N) * LOG10_2) as usize;
    |
 
+note: erroneous constant encountered
+  --> $DIR/issue-50599.rs:4:29
+   |
+LL |     let mut digits = [0u32; M];
+   |                             ^
+
 error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs
index 65a85a5ed68..e27c8048049 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs
@@ -20,7 +20,7 @@ const WRAP_DIRECT_INLINE: WrapInline = WrapInline(NoDerive(0));
 fn main() {
     match WRAP_DIRECT_INLINE {
         WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        //~^ ERROR constant of non-structural type `NoDerive` in a pattern
         _ => { println!("WRAP_DIRECT_INLINE did not match itself"); }
     }
 }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr
index cc5d4106331..8787d140e17 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr
@@ -1,11 +1,20 @@
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
+error: constant of non-structural type `NoDerive` in a pattern
   --> $DIR/cant-hide-behind-direct-struct-embedded.rs:22:9
    |
+LL | struct NoDerive(#[allow(dead_code)] i32);
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL | const WRAP_DIRECT_INLINE: WrapInline = WrapInline(NoDerive(0));
+   | ------------------------------------ constant defined here
+...
 LL |         WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
-   |         ^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/cant-hide-behind-direct-struct-embedded.rs:11:1
+   |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs
index f840b4040b6..713ff23573d 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs
@@ -19,7 +19,7 @@ const WRAP_DIRECT_PARAM: WrapParam<NoDerive> = WrapParam(NoDerive(0));
 fn main() {
     match WRAP_DIRECT_PARAM {
         WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        //~^ ERROR constant of non-structural type `NoDerive` in a pattern
         _ => { println!("WRAP_DIRECT_PARAM did not match itself"); }
     }
 }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr
index 3d00ef2dfbf..ec836db02ad 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr
@@ -1,11 +1,20 @@
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
+error: constant of non-structural type `NoDerive` in a pattern
   --> $DIR/cant-hide-behind-direct-struct-param.rs:21:9
    |
+LL | struct NoDerive(i32);
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL | const WRAP_DIRECT_PARAM: WrapParam<NoDerive> = WrapParam(NoDerive(0));
+   | -------------------------------------------- constant defined here
+...
 LL |         WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
-   |         ^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/cant-hide-behind-direct-struct-param.rs:10:1
+   |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs
index 898acefc83c..7766a469192 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs
@@ -20,7 +20,7 @@ const WRAP_DOUBLY_INDIRECT_INLINE: & &WrapInline = & &WrapInline(& & NoDerive(0)
 fn main() {
     match WRAP_DOUBLY_INDIRECT_INLINE {
         WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        //~^ ERROR constant of non-structural type `NoDerive` in a pattern
         _ => { println!("WRAP_DOUBLY_INDIRECT_INLINE correctly did not match itself"); }
     }
 }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr
index 3636307e16c..fdc16fe300c 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr
@@ -1,11 +1,20 @@
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
+error: constant of non-structural type `NoDerive` in a pattern
   --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:22:9
    |
+LL | struct NoDerive(#[allow(dead_code)] i32);
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL | const WRAP_DOUBLY_INDIRECT_INLINE: & &WrapInline = & &WrapInline(& & NoDerive(0));
+   | ------------------------------------------------ constant defined here
+...
 LL |         WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:11:1
+   |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs
index 7cbaada88a3..ed84900b6e9 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs
@@ -20,7 +20,7 @@ const WRAP_DOUBLY_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(& & NoDe
 fn main() {
     match WRAP_DOUBLY_INDIRECT_PARAM {
         WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        //~^ ERROR constant of non-structural type `NoDerive` in a pattern
         _ => { println!("WRAP_DOUBLY_INDIRECT_PARAM correctly did not match itself"); }
     }
 }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr
index 40fd31762b2..b46fc041f14 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr
@@ -1,11 +1,20 @@
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
+error: constant of non-structural type `NoDerive` in a pattern
   --> $DIR/cant-hide-behind-doubly-indirect-param.rs:22:9
    |
+LL | struct NoDerive(#[allow(dead_code)] i32);
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL | const WRAP_DOUBLY_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(& & NoDerive(0));
+   | -------------------------------------------------------- constant defined here
+...
 LL |         WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/cant-hide-behind-doubly-indirect-param.rs:11:1
+   |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs
index ac868efed6f..5743d7a24d3 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs
@@ -20,7 +20,7 @@ const WRAP_INDIRECT_INLINE: & &WrapInline = & &WrapInline(NoDerive(0));
 fn main() {
     match WRAP_INDIRECT_INLINE {
         WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        //~^ ERROR constant of non-structural type `NoDerive` in a pattern
         _ => { println!("WRAP_INDIRECT_INLINE did not match itself"); }
     }
 }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr
index dbf1848326a..70f39aa01d8 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr
@@ -1,11 +1,20 @@
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
+error: constant of non-structural type `NoDerive` in a pattern
   --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:22:9
    |
+LL | struct NoDerive(#[allow(dead_code)] i32);
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL | const WRAP_INDIRECT_INLINE: & &WrapInline = & &WrapInline(NoDerive(0));
+   | ----------------------------------------- constant defined here
+...
 LL |         WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
-   |         ^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:11:1
+   |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs
index cbfabec6819..9226f9c3ecd 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs
@@ -20,7 +20,7 @@ const WRAP_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(NoDerive(0));
 fn main() {
     match WRAP_INDIRECT_PARAM {
         WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        //~^ ERROR constant of non-structural type `NoDerive` in a pattern
         _ => { println!("WRAP_INDIRECT_PARAM correctly did not match itself"); }
     }
 }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr
index 58acc11a744..fceb3acb025 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr
@@ -1,11 +1,20 @@
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
+error: constant of non-structural type `NoDerive` in a pattern
   --> $DIR/cant-hide-behind-indirect-struct-param.rs:22:9
    |
+LL | struct NoDerive(#[allow(dead_code)] i32);
+   | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL | const WRAP_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(NoDerive(0));
+   | ------------------------------------------------- constant defined here
+...
 LL |         WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
-   |         ^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/cant-hide-behind-indirect-struct-param.rs:11:1
+   |
+LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr
index 0bc1e7fc89b..cdbe72ca48f 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr
@@ -1,62 +1,112 @@
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/fn-ptr-is-not-structurally-matchable.rs:41:14
    |
+LL |     const CFN1: Wrap<fn()> = Wrap(trivial);
+   |     ---------------------- constant defined here
+...
 LL |         Wrap(CFN1) => count += 1,
-   |              ^^^^
+   |              ^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/fn-ptr-is-not-structurally-matchable.rs:49:14
    |
+LL |     const CFN2: Wrap<fn(SM)> = Wrap(sm_to);
+   |     ------------------------ constant defined here
+...
 LL |         Wrap(CFN2) => count += 1,
-   |              ^^^^
+   |              ^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/fn-ptr-is-not-structurally-matchable.rs:57:14
    |
+LL |     const CFN3: Wrap<fn() -> SM> = Wrap(to_sm);
+   |     ---------------------------- constant defined here
+...
 LL |         Wrap(CFN3) => count += 1,
-   |              ^^^^
+   |              ^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/fn-ptr-is-not-structurally-matchable.rs:65:14
    |
+LL |     const CFN4: Wrap<fn(NotSM)> = Wrap(not_sm_to);
+   |     --------------------------- constant defined here
+...
 LL |         Wrap(CFN4) => count += 1,
-   |              ^^^^
+   |              ^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/fn-ptr-is-not-structurally-matchable.rs:73:14
    |
+LL |     const CFN5: Wrap<fn() -> NotSM> = Wrap(to_not_sm);
+   |     ------------------------------- constant defined here
+...
 LL |         Wrap(CFN5) => count += 1,
-   |              ^^^^
+   |              ^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/fn-ptr-is-not-structurally-matchable.rs:81:14
    |
+LL |     const CFN6: Wrap<fn(&SM)> = Wrap(r_sm_to);
+   |     ------------------------- constant defined here
+...
 LL |         Wrap(CFN6) => count += 1,
-   |              ^^^^
+   |              ^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/fn-ptr-is-not-structurally-matchable.rs:89:14
    |
+LL |     const CFN7: Wrap<fn(&()) -> &SM> = Wrap(r_to_r_sm);
+   |     -------------------------------- constant defined here
+...
 LL |         Wrap(CFN7) => count += 1,
-   |              ^^^^
+   |              ^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/fn-ptr-is-not-structurally-matchable.rs:97:14
    |
+LL |     const CFN8: Wrap<fn(&NotSM)> = Wrap(r_not_sm_to);
+   |     ---------------------------- constant defined here
+...
 LL |         Wrap(CFN8) => count += 1,
-   |              ^^^^
+   |              ^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/fn-ptr-is-not-structurally-matchable.rs:105:14
    |
+LL |     const CFN9: Wrap<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm);
+   |     ----------------------------------- constant defined here
+...
 LL |         Wrap(CFN9) => count += 1,
-   |              ^^^^
+   |              ^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/fn-ptr-is-not-structurally-matchable.rs:127:9
    |
+LL |     const CFOO: Foo = Foo {
+   |     --------------- constant defined here
+...
 LL |         CFOO => count += 1,
-   |         ^^^^
+   |         ^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
 error: aborting due to 10 previous errors
 
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs
index c01f8934c75..95a3be517a9 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs
@@ -12,8 +12,7 @@ const A: &[B] = &[];
 
 pub fn main() {
     match &[][..] {
-        A => (),
-        //~^ ERROR must implement `PartialEq`
+        A => (), //~ ERROR constant of non-structural type `&[B]` in a pattern
         _ => (),
     }
 }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr
index 736e4c30c8a..7d3b37686b8 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr
@@ -1,8 +1,16 @@
-error: to use a constant of type `&[B]` in a pattern, the type must implement `PartialEq`
+error: constant of non-structural type `&[B]` in a pattern
   --> $DIR/issue-61188-match-slice-forbidden-without-eq.rs:15:9
    |
+LL | struct B(i32);
+   | -------- must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+LL |
+LL | const A: &[B] = &[];
+   | ------------- constant defined here
+...
 LL |         A => (),
-   |         ^
+   |         ^ constant of non-structural type
+   |
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs
index 0fa2370c95b..843c5a38649 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs
@@ -13,27 +13,35 @@
 
 #[derive(Debug)]
 struct B(i32);
+//~^ NOTE `B` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+//~| NOTE `B` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
 
 // Overriding `PartialEq` to use this strange notion of "equality" exposes
 // whether `match` is using structural-equality or method-dispatch
 // under the hood, which is the antithesis of rust-lang/rfcs#1445
 impl PartialEq for B {
+//~^ NOTE the `PartialEq` trait must be derived, manual `impl`s are not sufficient
+//~| NOTE the `PartialEq` trait must be derived, manual `impl`s are not sufficient
     fn eq(&self, other: &B) -> bool { std::cmp::min(self.0, other.0) == 0 }
 }
 
 fn main() {
     const RR_B0: & & B = & & B(0);
     const RR_B1: & & B = & & B(1);
+    //~^ NOTE constant defined here
+    //~| NOTE constant defined here
 
     match RR_B0 {
         RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        //~^ ERROR constant of non-structural type `B` in a pattern
+        //~| NOTE constant of non-structural type
         _ => { }
     }
 
     match RR_B1 {
         RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        //~^ ERROR constant of non-structural type `B` in a pattern
+        //~| NOTE constant of non-structural type
         _ => { }
     }
 }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr
index e79b05fdf9d..34fffd99c2c 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr
@@ -1,20 +1,38 @@
-error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:29:9
+error: constant of non-structural type `B` in a pattern
+  --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:35:9
    |
+LL | struct B(i32);
+   | -------- `B` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     const RR_B1: & & B = & & B(1);
+   |     ------------------ constant defined here
+...
 LL |         RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
-   |         ^^^^^
+   |         ^^^^^ constant of non-structural type
+   |
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:22:1
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+LL | impl PartialEq for B {
+   | ^^^^^^^^^^^^^^^^^^^^
 
-error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:35:9
+error: constant of non-structural type `B` in a pattern
+  --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:42:9
    |
+LL | struct B(i32);
+   | -------- `B` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL |     const RR_B1: & & B = & & B(1);
+   |     ------------------ constant defined here
+...
 LL |         RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
-   |         ^^^^^
+   |         ^^^^^ constant of non-structural type
+   |
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:22:1
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+LL | impl PartialEq for B {
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
index 7b1832ed0fa..ea6121839be 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
@@ -1,14 +1,24 @@
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/issue-63479-match-fnptr.rs:32:7
    |
+LL | const TEST: Fn = my_fn;
+   | -------------- constant defined here
+...
 LL |     B(TEST) => println!("matched"),
-   |       ^^^^
+   |       ^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
-error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon
   --> $DIR/issue-63479-match-fnptr.rs:37:5
    |
+LL | const TEST2: (Fn, u8) = (TEST, 0);
+   | --------------------- constant defined here
+...
 LL |     TEST2 => println!("matched"),
-   |     ^^^^^
+   |     ^^^^^ can't be used in patterns
+   |
+   = note: see https://github.com/rust-lang/rust/issues/70861 for details
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr
index 44b05ea31e9..7c49870e5d0 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr
@@ -1,8 +1,11 @@
 error: cannot use NaN in patterns
   --> $DIR/issue-6804-nan-match.rs:14:9
    |
+LL | const NAN: f64 = f64::NAN;
+   | -------------- constant defined here
+...
 LL |         NAN => {},
-   |         ^^^
+   |         ^^^ evaluates to `NaN`, which is not allowed in patterns
    |
    = note: NaNs compare inequal to everything, even themselves, so this pattern would never match
    = help: try using the `is_nan` method instead
@@ -10,8 +13,11 @@ LL |         NAN => {},
 error: cannot use NaN in patterns
   --> $DIR/issue-6804-nan-match.rs:19:10
    |
+LL | const NAN: f64 = f64::NAN;
+   | -------------- constant defined here
+...
 LL |         [NAN, _] => {},
-   |          ^^^
+   |          ^^^ evaluates to `NaN`, which is not allowed in patterns
    |
    = note: NaNs compare inequal to everything, even themselves, so this pattern would never match
    = help: try using the `is_nan` method instead
@@ -19,8 +25,11 @@ LL |         [NAN, _] => {},
 error: cannot use NaN in patterns
   --> $DIR/issue-6804-nan-match.rs:24:9
    |
+LL | const C: MyType<f32> = MyType(f32::NAN);
+   | -------------------- constant defined here
+...
 LL |         C => {},
-   |         ^
+   |         ^ evaluates to `NaN`, which is not allowed in patterns
    |
    = note: NaNs compare inequal to everything, even themselves, so this pattern would never match
    = help: try using the `is_nan` method instead
@@ -28,8 +37,11 @@ LL |         C => {},
 error: cannot use NaN in patterns
   --> $DIR/issue-6804-nan-match.rs:30:9
    |
+LL | const NAN: f64 = f64::NAN;
+   | -------------- constant defined here
+...
 LL |         NAN..=1.0 => {},
-   |         ^^^
+   |         ^^^ evaluates to `NaN`, which is not allowed in patterns
    |
    = note: NaNs compare inequal to everything, even themselves, so this pattern would never match
    = help: try using the `is_nan` method instead
@@ -37,8 +49,11 @@ LL |         NAN..=1.0 => {},
 error: cannot use NaN in patterns
   --> $DIR/issue-6804-nan-match.rs:31:16
    |
+LL | const NAN: f64 = f64::NAN;
+   | -------------- constant defined here
+...
 LL |         -1.0..=NAN => {},
-   |                ^^^
+   |                ^^^ evaluates to `NaN`, which is not allowed in patterns
    |
    = note: NaNs compare inequal to everything, even themselves, so this pattern would never match
    = help: try using the `is_nan` method instead
@@ -46,8 +61,11 @@ LL |         -1.0..=NAN => {},
 error: cannot use NaN in patterns
   --> $DIR/issue-6804-nan-match.rs:32:9
    |
+LL | const NAN: f64 = f64::NAN;
+   | -------------- constant defined here
+...
 LL |         NAN.. => {},
-   |         ^^^
+   |         ^^^ evaluates to `NaN`, which is not allowed in patterns
    |
    = note: NaNs compare inequal to everything, even themselves, so this pattern would never match
    = help: try using the `is_nan` method instead
@@ -55,8 +73,11 @@ LL |         NAN.. => {},
 error: cannot use NaN in patterns
   --> $DIR/issue-6804-nan-match.rs:33:11
    |
+LL | const NAN: f64 = f64::NAN;
+   | -------------- constant defined here
+...
 LL |         ..NAN => {},
-   |           ^^^
+   |           ^^^ evaluates to `NaN`, which is not allowed in patterns
    |
    = note: NaNs compare inequal to everything, even themselves, so this pattern would never match
    = help: try using the `is_nan` method instead
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs
index 9020eb291f5..74394698fbc 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs
@@ -1,3 +1,5 @@
+// Note: It is no longer true that both `Eq` and `PartialEq` must the derived, only the later.
+
 #[derive(Eq)]
 struct Foo {
     x: u32
@@ -15,7 +17,7 @@ fn main() {
     let y = Foo { x: 1 };
     match y {
         FOO => { }
-        //~^ ERROR must be annotated with `#[derive(PartialEq)]`
+        //~^ ERROR constant of non-structural type `Foo` in a pattern
         _ => { }
     }
 }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr
index efd9c8c45af..bbcab3b62d0 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr
@@ -1,11 +1,20 @@
-error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/match-requires-both-partialeq-and-eq.rs:17:9
+error: constant of non-structural type `Foo` in a pattern
+  --> $DIR/match-requires-both-partialeq-and-eq.rs:19:9
    |
+LL | struct Foo {
+   | ---------- `Foo` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
+...
+LL | const FOO: Foo = Foo { x: 0 };
+   | -------------- constant defined here
+...
 LL |         FOO => { }
-   |         ^^^
+   |         ^^^ constant of non-structural type
    |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+  --> $DIR/match-requires-both-partialeq-and-eq.rs:8:1
+   |
+LL | impl PartialEq for Foo {
+   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr
index 606f808f093..eab2604d4c0 100644
--- a/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr
+++ b/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr
@@ -6,5 +6,11 @@ LL |     !let y = 42;
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 
+note: erroneous constant encountered
+  --> $DIR/avoid-invalid-mir.rs:11:13
+   |
+LL |     x: [(); N]
+   |             ^
+
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr
index cf4c219215e..e4991823d28 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr
+++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr
@@ -17,6 +17,12 @@ LL |     const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
 LL |     }
    |     - value is dropped here
 
+note: erroneous constant encountered
+  --> $DIR/arbitrary-self-from-method-substs-ice.rs:24:5
+   |
+LL |     FOO;
+   |     ^^^
+
 error[E0801]: invalid generic `self` parameter type: `R`
   --> $DIR/arbitrary-self-from-method-substs-ice.rs:10:49
    |
diff --git a/tests/ui/self/arbitrary-self-opaque.rs b/tests/ui/self/arbitrary-self-opaque.rs
index 3c2e2d9db72..c26ef658b69 100644
--- a/tests/ui/self/arbitrary-self-opaque.rs
+++ b/tests/ui/self/arbitrary-self-opaque.rs
@@ -2,7 +2,6 @@
 struct Foo;
 
 type Bar = impl Sized;
-//~^ ERROR unconstrained opaque type
 
 impl Foo {
     fn foo(self: Bar) {}
diff --git a/tests/ui/self/arbitrary-self-opaque.stderr b/tests/ui/self/arbitrary-self-opaque.stderr
index 5634b3d6e64..c75165d9f8e 100644
--- a/tests/ui/self/arbitrary-self-opaque.stderr
+++ b/tests/ui/self/arbitrary-self-opaque.stderr
@@ -1,5 +1,5 @@
 error[E0307]: invalid `self` parameter type: `Bar`
-  --> $DIR/arbitrary-self-opaque.rs:8:18
+  --> $DIR/arbitrary-self-opaque.rs:7:18
    |
 LL |     fn foo(self: Bar) {}
    |                  ^^^
@@ -8,7 +8,7 @@ LL |     fn foo(self: Bar) {}
    = 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:8:8
+  --> $DIR/arbitrary-self-opaque.rs:7:8
    |
 LL |     fn foo(self: Bar) {}
    |        ^^^
@@ -20,14 +20,6 @@ note: this opaque type is in the signature
 LL | type Bar = impl Sized;
    |            ^^^^^^^^^^
 
-error: unconstrained opaque type
-  --> $DIR/arbitrary-self-opaque.rs:4:12
-   |
-LL | type Bar = impl Sized;
-   |            ^^^^^^^^^^
-   |
-   = note: `Bar` must be used in combination with a concrete type within the same module
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/simd/intrinsic/float-math-pass.rs b/tests/ui/simd/intrinsic/float-math-pass.rs
index 9b14d410acb..24b9941133e 100644
--- a/tests/ui/simd/intrinsic/float-math-pass.rs
+++ b/tests/ui/simd/intrinsic/float-math-pass.rs
@@ -23,6 +23,7 @@ extern "rust-intrinsic" {
     fn simd_fexp<T>(x: T) -> T;
     fn simd_fexp2<T>(x: T) -> T;
     fn simd_fma<T>(x: T, y: T, z: T) -> T;
+    fn simd_relaxed_fma<T>(x: T, y: T, z: T) -> T;
     fn simd_flog<T>(x: T) -> T;
     fn simd_flog10<T>(x: T) -> T;
     fn simd_flog2<T>(x: T) -> T;
@@ -77,6 +78,9 @@ fn main() {
         let r = simd_fma(x, h, h);
         assert_approx_eq!(x, r);
 
+        let r = simd_relaxed_fma(x, h, h);
+        assert_approx_eq!(x, r);
+
         let r = simd_fsqrt(x);
         assert_approx_eq!(x, r);
 
diff --git a/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs b/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs
index 48a98efea5e..0da68afb592 100644
--- a/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs
+++ b/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs
@@ -3,7 +3,6 @@
 trait X {
     fn a<T>() -> T::unknown<{}> {}
     //~^ ERROR: associated type `unknown` not found for `T`
-    //~| ERROR: associated type `unknown` not found for `T`
 }
 
 trait Y {
@@ -14,7 +13,6 @@ trait Y {
 trait Z<T> {
     fn a() -> T::unknown<{}> {}
     //~^ ERROR: associated type `unknown` not found for `T`
-    //~| ERROR: associated type `unknown` not found for `T`
 }
 
 fn main() {}
diff --git a/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr b/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr
index 9598c373e6e..49e41f75ff3 100644
--- a/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr
+++ b/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr
@@ -5,34 +5,18 @@ LL |     fn a<T>() -> T::unknown<{}> {}
    |                     ^^^^^^^ associated type `unknown` not found
 
 error[E0220]: associated type `unknown` not found for `T`
-  --> $DIR/unknown-assoc-with-const-arg.rs:15:18
+  --> $DIR/unknown-assoc-with-const-arg.rs:14:18
    |
 LL |     fn a() -> T::unknown<{}> {}
    |                  ^^^^^^^ associated type `unknown` not found
 
-error[E0220]: associated type `unknown` not found for `T`
-  --> $DIR/unknown-assoc-with-const-arg.rs:4:21
-   |
-LL |     fn a<T>() -> T::unknown<{}> {}
-   |                     ^^^^^^^ associated type `unknown` not found
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0220]: associated type `unknown` not found for `T`
-  --> $DIR/unknown-assoc-with-const-arg.rs:15:18
-   |
-LL |     fn a() -> T::unknown<{}> {}
-   |                  ^^^^^^^ associated type `unknown` not found
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
 error[E0433]: failed to resolve: use of undeclared type `NOT_EXIST`
-  --> $DIR/unknown-assoc-with-const-arg.rs:10:15
+  --> $DIR/unknown-assoc-with-const-arg.rs:9:15
    |
 LL |     fn a() -> NOT_EXIST::unknown<{}> {}
    |               ^^^^^^^^^ use of undeclared type `NOT_EXIST`
 
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0220, E0433.
 For more information about an error, try `rustc --explain E0220`.
diff --git a/tests/ui/traits/const-traits/hir-const-check.rs b/tests/ui/traits/const-traits/hir-const-check.rs
index ea1783b7c2c..c485fb12184 100644
--- a/tests/ui/traits/const-traits/hir-const-check.rs
+++ b/tests/ui/traits/const-traits/hir-const-check.rs
@@ -11,9 +11,9 @@ pub trait MyTrait {
 
 impl const MyTrait for () {
     fn method(&self) -> Option<()> {
-        Some(())?; //~ ERROR `?` is not allowed in a `const fn`
-        //~^ ERROR `?` cannot determine the branch of `Option<()>` in constant functions
-        //~| ERROR `?` cannot convert from residual of `Option<()>` in constant functions
+        Some(())?;
+        //~^ ERROR `?` is not allowed on
+        //~| ERROR `?` is not allowed on
         None
     }
 }
diff --git a/tests/ui/traits/const-traits/hir-const-check.stderr b/tests/ui/traits/const-traits/hir-const-check.stderr
index ef5dba0dc0e..d66a7ea3144 100644
--- a/tests/ui/traits/const-traits/hir-const-check.stderr
+++ b/tests/ui/traits/const-traits/hir-const-check.stderr
@@ -1,34 +1,19 @@
-error[E0658]: `?` is not allowed in a `const fn`
+error[E0015]: `?` is not allowed on `Option<()>` in constant functions
   --> $DIR/hir-const-check.rs:14:9
    |
 LL |         Some(())?;
    |         ^^^^^^^^^
    |
-   = note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
-   = help: add `#![feature(const_try)]` 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[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions
-  --> $DIR/hir-const-check.rs:14:9
-   |
-LL |         Some(())?;
-   |         ^^^^^^^^^
-   |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/option.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions
+error[E0015]: `?` is not allowed on `Option<()>` in constant functions
   --> $DIR/hir-const-check.rs:14:9
    |
 LL |         Some(())?;
    |         ^^^^^^^^^
    |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/option.rs:LL:COL
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0015, E0658.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs
index 9ce81031b27..3473be565c1 100644
--- a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs
+++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs
@@ -18,8 +18,8 @@ impl const Try for TryMe {
 
 const fn t() -> TryMe {
     TryMe?;
-    //~^ ERROR `?` cannot determine the branch of `TryMe` in constant functions
-    //~| ERROR `?` cannot convert from residual of `TryMe` in constant functions
+    //~^ ERROR `?` is not allowed on
+    //~| ERROR `?` is not allowed on
     TryMe
 }
 
diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr
index db047bfd94d..9bd493e5fdb 100644
--- a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr
+++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr
@@ -33,7 +33,7 @@ LL | impl const Try for TryMe {
    = help: implement the missing item: `fn from_output(_: <Self as Try>::Output) -> Self { todo!() }`
    = help: implement the missing item: `fn branch(self) -> ControlFlow<<Self as Try>::Residual, <Self as Try>::Output> { todo!() }`
 
-error[E0015]: `?` cannot determine the branch of `TryMe` in constant functions
+error[E0015]: `?` is not allowed on `TryMe` in constant functions
   --> $DIR/ice-126148-failed-to-normalize.rs:20:5
    |
 LL |     TryMe?;
@@ -41,7 +41,7 @@ LL |     TryMe?;
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions
+error[E0015]: `?` is not allowed on `TryMe` in constant functions
   --> $DIR/ice-126148-failed-to-normalize.rs:20:5
    |
 LL |     TryMe?;
diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr b/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr
new file mode 100644
index 00000000000..bd822970ad1
--- /dev/null
+++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr
@@ -0,0 +1,14 @@
+error[E0119]: conflicting implementations of trait `Foo` for type `(_,)`
+  --> $DIR/overlap-const-with-nonconst.rs:23:1
+   |
+LL | / impl<T> const Foo for T
+LL | | where
+LL | |     T: ~const Bar,
+   | |__________________- first implementation here
+...
+LL |   impl<T> Foo for (T,) {
+   |   ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_,)`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs b/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs
new file mode 100644
index 00000000000..eb66d03faa6
--- /dev/null
+++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs
@@ -0,0 +1,38 @@
+//@ revisions: spec min_spec
+
+#![feature(const_trait_impl)]
+#![cfg_attr(spec, feature(specialization))]
+//[spec]~^ WARN the feature `specialization` is incomplete
+#![cfg_attr(min_spec, feature(min_specialization))]
+
+#[const_trait]
+trait Bar {}
+impl<T> const Bar for T {}
+
+#[const_trait]
+trait Foo {
+    fn method(&self);
+}
+impl<T> const Foo for T
+where
+    T: ~const Bar,
+{
+    default fn method(&self) {}
+}
+// specializing impl:
+impl<T> Foo for (T,) {
+//~^ ERROR conflicting implementations
+    fn method(&self) {
+        println!("hi");
+    }
+}
+
+const fn dispatch<T: ~const Bar + Copy>(t: T) {
+    t.method();
+}
+
+fn main() {
+    const {
+        dispatch(((),));
+    }
+}
diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr b/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr
new file mode 100644
index 00000000000..cbdcb45f6be
--- /dev/null
+++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr
@@ -0,0 +1,24 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/overlap-const-with-nonconst.rs:4:27
+   |
+LL | #![cfg_attr(spec, feature(specialization))]
+   |                           ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0119]: conflicting implementations of trait `Foo` for type `(_,)`
+  --> $DIR/overlap-const-with-nonconst.rs:23:1
+   |
+LL | / impl<T> const Foo for T
+LL | | where
+LL | |     T: ~const Bar,
+   | |__________________- first implementation here
+...
+LL |   impl<T> Foo for (T,) {
+   |   ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_,)`
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr
index bffc60c65fc..9166b8ca5d2 100644
--- a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr
+++ b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr
@@ -1,11 +1,31 @@
-error: cannot specialize on const impl with non-const impl
+error[E0119]: conflicting implementations of trait `Bar`
   --> $DIR/const-default-bound-non-const-specialized-bound.rs:28:1
    |
+LL | / impl<T> const Bar for T
+LL | | where
+LL | |     T: ~const Foo,
+   | |__________________- first implementation here
+...
 LL | / impl<T> Bar for T
 LL | | where
 LL | |     T: Foo, //FIXME ~ ERROR missing `~const` qualifier
 LL | |     T: Specialize,
-   | |__________________^
+   | |__________________^ conflicting implementation
+
+error[E0119]: conflicting implementations of trait `Baz`
+  --> $DIR/const-default-bound-non-const-specialized-bound.rs:48:1
+   |
+LL | / impl<T> const Baz for T
+LL | | where
+LL | |     T: ~const Foo,
+   | |__________________- first implementation here
+...
+LL | / impl<T> const Baz for T //FIXME ~ ERROR conflicting implementations of trait `Baz`
+LL | | where
+LL | |     T: Foo,
+LL | |     T: Specialize,
+   | |__________________^ conflicting implementation
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr
new file mode 100644
index 00000000000..38fc5ddfbef
--- /dev/null
+++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo`
+  --> $DIR/const-default-impl-non-const-specialized-impl.rs:22:1
+   |
+LL | impl<T> const Value for T {
+   | ------------------------- first implementation here
+...
+LL | impl Value for FortyTwo {
+   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `FortyTwo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs
index a3bb9b3f93e..acf0a967a88 100644
--- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs
+++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs
@@ -1,7 +1,10 @@
 // Tests that specializing trait impls must be at least as const as the default impl.
+//@ revisions: spec min_spec
 
 #![feature(const_trait_impl)]
-#![feature(min_specialization)]
+#![cfg_attr(spec, feature(specialization))]
+//[spec]~^ WARN the feature `specialization` is incomplete
+#![cfg_attr(min_spec, feature(min_specialization))]
 
 #[const_trait]
 trait Value {
@@ -16,7 +19,8 @@ impl<T> const Value for T {
 
 struct FortyTwo;
 
-impl Value for FortyTwo { //~ ERROR cannot specialize on const impl with non-const impl
+impl Value for FortyTwo {
+    //~^ ERROR conflicting implementations
     fn value() -> u32 {
         println!("You can't do that (constly)");
         42
diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr
new file mode 100644
index 00000000000..b59c42f5189
--- /dev/null
+++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr
@@ -0,0 +1,22 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/const-default-impl-non-const-specialized-impl.rs:5:27
+   |
+LL | #![cfg_attr(spec, feature(specialization))]
+   |                           ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo`
+  --> $DIR/const-default-impl-non-const-specialized-impl.rs:22:1
+   |
+LL | impl<T> const Value for T {
+   | ------------------------- first implementation here
+...
+LL | impl Value for FortyTwo {
+   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `FortyTwo`
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr
deleted file mode 100644
index e356621ba47..00000000000
--- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: cannot specialize on const impl with non-const impl
-  --> $DIR/const-default-impl-non-const-specialized-impl.rs:19:1
-   |
-LL | impl Value for FortyTwo {
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/traits/const-traits/specializing-constness.rs b/tests/ui/traits/const-traits/specializing-constness.rs
index 632121924a6..94b6da7124d 100644
--- a/tests/ui/traits/const-traits/specializing-constness.rs
+++ b/tests/ui/traits/const-traits/specializing-constness.rs
@@ -21,8 +21,7 @@ impl<T: ~const Spec> const A for T {
 }
 
 impl<T: Spec + Sup> A for T {
-//~^ ERROR: cannot specialize
-//FIXME(const_trait_impl) ~| ERROR: missing `~const` qualifier
+    //~^ ERROR conflicting implementations of trait `A`
     fn a() -> u32 {
         3
     }
diff --git a/tests/ui/traits/const-traits/specializing-constness.stderr b/tests/ui/traits/const-traits/specializing-constness.stderr
index 21e21c2cb71..2ca70b53e4e 100644
--- a/tests/ui/traits/const-traits/specializing-constness.stderr
+++ b/tests/ui/traits/const-traits/specializing-constness.stderr
@@ -1,8 +1,12 @@
-error: cannot specialize on const impl with non-const impl
+error[E0119]: conflicting implementations of trait `A`
   --> $DIR/specializing-constness.rs:23:1
    |
+LL | impl<T: ~const Spec> const A for T {
+   | ---------------------------------- first implementation here
+...
 LL | impl<T: Spec + Sup> A for T {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/const-traits/trait-default-body-stability.stderr b/tests/ui/traits/const-traits/trait-default-body-stability.stderr
index 5806b6d6fd2..b471cb81c3b 100644
--- a/tests/ui/traits/const-traits/trait-default-body-stability.stderr
+++ b/tests/ui/traits/const-traits/trait-default-body-stability.stderr
@@ -16,7 +16,7 @@ LL | impl const FromResidual for T {
    = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
    = note: adding a non-const method body in the future would be a breaking change
 
-error[E0015]: `?` cannot determine the branch of `T` in constant functions
+error[E0015]: `?` is not allowed on `T` in constant functions
   --> $DIR/trait-default-body-stability.rs:45:9
    |
 LL |         T?
@@ -24,7 +24,7 @@ LL |         T?
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: `?` cannot convert from residual of `T` in constant functions
+error[E0015]: `?` is not allowed on `T` in constant functions
   --> $DIR/trait-default-body-stability.rs:45:9
    |
 LL |         T?
diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr
index 03a4017b3d7..38e692521ca 100644
--- a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr
+++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr
@@ -23,29 +23,29 @@ LL | struct Struct {}
    | ---------------- not a trait
 
 error: function not found in this trait
-  --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34
+  --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31
    |
 LL | #[rustc_must_implement_one_of(a, b)]
-   |                                  ^
-
-error: the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
-  --> $DIR/rustc_must_implement_one_of_misuse.rs:14:1
-   |
-LL | #[rustc_must_implement_one_of(a)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^
 
 error: function not found in this trait
-  --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31
+  --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34
    |
 LL | #[rustc_must_implement_one_of(a, b)]
-   |                               ^
+   |                                  ^
 
 error: function not found in this trait
-  --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34
+  --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34
    |
 LL | #[rustc_must_implement_one_of(a, b)]
    |                                  ^
 
+error: the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
+  --> $DIR/rustc_must_implement_one_of_misuse.rs:14:1
+   |
+LL | #[rustc_must_implement_one_of(a)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: not a function
   --> $DIR/rustc_must_implement_one_of_misuse.rs:26:5
    |
diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.rs b/tests/ui/traits/next-solver/issue-118950-root-region.rs
index e1bd234a275..8fe53d6773b 100644
--- a/tests/ui/traits/next-solver/issue-118950-root-region.rs
+++ b/tests/ui/traits/next-solver/issue-118950-root-region.rs
@@ -18,6 +18,6 @@ impl<T> Overlap<T> for T {}
 
 impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {}
 //~^ ERROR cannot find type `Missing` in this scope
-//~| ERROR the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied
+//~| ERROR the trait bound `T: Overlap<for<'a> fn(Assoc<'a, T>)>` is not satisfied
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr
index f6545c6ebf9..09162970d33 100644
--- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr
+++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr
@@ -26,17 +26,16 @@ LL | trait ToUnit<'a> {
    | ^^^^^^^^^^^^^^^^
 
  WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. }
-error[E0277]: the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied
-  --> $DIR/issue-118950-root-region.rs:19:17
+error[E0277]: the trait bound `T: Overlap<for<'a> fn(Assoc<'a, T>)>` is not satisfied
+  --> $DIR/issue-118950-root-region.rs:19:47
    |
 LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {}
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `*const T`
+   |                                               ^ the trait `Overlap<for<'a> fn(Assoc<'a, T>)>` is not implemented for `T`
    |
-help: this trait has no implementations, consider adding one
-  --> $DIR/issue-118950-root-region.rs:8:1
+help: consider further restricting type parameter `T`
    |
-LL | trait ToUnit<'a> {
-   | ^^^^^^^^^^^^^^^^
+LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T>, T: Overlap<for<'a> fn(Assoc<'a, T>)> {}
+   |                                                                          ++++++++++++++++++++++++++++++++++++++
 
 error: aborting due to 3 previous errors; 1 warning emitted
 
diff --git a/tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs b/tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs
new file mode 100644
index 00000000000..1dca19d28e9
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs
@@ -0,0 +1,46 @@
+//@ check-pass
+//@ compile-flags: -Znext-solver
+
+// Minimized example from `rustc_type_ir` that demonstrates a missing deep normalization
+// in the new solver when computing the implies outlives bounds of an impl.
+
+use std::marker::PhantomData;
+use std::ops::Deref;
+
+pub struct SearchGraph<D: Delegate, X = <D as Delegate>::Cx> {
+    d: PhantomData<D>,
+    x: PhantomData<X>,
+}
+
+pub trait Delegate {
+    type Cx;
+}
+
+struct SearchGraphDelegate<D: SolverDelegate> {
+    _marker: PhantomData<D>,
+}
+
+impl<D> Delegate for SearchGraphDelegate<D>
+where
+    D: SolverDelegate,
+{
+    type Cx = D::Interner;
+}
+
+pub trait SolverDelegate {
+    type Interner;
+}
+
+struct EvalCtxt<'a, D, I>
+where
+    D: SolverDelegate<Interner = I>,
+{
+    search_graph: &'a SearchGraph<SearchGraphDelegate<D>>,
+}
+
+impl<'a, D, I> EvalCtxt<'a, D, <D as SolverDelegate>::Interner>
+where
+    D: SolverDelegate<Interner = I>
+{}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/typeck/structurally-resolve-in-probe_adt.rs b/tests/ui/traits/next-solver/typeck/structurally-resolve-in-probe_adt.rs
new file mode 100644
index 00000000000..23915808279
--- /dev/null
+++ b/tests/ui/traits/next-solver/typeck/structurally-resolve-in-probe_adt.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+//@ compile-flags: -Znext-solver
+
+trait Mirror {
+    type Assoc;
+}
+impl<T> Mirror for T {
+    type Assoc = T;
+}
+
+type Foo<T> = <Option<T> as Mirror>::Assoc;
+
+fn main() {
+    let x = Foo::<i32>::None;
+}
diff --git a/tests/ui/transmutability/uninhabited.rs b/tests/ui/transmutability/uninhabited.rs
index 74f7a1a2e89..274104ffb39 100644
--- a/tests/ui/transmutability/uninhabited.rs
+++ b/tests/ui/transmutability/uninhabited.rs
@@ -91,3 +91,19 @@ fn distant_void() {
     assert::is_maybe_transmutable::<DistantVoid, &'static Void>();
     assert::is_maybe_transmutable::<u128, DistantVoid>(); //~ ERROR: cannot be safely transmuted
 }
+
+fn issue_126267() {
+    pub enum ApiError {}
+    pub struct TokioError {
+        b: bool,
+    }
+    pub enum Error {
+        Api { source: ApiError }, // this variant is uninhabited
+        Ethereum,
+        Tokio { source: TokioError },
+    }
+
+    struct Src;
+    type Dst = Error;
+    assert::is_maybe_transmutable::<Src, Dst>(); //~ERROR: cannot be safely transmuted
+}
diff --git a/tests/ui/transmutability/uninhabited.stderr b/tests/ui/transmutability/uninhabited.stderr
index 3fa02f0867c..f112d2fbe44 100644
--- a/tests/ui/transmutability/uninhabited.stderr
+++ b/tests/ui/transmutability/uninhabited.stderr
@@ -110,7 +110,29 @@ LL | |             }
 LL | |         }>
    | |__________^ required by this bound in `is_maybe_transmutable`
 
-error: aborting due to 7 previous errors
+error[E0277]: `Src` cannot be safely transmuted into `issue_126267::Error`
+  --> $DIR/uninhabited.rs:108:42
+   |
+LL |     assert::is_maybe_transmutable::<Src, Dst>();
+   |                                          ^^^ the size of `Src` is smaller than the size of `issue_126267::Error`
+   |
+note: required by a bound in `is_maybe_transmutable`
+  --> $DIR/uninhabited.rs:10:14
+   |
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this function
+LL |       where
+LL |           Dst: TransmuteFrom<Src, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
+
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0080, E0277.
 For more information about an error, try `rustc --explain E0080`.
diff --git a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs
index 18cfb1c1f93..4b2ee344aa3 100644
--- a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs
+++ b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs
@@ -3,7 +3,6 @@
 #![feature(type_alias_impl_trait)]
 trait Trait<T> {}
 type Alias<'a, U> = impl Trait<U>;
-//~^ ERROR unconstrained opaque type
 
 pub enum UninhabitedVariants {
     Tuple(Alias),
diff --git a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr
index cf366c55ea8..55df117d066 100644
--- a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr
+++ b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr
@@ -1,5 +1,5 @@
 error[E0106]: missing lifetime specifier
-  --> $DIR/bad-tait-no-substs.rs:9:11
+  --> $DIR/bad-tait-no-substs.rs:8:11
    |
 LL |     Tuple(Alias),
    |           ^^^^^ expected named lifetime parameter
@@ -11,7 +11,7 @@ LL ~     Tuple(Alias<'a>),
    |
 
 error[E0107]: missing generics for type alias `Alias`
-  --> $DIR/bad-tait-no-substs.rs:9:11
+  --> $DIR/bad-tait-no-substs.rs:8:11
    |
 LL |     Tuple(Alias),
    |           ^^^^^ expected 1 generic argument
@@ -27,7 +27,7 @@ LL |     Tuple(Alias<U>),
    |                +++
 
 error[E0792]: non-defining opaque type use in defining scope
-  --> $DIR/bad-tait-no-substs.rs:9:11
+  --> $DIR/bad-tait-no-substs.rs:8:11
    |
 LL |     Tuple(Alias),
    |           ^^^^^ argument `'_` is not a generic parameter
@@ -39,7 +39,7 @@ LL | type Alias<'a, U> = impl Trait<U>;
    |                     ^^^^^^^^^^^^^
 
 error: item does not constrain `Alias::{opaque#0}`, but has it in its signature
-  --> $DIR/bad-tait-no-substs.rs:15:4
+  --> $DIR/bad-tait-no-substs.rs:14:4
    |
 LL | fn uwu(x: UninhabitedVariants) {
    |    ^^^
@@ -51,22 +51,14 @@ note: this opaque type is in the signature
 LL | type Alias<'a, U> = impl Trait<U>;
    |                     ^^^^^^^^^^^^^
 
-error: unconstrained opaque type
-  --> $DIR/bad-tait-no-substs.rs:5:21
-   |
-LL | type Alias<'a, U> = impl Trait<U>;
-   |                     ^^^^^^^^^^^^^
-   |
-   = note: `Alias` must be used in combination with a concrete type within the same module
-
 error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` not covered
-  --> $DIR/bad-tait-no-substs.rs:17:11
+  --> $DIR/bad-tait-no-substs.rs:16:11
    |
 LL |     match x {}
    |           ^ pattern `UninhabitedVariants::Tuple(_)` not covered
    |
 note: `UninhabitedVariants` defined here
-  --> $DIR/bad-tait-no-substs.rs:8:10
+  --> $DIR/bad-tait-no-substs.rs:7:10
    |
 LL | pub enum UninhabitedVariants {
    |          ^^^^^^^^^^^^^^^^^^^
@@ -80,7 +72,7 @@ LL +         UninhabitedVariants::Tuple(_) => todo!(),
 LL +     }
    |
 
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0004, E0106, E0107, E0792.
 For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr
index b7999a695e7..5b77bb6c2bc 100644
--- a/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr
+++ b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr
@@ -1,5 +1,5 @@
 error: `Bar` is forbidden as the type of a const generic parameter
-  --> $DIR/const_generic_type.rs:8:24
+  --> $DIR/const_generic_type.rs:7:24
    |
 LL | async fn test<const N: crate::Bar>() {
    |                        ^^^^^^^^^^
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 ec8a51b0818..8888f2d49df 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
@@ -1,5 +1,5 @@
 error: `Bar` is forbidden as the type of a const generic parameter
-  --> $DIR/const_generic_type.rs:8:24
+  --> $DIR/const_generic_type.rs:7:24
    |
 LL | async fn test<const N: crate::Bar>() {
    |                        ^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | async fn test<const N: crate::Bar>() {
    = note: the only supported types are integers, `bool`, and `char`
 
 error: item does not constrain `Bar::{opaque#0}`, but has it in its signature
-  --> $DIR/const_generic_type.rs:8:10
+  --> $DIR/const_generic_type.rs:7:10
    |
 LL | async fn test<const N: crate::Bar>() {
    |          ^^^^
@@ -20,7 +20,7 @@ LL | type Bar = impl std::fmt::Display;
    |            ^^^^^^^^^^^^^^^^^^^^^^
 
 error: item does not constrain `Bar::{opaque#0}`, but has it in its signature
-  --> $DIR/const_generic_type.rs:8:38
+  --> $DIR/const_generic_type.rs:7:38
    |
 LL |   async fn test<const N: crate::Bar>() {
    |  ______________________________________^
@@ -39,13 +39,5 @@ note: this opaque type is in the signature
 LL | type Bar = impl std::fmt::Display;
    |            ^^^^^^^^^^^^^^^^^^^^^^
 
-error: unconstrained opaque type
-  --> $DIR/const_generic_type.rs:5:12
-   |
-LL | type Bar = impl std::fmt::Display;
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `Bar` must be used in combination with a concrete type within the same module
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.rs b/tests/ui/type-alias-impl-trait/const_generic_type.rs
index de493d04f81..7149370048b 100644
--- a/tests/ui/type-alias-impl-trait/const_generic_type.rs
+++ b/tests/ui/type-alias-impl-trait/const_generic_type.rs
@@ -3,7 +3,6 @@
 
 #![feature(type_alias_impl_trait)]
 type Bar = impl std::fmt::Display;
-//[no_infer]~^ ERROR: unconstrained opaque type
 
 async fn test<const N: crate::Bar>() {
     //~^ ERROR: `Bar` is forbidden as the type of a const generic parameter
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
index 96c905ef3a9..fd06ea677c3 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
@@ -8,7 +8,6 @@
 use std::future::Future;
 
 type FutNothing<'a> = impl 'a + Future<Output = ()>;
-//~^ ERROR: unconstrained opaque type
 
 async fn operation(_: &mut ()) -> () {
     //~^ ERROR: concrete type differs from previous
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
index 0c2772683a9..08ebc3208d7 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
@@ -1,5 +1,5 @@
 error: item does not constrain `FutNothing::{opaque#0}`, but has it in its signature
-  --> $DIR/hkl_forbidden4.rs:19:10
+  --> $DIR/hkl_forbidden4.rs:18:10
    |
 LL | async fn call<F>(_f: F)
    |          ^^^^
@@ -12,7 +12,7 @@ LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item does not constrain `FutNothing::{opaque#0}`, but has it in its signature
-  --> $DIR/hkl_forbidden4.rs:23:1
+  --> $DIR/hkl_forbidden4.rs:22:1
    |
 LL | / {
 LL | |
@@ -27,16 +27,8 @@ note: this opaque type is in the signature
 LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: unconstrained opaque type
-  --> $DIR/hkl_forbidden4.rs:10:23
-   |
-LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `FutNothing` must be used in combination with a concrete type within the same module
-
 error[E0792]: expected generic lifetime parameter, found `'any`
-  --> $DIR/hkl_forbidden4.rs:15:5
+  --> $DIR/hkl_forbidden4.rs:14:5
    |
 LL | async fn operation(_: &mut ()) -> () {
    |                       - this generic parameter must be used with a generic lifetime parameter
@@ -45,19 +37,19 @@ LL |     call(operation).await
    |     ^^^^^^^^^^^^^^^
 
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/hkl_forbidden4.rs:13:1
+  --> $DIR/hkl_forbidden4.rs:12:1
    |
 LL | async fn operation(_: &mut ()) -> () {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}`
    |
 note: previous use here
-  --> $DIR/hkl_forbidden4.rs:15:5
+  --> $DIR/hkl_forbidden4.rs:14:5
    |
 LL |     call(operation).await
    |     ^^^^^^^^^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'any`
-  --> $DIR/hkl_forbidden4.rs:23:1
+  --> $DIR/hkl_forbidden4.rs:22:1
    |
 LL |   type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |                   -- this generic parameter must be used with a generic lifetime parameter
@@ -68,6 +60,6 @@ LL | |
 LL | | }
    | |_^
 
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs
index a7d824c5a6a..aaf2812532d 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs
@@ -4,7 +4,6 @@
 use std::fmt::Debug;
 
 type FooX = impl Debug;
-//~^ ERROR unconstrained opaque type
 
 trait Foo<A> {}
 
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr
index 9ccd9544896..969409ebc59 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr
@@ -1,5 +1,5 @@
 error: item does not constrain `FooX::{opaque#0}`, but has it in its signature
-  --> $DIR/nested-tait-inference3.rs:13:4
+  --> $DIR/nested-tait-inference3.rs:12:4
    |
 LL | fn foo() -> impl Foo<FooX> {
    |    ^^^
@@ -11,13 +11,5 @@ note: this opaque type is in the signature
 LL | type FooX = impl Debug;
    |             ^^^^^^^^^^
 
-error: unconstrained opaque type
-  --> $DIR/nested-tait-inference3.rs:6:13
-   |
-LL | type FooX = impl Debug;
-   |             ^^^^^^^^^^
-   |
-   = note: `FooX` must be used in combination with a concrete type within the same module
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
index 3954672500b..41238c27351 100644
--- a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
+++ b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
@@ -5,7 +5,6 @@
 
 mod foo {
     pub type Foo = impl Copy;
-    //~^ ERROR unconstrained opaque type
 
     // make compiler happy about using 'Foo'
     pub fn bar(x: Foo) -> Foo {
diff --git a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
index d95a4a8a727..eed88c5df4f 100644
--- a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
+++ b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
@@ -1,5 +1,5 @@
 error: item does not constrain `Foo::{opaque#0}`, but has it in its signature
-  --> $DIR/no_inferrable_concrete_type.rs:11:12
+  --> $DIR/no_inferrable_concrete_type.rs:10:12
    |
 LL |     pub fn bar(x: Foo) -> Foo {
    |            ^^^
@@ -11,13 +11,5 @@ note: this opaque type is in the signature
 LL |     pub type Foo = impl Copy;
    |                    ^^^^^^^^^
 
-error: unconstrained opaque type
-  --> $DIR/no_inferrable_concrete_type.rs:7:20
-   |
-LL |     pub type Foo = impl Copy;
-   |                    ^^^^^^^^^
-   |
-   = note: `Foo` must be used in combination with a concrete type within the same module
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr
index 98d71aa9a17..28f5d6728a9 100644
--- a/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr
+++ b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr
@@ -1,8 +1,11 @@
-error: `Bar` cannot be used in patterns
+error: opaque type `Bar` cannot be used in patterns
   --> $DIR/structural-match-no-leak.rs:16:9
    |
+LL | const LEAK_FREE: bar::Bar = bar::leak_free();
+   | ------------------------- constant defined here
+...
 LL |         LEAK_FREE => (),
-   |         ^^^^^^^^^
+   |         ^^^^^^^^^ opaque type can't be used in patterns
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/structural-match.stderr b/tests/ui/type-alias-impl-trait/structural-match.stderr
index c7478b0a135..b06b31a060f 100644
--- a/tests/ui/type-alias-impl-trait/structural-match.stderr
+++ b/tests/ui/type-alias-impl-trait/structural-match.stderr
@@ -1,8 +1,11 @@
-error: `foo::Foo` cannot be used in patterns
+error: opaque type `foo::Foo` cannot be used in patterns
   --> $DIR/structural-match.rs:18:9
    |
+LL | const VALUE: Foo = value();
+   | ---------------- constant defined here
+...
 LL |         VALUE => (),
-   |         ^^^^^
+   |         ^^^^^ opaque type can't be used in patterns
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type/type-dependent-def-issue-49241.stderr b/tests/ui/type/type-dependent-def-issue-49241.stderr
index cf372dc5968..4e55618e5cb 100644
--- a/tests/ui/type/type-dependent-def-issue-49241.stderr
+++ b/tests/ui/type/type-dependent-def-issue-49241.stderr
@@ -9,6 +9,12 @@ help: consider using `let` instead of `const`
 LL |     let l: usize = v.count();
    |     ~~~
 
+note: erroneous constant encountered
+  --> $DIR/type-dependent-def-issue-49241.rs:4:18
+   |
+LL |     let s: [u32; l] = v.into_iter().collect();
+   |                  ^
+
 error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0435`.
diff --git a/tests/ui/union/union-const-pat.stderr b/tests/ui/union/union-const-pat.stderr
index e9dbb275944..59dc89c77a4 100644
--- a/tests/ui/union/union-const-pat.stderr
+++ b/tests/ui/union/union-const-pat.stderr
@@ -1,8 +1,11 @@
 error: cannot use unions in constant patterns
   --> $DIR/union-const-pat.rs:10:9
    |
+LL | const C: U = U { a: 10 };
+   | ---------- constant defined here
+...
 LL |         C => {}
-   |         ^
+   |         ^ can't use a `union` here
 
 error: aborting due to 1 previous error
 
diff --git a/triagebot.toml b/triagebot.toml
index 47b96824098..4d6806711fb 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -996,7 +996,6 @@ warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
 users_on_vacation = [
     "jyn514",
-    "oli-obk",
 ]
 
 [assign.adhoc_groups]