about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml7
-rw-r--r--.reuse/dep51
-rw-r--r--Cargo.lock5
-rw-r--r--README.md2
-rw-r--r--RELEASES.md117
-rw-r--r--compiler/rustc_abi/Cargo.toml4
-rw-r--r--compiler/rustc_abi/src/layout.rs310
-rw-r--r--compiler/rustc_abi/src/lib.rs240
-rw-r--r--compiler/rustc_arena/src/lib.rs253
-rw-r--r--compiler/rustc_ast/src/entry.rs27
-rw-r--r--compiler/rustc_ast/src/token.rs2
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl2
-rw-r--r--compiler/rustc_ast_lowering/src/format.rs47
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs5
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs56
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs1
-rw-r--r--compiler/rustc_attr/Cargo.toml10
-rw-r--r--compiler/rustc_attr/src/builtin.rs4
-rw-r--r--compiler/rustc_attr/src/session_diagnostics.rs9
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs5
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs5
-rw-r--r--compiler/rustc_borrowck/src/lib.rs4
-rw-r--r--compiler/rustc_borrowck/src/places_conflict.rs2
-rw-r--r--compiler/rustc_borrowck/src/prefixes.rs3
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs6
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs22
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh2
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs10
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs2
-rwxr-xr-xcompiler/rustc_codegen_gcc/test.sh2
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs93
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs45
-rw-r--r--compiler/rustc_codegen_llvm/src/type_.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/type_.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs25
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs25
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs9
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs32
-rw-r--r--compiler/rustc_const_eval/src/util/compare_types.rs14
-rw-r--r--compiler/rustc_const_eval/src/util/mod.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0551.md4
-rw-r--r--compiler/rustc_errors/src/lib.rs11
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_fluent_macro/src/fluent.rs58
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl2
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs60
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs100
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs57
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs74
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs41
-rw-r--r--compiler/rustc_infer/messages.ftl4
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs10
-rw-r--r--compiler/rustc_infer/src/infer/outlives/test_type_match.rs24
-rw-r--r--compiler/rustc_lint/messages.ftl6
-rw-r--r--compiler/rustc_lint/src/async_fn_in_trait.rs128
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs25
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs10
-rw-r--r--compiler/rustc_lint/src/reference_casting.rs26
-rw-r--r--compiler/rustc_llvm/Cargo.toml4
-rw-r--r--compiler/rustc_log/src/lib.rs4
-rw-r--r--compiler/rustc_middle/src/arena.rs2
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs11
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs10
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs26
-rw-r--r--compiler/rustc_middle/src/mir/patch.rs11
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs15
-rw-r--r--compiler/rustc_middle/src/mir/statement.rs3
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs16
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs9
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs10
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs12
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs14
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs9
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs50
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs3
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_temp.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs3
-rw-r--r--compiler/rustc_mir_build/src/build/misc.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs242
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs9
-rw-r--r--compiler/rustc_mir_transform/src/add_subtyping_projections.rs70
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/counters.rs37
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs81
-rw-r--r--compiler/rustc_mir_transform/src/coverage/query.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs57
-rw-r--r--compiler/rustc_mir_transform/src/coverage/tests.rs34
-rw-r--r--compiler/rustc_mir_transform/src/deref_separator.rs2
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_box_derefs.rs2
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs2
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs2
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs1
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs32
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/reveal_all.rs4
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs10
-rw-r--r--compiler/rustc_monomorphize/messages.ftl2
-rw-r--r--compiler/rustc_parse/messages.ftl30
-rw-r--r--compiler/rustc_parse/src/parser/item.rs7
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs2
-rw-r--r--compiler/rustc_passes/src/dead.rs73
-rw-r--r--compiler/rustc_passes/src/entry.rs33
-rw-r--r--compiler/rustc_query_system/messages.ftl2
-rw-r--r--compiler/rustc_resolve/messages.ftl12
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs4
-rw-r--r--compiler/rustc_resolve/src/late.rs38
-rw-r--r--compiler/rustc_session/messages.ftl2
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs175
-rw-r--r--compiler/rustc_span/src/symbol.rs51
-rw-r--r--compiler/rustc_target/Cargo.toml1
-rw-r--r--compiler/rustc_target/src/abi/mod.rs110
-rw-r--r--compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs2
-rw-r--r--compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs91
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs122
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs52
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs2
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs2
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs2
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs9
-rw-r--r--compiler/stable_mir/src/mir/body.rs24
-rw-r--r--config.example.toml17
-rw-r--r--library/alloc/src/borrow.rs1
-rw-r--r--library/alloc/src/collections/btree/dedup_sorted_iter.rs2
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/rc.rs5
-rw-r--r--library/alloc/src/string.rs1
-rw-r--r--library/alloc/src/sync.rs5
-rw-r--r--library/core/src/array/iter.rs1
-rw-r--r--library/core/src/cell.rs2
-rw-r--r--library/core/src/cmp.rs68
-rw-r--r--library/core/src/convert/mod.rs2
-rw-r--r--library/core/src/default.rs1
-rw-r--r--library/core/src/fmt/builders.rs1
-rw-r--r--library/core/src/fmt/mod.rs7
-rw-r--r--library/core/src/fmt/rt.rs4
-rw-r--r--library/core/src/hint.rs2
-rw-r--r--library/core/src/intrinsics.rs5
-rw-r--r--library/core/src/iter/adapters/peekable.rs1
-rw-r--r--library/core/src/iter/sources/empty.rs1
-rw-r--r--library/core/src/iter/sources/once.rs1
-rw-r--r--library/core/src/iter/sources/successors.rs2
-rw-r--r--library/core/src/iter/traits/collect.rs1
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/macros/mod.rs34
-rw-r--r--library/core/src/mem/manually_drop.rs12
-rw-r--r--library/core/src/mem/mod.rs12
-rw-r--r--library/core/src/num/f32.rs44
-rw-r--r--library/core/src/num/f64.rs42
-rw-r--r--library/core/src/ops/deref.rs1
-rw-r--r--library/core/src/ops/range.rs1
-rw-r--r--library/core/src/option.rs14
-rw-r--r--library/core/src/panic.rs45
-rw-r--r--library/core/src/panicking.rs12
-rw-r--r--library/core/src/primitive_docs.rs10
-rw-r--r--library/core/src/ptr/mod.rs34
-rw-r--r--library/core/src/ptr/non_null.rs1
-rw-r--r--library/core/src/result.rs1
-rw-r--r--library/core/src/slice/iter.rs1
-rw-r--r--library/core/src/slice/raw.rs2
-rw-r--r--library/core/src/str/mod.rs2
-rw-r--r--library/core/src/str/traits.rs1
-rw-r--r--library/core/src/time.rs9
-rw-r--r--library/core/tests/array.rs4
-rw-r--r--library/std/src/fs.rs3
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--library/std/src/io/stdio.rs2
-rw-r--r--library/std/src/lib.rs4
-rw-r--r--library/std/src/net/udp.rs21
-rw-r--r--library/std/src/process.rs6
-rw-r--r--library/std/src/sync/rwlock.rs4
-rw-r--r--library/std/src/sys/personality/gcc.rs2
-rw-r--r--library/std/src/sys/sgx/abi/usercalls/alloc.rs207
-rw-r--r--library/std/src/sys/sgx/waitqueue/mod.rs26
-rw-r--r--library/std/src/sys/uefi/mod.rs1
-rw-r--r--library/std/src/sys/uefi/stdio.rs162
-rw-r--r--library/std/src/sys/unix/fs.rs1
-rw-r--r--library/std/src/sys/unix/thread_local_dtor.rs43
-rw-r--r--library/std/src/sys/wasi/mod.rs115
-rw-r--r--library/std/src/sys/windows/c.rs4
-rw-r--r--library/std/src/sys/windows/cmath.rs6
-rw-r--r--library/std/src/sys/windows/fs.rs8
-rw-r--r--library/std/src/sys/windows/io.rs4
-rw-r--r--library/std/src/sys/windows/net.rs2
-rw-r--r--library/std/src/sys/windows/process.rs5
-rw-r--r--library/std/src/sys/windows/thread.rs2
-rw-r--r--library/std/src/time.rs3
m---------library/stdarch0
-rw-r--r--rust-bors.toml1
-rw-r--r--src/bootstrap/CHANGELOG.md71
-rw-r--r--src/bootstrap/README.md14
-rw-r--r--src/bootstrap/bin/main.rs41
-rw-r--r--src/bootstrap/bootstrap.py6
-rw-r--r--src/bootstrap/bootstrap_test.py2
-rw-r--r--src/bootstrap/compile.rs19
-rw-r--r--src/bootstrap/config.rs20
-rw-r--r--src/bootstrap/config/tests.rs12
-rw-r--r--src/bootstrap/install.rs6
-rw-r--r--src/bootstrap/lib.rs23
-rw-r--r--src/bootstrap/mk/Makefile.in7
-rw-r--r--src/bootstrap/setup.rs5
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/wasm32/Dockerfile63
-rw-r--r--src/ci/github-actions/ci.yml7
-rw-r--r--src/doc/rustc/src/platform-support.md47
-rw-r--r--src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md2
-rw-r--r--src/doc/rustc/src/platform-support/mips-release-6.md2
-rw-r--r--src/doc/rustc/src/platform-support/nto-qnx.md2
-rw-r--r--src/doc/rustc/src/platform-support/openharmony.md2
-rw-r--r--src/doc/rustc/src/platform-support/unknown-uefi.md8
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md161
-rw-r--r--src/doc/unstable-book/src/language-features/plugin.md2
-rw-r--r--src/librustdoc/clean/auto_trait.rs7
-rw-r--r--src/librustdoc/clean/inline.rs17
-rw-r--r--src/librustdoc/clean/mod.rs111
-rw-r--r--src/librustdoc/clean/simplify.rs19
-rw-r--r--src/librustdoc/clean/types.rs11
-rw-r--r--src/librustdoc/html/format.rs3
-rw-r--r--src/librustdoc/html/static/js/search.js2
-rw-r--r--src/librustdoc/json/conversions.rs5
-rw-r--r--src/tools/build_helper/src/ci.rs6
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/await_holding_invalid.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/box_default.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/create_dir.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/default.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/exit.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/explicit_write.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/instant_subtraction.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_retain.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bytecount.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/open_options.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/non_canonical_impls.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs94
-rw-r--r--src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/unnamed_address.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_peekable.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/higher.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs16
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs48
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs6
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs4
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr4
-rw-r--r--src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10645.stderr4
-rw-r--r--src/tools/clippy/tests/ui/functions.stderr6
-rw-r--r--src/tools/clippy/tests/ui/future_not_send.stderr37
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs20
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr16
-rw-r--r--src/tools/clippy/tests/ui/must_use_unit.stderr4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr4
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/opt-dist/src/tests.rs2
-rw-r--r--src/tools/rustfmt/src/items.rs3
-rw-r--r--src/version2
-rw-r--r--tests/assembly/stack-protector/stack-protector-heuristics-effect.rs3
-rw-r--r--tests/codegen/issue-97217.rs22
-rw-r--r--tests/codegen/simd/simd-wide-sum.rs26
-rw-r--r--tests/codegen/unwind-landingpad-cold.rs16
-rw-r--r--tests/codegen/unwind-landingpad-inline.rs39
-rw-r--r--tests/coverage-map/status-quo/async.cov-map90
-rw-r--r--tests/coverage-map/status-quo/async2.cov-map28
-rw-r--r--tests/coverage-map/status-quo/closure.cov-map185
-rw-r--r--tests/coverage-map/status-quo/closure_bug.cov-map125
-rw-r--r--tests/coverage-map/status-quo/closure_macro.cov-map22
-rw-r--r--tests/coverage-map/status-quo/closure_macro_async.cov-map22
-rw-r--r--tests/coverage-map/status-quo/conditions.cov-map338
-rw-r--r--tests/coverage-map/status-quo/continue.cov-map74
-rw-r--r--tests/coverage-map/status-quo/dead_code.cov-map8
-rw-r--r--tests/coverage-map/status-quo/generator.cov-map39
-rw-r--r--tests/coverage-map/status-quo/inline-dead.cov-map12
-rw-r--r--tests/coverage-map/status-quo/inline.cov-map26
-rw-r--r--tests/coverage-map/status-quo/issue-93054.cov-map8
-rw-r--r--tests/coverage-map/status-quo/lazy_boolean.cov-map372
-rw-r--r--tests/coverage-map/status-quo/loops_branches.cov-map218
-rw-r--r--tests/coverage-map/status-quo/no_cov_crate.cov-map4
-rw-r--r--tests/coverage-map/status-quo/partial_eq.cov-map12
-rw-r--r--tests/coverage-map/status-quo/simple_loop.cov-map23
-rw-r--r--tests/coverage-map/status-quo/simple_match.cov-map31
-rw-r--r--tests/coverage-map/status-quo/test_harness.cov-map4
-rw-r--r--tests/coverage-map/status-quo/try_error_result.cov-map166
-rw-r--r--tests/coverage-map/status-quo/unused.cov-map16
-rw-r--r--tests/coverage-map/status-quo/yield.cov-map62
-rw-r--r--tests/coverage-map/unreachable.cov-map24
-rw-r--r--tests/coverage-map/unreachable.rs37
-rw-r--r--tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff2
-rw-r--r--tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff2
-rw-r--r--tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir4
-rw-r--r--tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff4
-rw-r--r--tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff4
-rw-r--r--tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff10
-rw-r--r--tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff10
-rw-r--r--tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff2
-rw-r--r--tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff2
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir4
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir4
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff2
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff2
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff2
-rw-r--r--tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff9
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir5
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir5
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir2
-rw-r--r--tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir16
-rw-r--r--tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff2
-rw-r--r--tests/run-coverage/unreachable.coverage38
-rw-r--r--tests/run-coverage/unreachable.rs37
-rw-r--r--tests/rustdoc-js/impl-trait.js19
-rw-r--r--tests/rustdoc-js/impl-trait.rs6
-rw-r--r--tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr2
-rw-r--r--tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr1
-rw-r--r--tests/rustdoc-ui/issues/issue-105742.stderr16
-rw-r--r--tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.rs7
-rw-r--r--tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr26
-rw-r--r--tests/rustdoc-ui/unescaped_backticks.stderr3
-rw-r--r--tests/rustdoc/anchor-id-duplicate-method-name-25001.rs (renamed from tests/rustdoc/issue-25001.rs)3
-rw-r--r--tests/rustdoc/anchor-id-trait-tymethod-28478.rs (renamed from tests/rustdoc/issue-28478.rs)3
-rw-r--r--tests/rustdoc/deduplicate-glob-import-impl-21474.rs (renamed from tests/rustdoc/issue-21474.rs)3
-rw-r--r--tests/rustdoc/deduplicate-trait-impl-22025.rs (renamed from tests/rustdoc/issue-22025.rs)3
-rw-r--r--tests/rustdoc/doctest-hide-empty-line-23106.rs10
-rw-r--r--tests/rustdoc/doctest-markdown-inline-parse-23744.rs (renamed from tests/rustdoc/issue-23744.rs)3
-rw-r--r--tests/rustdoc/doctest-multi-line-string-literal-25944.rs (renamed from tests/rustdoc/issue-25944.rs)3
-rw-r--r--tests/rustdoc/extern-fn-22038.rs (renamed from tests/rustdoc/issue-22038.rs)3
-rw-r--r--tests/rustdoc/ice-reexport-crate-root-28927.rs (renamed from tests/rustdoc/issue-28927.rs)3
-rw-r--r--tests/rustdoc/impl-assoc-type-21092.rs (renamed from tests/rustdoc/issue-21092.rs)3
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/fn-type.rs1
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs2
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/issue-21801.rs (renamed from tests/rustdoc/auxiliary/issue-21801.rs)0
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/issue-23207-1.rs (renamed from tests/rustdoc/auxiliary/issue-23207-1.rs)0
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/issue-23207-2.rs (renamed from tests/rustdoc/auxiliary/issue-23207-2.rs)0
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/issue-27362-aux.rs (renamed from tests/rustdoc/auxiliary/issue-27362-aux.rs)0
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs10
-rw-r--r--tests/rustdoc/inline_cross/const-fn-27362.rs (renamed from tests/rustdoc/issue-27362.rs)3
-rw-r--r--tests/rustdoc/inline_cross/deduplicate-inlined-items-23207.rs (renamed from tests/rustdoc/issue-23207.rs)3
-rw-r--r--tests/rustdoc/inline_cross/fn-type.rs12
-rw-r--r--tests/rustdoc/inline_cross/impl_trait.rs2
-rw-r--r--tests/rustdoc/inline_cross/non_lifetime_binders.rs13
-rw-r--r--tests/rustdoc/inline_cross/sugar-closure-crate-21801.rs (renamed from tests/rustdoc/issue-21801.rs)3
-rw-r--r--tests/rustdoc/issue-23106.rs7
-rw-r--r--tests/rustdoc/macro-doc-comment-23812.rs (renamed from tests/rustdoc/issue-23812.rs)3
-rw-r--r--tests/rustdoc/markdown-table-escape-pipe-27862.rs (renamed from tests/rustdoc/issue-27862.rs)3
-rw-r--r--tests/rustdoc/search-index-primitive-inherent-method-23511.rs (renamed from tests/rustdoc/issue-23511.rs)3
-rw-r--r--tests/rustdoc/src-link-external-macro-26606.rs (renamed from tests/rustdoc/issue-26606.rs)5
-rw-r--r--tests/rustdoc/src-mod-path-absolute-26995.rs (renamed from tests/rustdoc/issue-26995.rs)3
-rw-r--r--tests/rustdoc/staged-api-feature-issue-27759.rs (renamed from tests/rustdoc/issue-27759.rs)3
-rw-r--r--tests/rustdoc/strip-priv-imports-pass-27104.rs (renamed from tests/rustdoc/issue-27104.rs)3
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.stderr2
-rw-r--r--tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.stderr1
-rw-r--r--tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.stderr2
-rw-r--r--tests/ui-fulldeps/plugin/lint-tool-test.stderr12
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr2
-rw-r--r--tests/ui-fulldeps/stable-mir/crate-info.rs40
-rw-r--r--tests/ui/allocator/not-an-allocator.stderr3
-rw-r--r--tests/ui/associated-consts/defaults-not-assumed-fail.stderr1
-rw-r--r--tests/ui/associated-consts/issue-105330.stderr2
-rw-r--r--tests/ui/associated-inherent-types/issue-109789.stderr1
-rw-r--r--tests/ui/associated-type-bounds/duplicate.stderr12
-rw-r--r--tests/ui/associated-type-bounds/issue-71443-1.stderr2
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-param-2.stderr1
-rw-r--r--tests/ui/async-await/async-await-let-else.stderr2
-rw-r--r--tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr1
-rw-r--r--tests/ui/async-await/in-trait/async-associated-types.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr4
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-extra.rs1
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared.rs1
-rw-r--r--tests/ui/async-await/in-trait/async-example.rs3
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.stderr16
-rw-r--r--tests/ui/async-await/in-trait/async-generics.stderr16
-rw-r--r--tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs1
-rw-r--r--tests/ui/async-await/in-trait/async-lifetimes.rs1
-rw-r--r--tests/ui/async-await/in-trait/async-recursive-generic.stderr4
-rw-r--r--tests/ui/async-await/in-trait/async-recursive.stderr4
-rw-r--r--tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr8
-rw-r--r--tests/ui/async-await/in-trait/early-bound-1.rs1
-rw-r--r--tests/ui/async-await/in-trait/early-bound-2.rs1
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err2.rs2
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err2.stderr2
-rw-r--r--tests/ui/async-await/in-trait/implied-bounds.rs2
-rw-r--r--tests/ui/async-await/in-trait/issue-102138.rs2
-rw-r--r--tests/ui/async-await/in-trait/issue-102219.rs1
-rw-r--r--tests/ui/async-await/in-trait/issue-102310.rs1
-rw-r--r--tests/ui/async-await/in-trait/issue-104678.rs1
-rw-r--r--tests/ui/async-await/in-trait/missing-feature-flag.stderr12
-rw-r--r--tests/ui/async-await/in-trait/nested-rpit.rs1
-rw-r--r--tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs1
-rw-r--r--tests/ui/async-await/in-trait/warn.rs23
-rw-r--r--tests/ui/async-await/in-trait/warn.stderr20
-rw-r--r--tests/ui/async-await/issue-108572.fixed16
-rw-r--r--tests/ui/async-await/issue-108572.rs7
-rw-r--r--tests/ui/async-await/issue-108572.stderr9
-rw-r--r--tests/ui/async-await/issue-64130-3-other.stderr2
-rw-r--r--tests/ui/async-await/issues/issue-67893.stderr4
-rw-r--r--tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr8
-rw-r--r--tests/ui/async-await/partial-drop-partial-reinit.stderr2
-rw-r--r--tests/ui/async-await/pin-needed-to-poll.stderr8
-rw-r--r--tests/ui/async-await/recursive-async-impl-trait-type.stderr4
-rw-r--r--tests/ui/async-await/return-type-notation/issue-110963-early.stderr1
-rw-r--r--tests/ui/auto-traits/pre-cfg.rs8
-rw-r--r--tests/ui/auto-traits/pre-cfg.stderr13
-rw-r--r--tests/ui/block-result/block-must-not-have-result-res.stderr2
-rw-r--r--tests/ui/block-result/issue-20862.stderr2
-rw-r--r--tests/ui/block-result/issue-22645.stderr2
-rw-r--r--tests/ui/block-result/issue-5500.stderr2
-rw-r--r--tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr1
-rw-r--r--tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr2
-rw-r--r--tests/ui/closures/add_semicolon_non_block_closure.stderr2
-rw-r--r--tests/ui/closures/binder/implicit-return.stderr4
-rw-r--r--tests/ui/closures/binder/implicit-stuff.stderr4
-rw-r--r--tests/ui/codegen/issue-79865-llvm-miscompile.rs2
-rw-r--r--tests/ui/codemap_tests/tab.stderr2
-rw-r--r--tests/ui/compare-method/bad-self-type.stderr4
-rw-r--r--tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr1
-rw-r--r--tests/ui/const-generics/assoc_const_eq_diagnostic.stderr1
-rw-r--r--tests/ui/const-generics/issues/issue-74950.min.stderr4
-rw-r--r--tests/ui/const-generics/occurs-check/unused-substs-1.stderr2
-rw-r--r--tests/ui/consts/const-adt-align-mismatch.rs2
-rw-r--r--tests/ui/consts/const-err-late.stderr2
-rw-r--r--tests/ui/consts/const-eval/issue-44578.stderr1
-rw-r--r--tests/ui/consts/const-eval/nrvo.rs3
-rw-r--r--tests/ui/consts/const-eval/panic-assoc-never-type.stderr2
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr1
-rw-r--r--tests/ui/consts/const-eval/union-const-eval-field.rs2
-rw-r--r--tests/ui/consts/const-eval/union-const-eval-field.stderr8
-rw-r--r--tests/ui/consts/const_in_pattern/reject_non_structural.rs5
-rw-r--r--tests/ui/consts/const_in_pattern/reject_non_structural.stderr33
-rw-r--r--tests/ui/consts/enum-discr-type-err.stderr1
-rw-r--r--tests/ui/consts/fn_trait_refs.stderr10
-rw-r--r--tests/ui/consts/invalid-union.32bit.stderr2
-rw-r--r--tests/ui/consts/invalid-union.64bit.stderr2
-rw-r--r--tests/ui/consts/issue-102117.stderr1
-rw-r--r--tests/ui/consts/issue-17718-const-bad-values.stderr1
-rw-r--r--tests/ui/consts/miri_unleashed/assoc_const.stderr2
-rw-r--r--tests/ui/consts/miri_unleashed/assoc_const_2.stderr2
-rw-r--r--tests/ui/consts/uninhabited-const-issue-61744.stderr2
-rw-r--r--tests/ui/crate-loading/invalid-rlib.rs1
-rw-r--r--tests/ui/crate-loading/invalid-rlib.stderr1
-rw-r--r--tests/ui/debuginfo/sroa-fragment-debuginfo.rs2
-rw-r--r--tests/ui/deduplicate-diagnostics.duplicate.stderr4
-rw-r--r--tests/ui/deprecation/deprecation-sanity.stderr10
-rw-r--r--tests/ui/derives/deriving-bounds.stderr2
-rw-r--r--tests/ui/derives/deriving-meta-unknown-trait.stderr2
-rw-r--r--tests/ui/derives/deriving-primitive.stderr2
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr6
-rw-r--r--tests/ui/did_you_mean/auxiliary/doc-hidden-fields.rs6
-rw-r--r--tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs38
-rw-r--r--tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr27
-rw-r--r--tests/ui/did_you_mean/dont-suggest-hygienic-fields.rs47
-rw-r--r--tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr50
-rw-r--r--tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs24
-rw-r--r--tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr19
-rw-r--r--tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr4
-rw-r--r--tests/ui/error-codes/E0452.stderr6
-rw-r--r--tests/ui/error-codes/E0453.stderr2
-rw-r--r--tests/ui/error-codes/E0602.stderr2
-rw-r--r--tests/ui/error-codes/E0719.stderr2
-rw-r--r--tests/ui/error-codes/E0789.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-associated_type_bounds.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-lint-reasons.stderr1
-rw-r--r--tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.rs1
-rw-r--r--tests/ui/feature-gates/feature-gate-strict_provenance.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr2
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-derive-2.stderr6
-rw-r--r--tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr1
-rw-r--r--tests/ui/generic-associated-types/issue-91139.stderr2
-rw-r--r--tests/ui/generic-const-items/unsatisfied-bounds.stderr2
-rw-r--r--tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr1
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr1
-rw-r--r--tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr2
-rw-r--r--tests/ui/impl-trait/impl-subtyper.rs18
-rw-r--r--tests/ui/impl-trait/impl-subtyper2.rs7
-rw-r--r--tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs1
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-with-rpit.rs1
-rw-r--r--tests/ui/impl-trait/in-trait/default-body.rs1
-rw-r--r--tests/ui/impl-trait/in-trait/early.rs1
-rw-r--r--tests/ui/impl-trait/in-trait/refine.rs11
-rw-r--r--tests/ui/impl-trait/in-trait/refine.stderr4
-rw-r--r--tests/ui/impl-trait/in-trait/suggest-missing-item.fixed3
-rw-r--r--tests/ui/impl-trait/in-trait/suggest-missing-item.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/suggest-missing-item.stderr6
-rw-r--r--tests/ui/impl-trait/issue-55872-2.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-54600.rs2
-rw-r--r--tests/ui/impl-trait/issues/issue-54600.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-54840.rs2
-rw-r--r--tests/ui/impl-trait/issues/issue-54840.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-58504.rs2
-rw-r--r--tests/ui/impl-trait/issues/issue-58504.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-58956.rs4
-rw-r--r--tests/ui/impl-trait/issues/issue-58956.stderr4
-rw-r--r--tests/ui/impl-trait/issues/issue-62742.stderr5
-rw-r--r--tests/ui/impl-trait/issues/issue-70971.rs2
-rw-r--r--tests/ui/impl-trait/issues/issue-70971.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-79099.rs2
-rw-r--r--tests/ui/impl-trait/issues/issue-79099.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs4
-rw-r--r--tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr4
-rw-r--r--tests/ui/impl-trait/issues/issue-84919.rs2
-rw-r--r--tests/ui/impl-trait/issues/issue-84919.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-86642.rs2
-rw-r--r--tests/ui/impl-trait/issues/issue-86642.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-87295.rs2
-rw-r--r--tests/ui/impl-trait/issues/issue-87295.stderr2
-rw-r--r--tests/ui/impl-trait/nested_impl_trait.rs2
-rw-r--r--tests/ui/impl-trait/nested_impl_trait.stderr2
-rw-r--r--tests/ui/impl-trait/where-allowed.rs78
-rw-r--r--tests/ui/impl-trait/where-allowed.stderr78
-rw-r--r--tests/ui/imports/ambiguous-9.stderr1
-rw-r--r--tests/ui/imports/issue-55457.stderr2
-rw-r--r--tests/ui/indexing/index-help.stderr3
-rw-r--r--tests/ui/indexing/indexing-requires-a-uint.stderr3
-rw-r--r--tests/ui/integral-indexing.stderr24
-rw-r--r--tests/ui/issues/issue-33571.stderr1
-rw-r--r--tests/ui/issues/issue-34334.stderr3
-rw-r--r--tests/ui/issues/issue-40000.stderr1
-rw-r--r--tests/ui/issues/issue-45801.stderr1
-rw-r--r--tests/ui/issues/issue-46101.stderr2
-rw-r--r--tests/ui/issues/issue-47715.rs8
-rw-r--r--tests/ui/issues/issue-47715.stderr8
-rw-r--r--tests/ui/issues/issue-53251.stderr1
-rw-r--r--tests/ui/issues/issue-66667-function-cmp-cycle.stderr6
-rw-r--r--tests/ui/issues/issue-66923-show-error-for-correct-call.stderr6
-rw-r--r--tests/ui/iterators/invalid-iterator-chain.stderr6
-rw-r--r--tests/ui/lang-items/start_lang_item_args.missing_ret.stderr4
-rw-r--r--tests/ui/lifetimes/issue-105675.stderr1
-rw-r--r--tests/ui/limits/issue-55878.stderr1
-rw-r--r--tests/ui/lint/cli-unknown-force-warn.stderr2
-rw-r--r--tests/ui/lint/command-line-register-unknown-lint-tool.stderr1
-rw-r--r--tests/ui/lint/crate_level_only_lint.stderr12
-rw-r--r--tests/ui/lint/forbid-group-group-2.stderr8
-rw-r--r--tests/ui/lint/forbid-group-member.stderr2
-rw-r--r--tests/ui/lint/forbid-member-group.stderr2
-rw-r--r--tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr2
-rw-r--r--tests/ui/lint/force-warn/cap-lints-allow.stderr2
-rw-r--r--tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr2
-rw-r--r--tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr2
-rw-r--r--tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr2
-rw-r--r--tests/ui/lint/force-warn/warnings-lint-group.stderr2
-rw-r--r--tests/ui/lint/issue-80988.stderr2
-rw-r--r--tests/ui/lint/lint-forbid-attr.stderr2
-rw-r--r--tests/ui/lint/lint-forbid-cmdline.stderr1
-rw-r--r--tests/ui/lint/lint-malformed.stderr6
-rw-r--r--tests/ui/lint/lint-removed-cmdline-deny.stderr2
-rw-r--r--tests/ui/lint/lint-removed-cmdline.stderr2
-rw-r--r--tests/ui/lint/lint-renamed-cmdline-deny.stderr2
-rw-r--r--tests/ui/lint/lint-renamed-cmdline.stderr2
-rw-r--r--tests/ui/lint/lint-stability-deprecated.stderr6
-rw-r--r--tests/ui/lint/lint-unexported-no-mangle.stderr4
-rw-r--r--tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr4
-rw-r--r--tests/ui/lint/lint-unknown-lint-cmdline.stderr4
-rw-r--r--tests/ui/lint/must_not_suspend/gated.stderr2
-rw-r--r--tests/ui/lint/reasons-erroneous.rs28
-rw-r--r--tests/ui/lint/reasons-erroneous.stderr94
-rw-r--r--tests/ui/lint/reference_casting.rs8
-rw-r--r--tests/ui/lint/reference_casting.stderr60
-rw-r--r--tests/ui/lint/register-tool-lint.stderr1
-rw-r--r--tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs30
-rw-r--r--tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs8
-rw-r--r--tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr30
-rw-r--r--tests/ui/loops/loop-break-value.stderr2
-rw-r--r--tests/ui/lub-glb/old-lub-glb-object.stderr1
-rw-r--r--tests/ui/macros/builtin-std-paths-fail.stderr8
-rw-r--r--tests/ui/macros/meta-item-absolute-path.stderr2
-rw-r--r--tests/ui/macros/stringify.rs1
-rw-r--r--tests/ui/mismatched_types/issue-19109.stderr2
-rw-r--r--tests/ui/native-library-link-flags/modifiers-override.stderr2
-rw-r--r--tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr1
-rw-r--r--tests/ui/nll/closure-malformed-projection-input-issue-102800.stderr1
-rw-r--r--tests/ui/nll/issue-97997.stderr1
-rw-r--r--tests/ui/nll/missing-universe-cause-issue-114907.stderr3
-rw-r--r--tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr2
-rw-r--r--tests/ui/nll/type-check-pointer-comparisons.stderr4
-rw-r--r--tests/ui/nll/user-annotations/normalization-2.stderr2
-rw-r--r--tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr2
-rw-r--r--tests/ui/offset-of/offset-of-output-type.stderr2
-rw-r--r--tests/ui/on-unimplemented/impl-substs.stderr3
-rw-r--r--tests/ui/on-unimplemented/on-impl.stderr3
-rw-r--r--tests/ui/on-unimplemented/slice-index.stderr3
-rw-r--r--tests/ui/or-patterns/missing-bindings.stderr84
-rw-r--r--tests/ui/parser/attr-stmt-expr-attr-bad.stderr1
-rw-r--r--tests/ui/parser/issues/issue-84117.stderr3
-rw-r--r--tests/ui/parser/macro/macro-repeat.stderr2
-rw-r--r--tests/ui/parser/recover-quantified-closure.stderr4
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr2
-rw-r--r--tests/ui/pattern/patkind-litrange-no-expr.stderr2
-rw-r--r--tests/ui/pattern/usefulness/floats.rs40
-rw-r--r--tests/ui/pattern/usefulness/floats.stderr52
-rw-r--r--tests/ui/privacy/effective_visibilities.stderr4
-rw-r--r--tests/ui/privacy/effective_visibilities_full_priv.stderr2
-rw-r--r--tests/ui/privacy/privacy1.stderr1
-rw-r--r--tests/ui/proc-macro/issue-37788.stderr2
-rw-r--r--tests/ui/proc-macro/issue-75930-derive-cfg.stderr1
-rw-r--r--tests/ui/proc-macro/macro-namespace-reserved-2.stderr1
-rw-r--r--tests/ui/proc-macro/pretty-print-hack-show.local.stderr6
-rw-r--r--tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr6
-rw-r--r--tests/ui/proc-macro/resolve-error.stderr8
-rw-r--r--tests/ui/proc-macro/resolved-located-at.stderr2
-rw-r--r--tests/ui/proc-macro/span-preservation.stderr8
-rw-r--r--tests/ui/recursion_limit/empty.stderr2
-rw-r--r--tests/ui/recursion_limit/invalid_digit.stderr2
-rw-r--r--tests/ui/recursion_limit/overflow.stderr2
-rw-r--r--tests/ui/regions/regions-close-object-into-object-4.stderr1
-rw-r--r--tests/ui/regions/regions-close-object-into-object-5.stderr1
-rw-r--r--tests/ui/repr/repr-align-assign.stderr4
-rw-r--r--tests/ui/repr/repr-align.stderr12
-rw-r--r--tests/ui/resolve/issue-116164.rs19
-rw-r--r--tests/ui/resolve/issue-116164.stderr14
-rw-r--r--tests/ui/resolve/resolve-inconsistent-names.stderr42
-rw-r--r--tests/ui/return/return-struct.stderr4
-rw-r--r--tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr1
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs28
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr26
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr1
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs9
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr32
-rw-r--r--tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr1
-rw-r--r--tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr2
-rw-r--r--tests/ui/rust-2018/edition-lint-nested-paths.stderr2
-rw-r--r--tests/ui/rust-2018/edition-lint-paths.stderr2
-rw-r--r--tests/ui/rust-2018/uniform-paths/cross-crate.stderr1
-rw-r--r--tests/ui/rust-2018/uniform-paths/prelude-fail-2.stderr2
-rw-r--r--tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.aarch64.stderr2
-rw-r--r--tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.x86_64.stderr2
-rw-r--r--tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed3
-rw-r--r--tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr10
-rw-r--r--tests/ui/span/issue-39698.stderr34
-rw-r--r--tests/ui/str/str-idx.stderr9
-rw-r--r--tests/ui/str/str-mut-idx.stderr9
-rw-r--r--tests/ui/suggestions/impl-trait-missing-lifetime.stderr6
-rw-r--r--tests/ui/suggestions/issue-101623.stderr3
-rw-r--r--tests/ui/suggestions/issue-61963.stderr5
-rw-r--r--tests/ui/suggestions/issue-83892.stderr2
-rw-r--r--tests/ui/suggestions/missing-lifetime-specifier.stderr8
-rw-r--r--tests/ui/suggestions/return-closures.stderr4
-rw-r--r--tests/ui/suggestions/suggest-dereferencing-index.stderr3
-rw-r--r--tests/ui/suggestions/suggest-ret-on-async-w-late.fixed14
-rw-r--r--tests/ui/suggestions/suggest-ret-on-async-w-late.rs3
-rw-r--r--tests/ui/suggestions/suggest-ret-on-async-w-late.stderr4
-rw-r--r--tests/ui/tool-attributes/tool-attributes-misplaced-1.stderr2
-rw-r--r--tests/ui/tool_lints.stderr1
-rw-r--r--tests/ui/traits/associated_type_bound/impl-is-shadowed.rs21
-rw-r--r--tests/ui/traits/coercion-generic-bad.stderr1
-rw-r--r--tests/ui/traits/issue-38404.stderr1
-rw-r--r--tests/ui/traits/issue-59029-1.stderr2
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-rpit.rs16
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-rpit.stderr11
-rw-r--r--tests/ui/try-block/try-block-bad-type.stderr1
-rw-r--r--tests/ui/try-trait/bad-interconversion.stderr9
-rw-r--r--tests/ui/tuple/tuple-struct-fields/test2.stderr2
-rw-r--r--tests/ui/tuple/tuple-struct-fields/test3.stderr2
-rw-r--r--tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr1
-rw-r--r--tests/ui/type-alias-impl-trait/normalize-alias-type.rs32
-rw-r--r--tests/ui/type-alias-impl-trait/tait-normalize.rs14
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr2
-rw-r--r--tests/ui/type/subtyping-opaque-type.rs19
-rw-r--r--tests/ui/type/type-check/point-at-inference-issue-116155.rs17
-rw-r--r--tests/ui/type/type-check/point-at-inference-issue-116155.stderr18
-rw-r--r--tests/ui/typeck/issue-104513-ice.rs2
-rw-r--r--tests/ui/typeck/issue-104513-ice.stderr2
-rw-r--r--tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr2
-rw-r--r--tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr2
-rw-r--r--tests/ui/typeck/issue-91267.stderr2
-rw-r--r--tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr2
-rw-r--r--tests/ui/unknown-lint-tool-name.stderr2
-rw-r--r--tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr2
-rw-r--r--tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr2
-rw-r--r--tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr2
-rw-r--r--tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr2
-rw-r--r--tests/ui/use/use-super-global-path.stderr2
-rw-r--r--triagebot.toml7
-rwxr-xr-xx2
757 files changed, 6631 insertions, 4334 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4dcc9556965..4e599829097 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -21,6 +21,8 @@ name: CI
       - auto
       - try
       - try-perf
+      - automation/bors/try
+      - automation/bors/try-merge
       - master
   pull_request:
     branches:
@@ -264,9 +266,6 @@ jobs:
           - name: test-various
             os: ubuntu-20.04-8core-32gb
             env: {}
-          - name: wasm32
-            os: ubuntu-20.04-8core-32gb
-            env: {}
           - name: x86_64-gnu
             os: ubuntu-20.04-4core-16gb
             env: {}
@@ -542,7 +541,7 @@ jobs:
       ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
       AWS_REGION: us-west-1
       CACHE_DOMAIN: ci-caches.rust-lang.org
-    if: "github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'"
+    if: "github.event_name == 'push' && (((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust') || ((github.ref == 'refs/heads/automation/bors/try') && github.repository == 'rust-lang/rust'))"
     strategy:
       matrix:
         include:
diff --git a/.reuse/dep5 b/.reuse/dep5
index 5546a7cf391..245ed2659f9 100644
--- a/.reuse/dep5
+++ b/.reuse/dep5
@@ -25,6 +25,7 @@ Files: compiler/*
        README.md
        RELEASES.md
        rustfmt.toml
+       rust-bors.toml
        triagebot.toml
        x
        x.ps1
diff --git a/Cargo.lock b/Cargo.lock
index 7f91d12a419..60a8f77c07d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2009,9 +2009,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
 
 [[package]]
 name = "jemalloc-sys"
-version = "0.5.3+5.3.0-patched"
+version = "0.5.4+5.3.0-patched"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9bd5d616ea7ed58b571b2e209a65759664d7fb021a0819d7a790afc67e47ca1"
+checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2"
 dependencies = [
  "cc",
  "libc",
@@ -4473,6 +4473,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_feature",
  "rustc_fs_util",
+ "rustc_index",
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
diff --git a/README.md b/README.md
index 8a6c559b0b3..f0c45f341d8 100644
--- a/README.md
+++ b/README.md
@@ -116,7 +116,7 @@ See [the rustc-dev-guide for more info][sysllvm].
 #### Configure and Make
 
 This project provides a configure script and makefile (the latter of which just
-invokes `x.py`). `./configure` is the recommended way to programatically
+invokes `x.py`). `./configure` is the recommended way to programmatically
 generate a `config.toml`. `make` is not recommended (we suggest using `x.py`
 directly), but it is supported and we try not to break it unnecessarily.
 
diff --git a/RELEASES.md b/RELEASES.md
index d390f2b7f5e..e261294a032 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,120 @@
+Version 1.73.0 (2023-10-05)
+==========================
+
+<a id="1.73.0-Language"></a>
+
+Language
+--------
+
+- [Uplift `clippy::fn_null_check` lint as `useless_ptr_null_checks`.](https://github.com/rust-lang/rust/pull/111717/)
+- [Make `noop_method_call` warn by default.](https://github.com/rust-lang/rust/pull/111916/)
+- [Support interpolated block for `try` and `async` in macros.](https://github.com/rust-lang/rust/pull/112953/)
+- [Make `unconditional_recursion` lint detect recursive drops.](https://github.com/rust-lang/rust/pull/113902/)
+- [Future compatibility warning for some impls being incorrectly considered not overlapping.](https://github.com/rust-lang/rust/pull/114023/)
+- [The `invalid_reference_casting` lint is now **deny-by-default** (instead of allow-by-default)](https://github.com/rust-lang/rust/pull/112431)
+
+<a id="1.73.0-Compiler"></a>
+
+Compiler
+--------
+
+- [Write version information in a `.comment` section like GCC/Clang.](https://github.com/rust-lang/rust/pull/97550/)
+- [Add documentation on v0 symbol mangling.](https://github.com/rust-lang/rust/pull/97571/)
+- [Stabilize `extern "thiscall"` and `"thiscall-unwind"` ABIs.](https://github.com/rust-lang/rust/pull/114562/)
+- [Only check outlives goals on impl compared to trait.](https://github.com/rust-lang/rust/pull/109356/)
+- [Infer type in irrefutable slice patterns with fixed length as array.](https://github.com/rust-lang/rust/pull/113199/)
+- [Discard default auto trait impls if explicit ones exist.](https://github.com/rust-lang/rust/pull/113312/)
+- Add several new tier 3 targets:
+    - [`aarch64-unknown-teeos`](https://github.com/rust-lang/rust/pull/113480/)
+    - [`csky-unknown-linux-gnuabiv2`](https://github.com/rust-lang/rust/pull/113658/)
+    - [`riscv64-linux-android`](https://github.com/rust-lang/rust/pull/112858/)
+    - [`riscv64gc-unknown-hermit`](https://github.com/rust-lang/rust/pull/114004/)
+    - [`x86_64-unikraft-linux-musl`](https://github.com/rust-lang/rust/pull/113411/)
+    - [`x86_64-unknown-linux-ohos`](https://github.com/rust-lang/rust/pull/113061/)
+- [Add `wasm32-wasi-preview1-threads` as a tier 2 target.](https://github.com/rust-lang/rust/pull/112922/)
+
+Refer to Rust's [platform support page][platform-support-doc]
+for more information on Rust's tiered platform support.
+
+<a id="1.73.0-Libraries"></a>
+
+Libraries
+---------
+
+- [Add `Read`, `Write` and `Seek` impls for `Arc<File>`.](https://github.com/rust-lang/rust/pull/94748/)
+- [Merge functionality of `io::Sink` into `io::Empty`.](https://github.com/rust-lang/rust/pull/98154/)
+- [Implement `RefUnwindSafe` for `Backtrace`](https://github.com/rust-lang/rust/pull/100455/)
+- [Make `ExitStatus` implement `Default`](https://github.com/rust-lang/rust/pull/106425/)
+- [`impl SliceIndex<str> for (Bound<usize>, Bound<usize>)`](https://github.com/rust-lang/rust/pull/111081/)
+- [Change default panic handler message format.](https://github.com/rust-lang/rust/pull/112849/)
+- [Cleaner `assert_eq!` & `assert_ne!` panic messages.](https://github.com/rust-lang/rust/pull/111071/)
+- [Correct the (deprecated) Android `stat` struct definitions.](https://github.com/rust-lang/rust/pull/113130/)
+
+<a id="1.73.0-Stabilized-APIs"></a>
+
+Stabilized APIs
+---------------
+
+- [Unsigned `{integer}::div_ceil`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.div_ceil)
+- [Unsigned `{integer}::next_multiple_of`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.next_multiple_of)
+- [Unsigned `{integer}::checked_next_multiple_of`](https://doc.rust-lang.org/stable/std/primitive.u32.html#method.checked_next_multiple_of)
+- [`std::ffi::FromBytesUntilNulError`](https://doc.rust-lang.org/stable/std/ffi/struct.FromBytesUntilNulError.html)
+- [`std::os::unix::fs::chown`](https://doc.rust-lang.org/stable/std/os/unix/fs/fn.chown.html)
+- [`std::os::unix::fs::fchown`](https://doc.rust-lang.org/stable/std/os/unix/fs/fn.fchown.html)
+- [`std::os::unix::fs::lchown`](https://doc.rust-lang.org/stable/std/os/unix/fs/fn.lchown.html)
+- [`LocalKey::<Cell<T>>::get`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.get)
+- [`LocalKey::<Cell<T>>::set`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.set)
+- [`LocalKey::<Cell<T>>::take`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.take)
+- [`LocalKey::<Cell<T>>::replace`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.replace)
+- [`LocalKey::<RefCell<T>>::with_borrow`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.with_borrow)
+- [`LocalKey::<RefCell<T>>::with_borrow_mut`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.with_borrow_mut)
+- [`LocalKey::<RefCell<T>>::set`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.set-1)
+- [`LocalKey::<RefCell<T>>::take`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.take-1)
+- [`LocalKey::<RefCell<T>>::replace`](https://doc.rust-lang.org/stable/std/thread/struct.LocalKey.html#method.replace-1)
+
+These APIs are now stable in const contexts:
+
+- [`rc::Weak::new`](https://doc.rust-lang.org/stable/alloc/rc/struct.Weak.html#method.new)
+- [`sync::Weak::new`](https://doc.rust-lang.org/stable/alloc/sync/struct.Weak.html#method.new)
+- [`NonNull::as_ref`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.as_ref)
+
+<a id="1.73.0-Cargo"></a>
+
+Cargo
+-----
+
+- [Encode URL params correctly for `SourceId` in `Cargo.lock`.](https://github.com/rust-lang/cargo/pull/12280/)
+- [Bail out an error when using `cargo::` in custom build script.](https://github.com/rust-lang/cargo/pull/12332/)
+
+<a id="1.73.0-Misc"></a>
+
+Misc
+----
+
+<a id="1.73.0-Compatibility-Notes"></a>
+
+Compatibility Notes
+-------------------
+
+- [Update the minimum external LLVM to 15.](https://github.com/rust-lang/rust/pull/114148/)
+- [Check for non-defining uses of return position `impl Trait`.](https://github.com/rust-lang/rust/pull/112842/)
+
+<a id="1.73.0-Internal-Changes"></a>
+
+Internal Changes
+----------------
+
+These changes do not affect any public interfaces of Rust, but they represent
+significant improvements to the performance or internals of rustc and related
+tools.
+
+- [Remove LLVM pointee types, supporting only opaque pointers.](https://github.com/rust-lang/rust/pull/105545/)
+- [Port PGO/LTO/BOLT optimized build pipeline to Rust.](https://github.com/rust-lang/rust/pull/112235/)
+- [Replace in-tree `rustc_apfloat` with the new version of the crate.](https://github.com/rust-lang/rust/pull/113843/)
+- [Update to LLVM 17.](https://github.com/rust-lang/rust/pull/114048/)
+- [Add `internal_features` lint for internal unstable features.](https://github.com/rust-lang/rust/pull/108955/)
+- [Mention style for new syntax in tracking issue template.](https://github.com/rust-lang/rust/pull/113586/)
+
 Version 1.72.1 (2023-09-19)
 ===========================
 
diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml
index 48b199cb8ee..c43fd745e8f 100644
--- a/compiler/rustc_abi/Cargo.toml
+++ b/compiler/rustc_abi/Cargo.toml
@@ -15,7 +15,9 @@ rustc_serialize = { path = "../rustc_serialize", optional = true  }
 
 [features]
 default = ["nightly", "randomize"]
-randomize = ["rand", "rand_xoshiro"]
+randomize = ["rand", "rand_xoshiro", "nightly"]
+# rust-analyzer depends on this crate and we therefore require it to built on a stable toolchain
+# without depending on rustc_data_structures, rustc_macros and rustc_serialize
 nightly = [
     "rustc_data_structures",
     "rustc_index/nightly",
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 0706dc18f0e..00d862ca27b 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -1,21 +1,27 @@
-use super::*;
-use std::fmt::Write;
+use std::fmt::{self, Write};
+use std::ops::Deref;
 use std::{borrow::Borrow, cmp, iter, ops::Bound};
 
-#[cfg(feature = "randomize")]
-use rand::{seq::SliceRandom, SeedableRng};
-#[cfg(feature = "randomize")]
-use rand_xoshiro::Xoshiro128StarStar;
-
+use rustc_index::Idx;
 use tracing::debug;
 
+use crate::{
+    Abi, AbiAndPrefAlign, Align, FieldsShape, IndexSlice, IndexVec, Integer, LayoutS, Niche,
+    NonZeroUsize, Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding, TargetDataLayout,
+    Variants, WrappingRange,
+};
+
 pub trait LayoutCalculator {
     type TargetDataLayoutRef: Borrow<TargetDataLayout>;
 
     fn delay_bug(&self, txt: String);
     fn current_data_layout(&self) -> Self::TargetDataLayoutRef;
 
-    fn scalar_pair(&self, a: Scalar, b: Scalar) -> LayoutS {
+    fn scalar_pair<FieldIdx: Idx, VariantIdx: Idx>(
+        &self,
+        a: Scalar,
+        b: Scalar,
+    ) -> LayoutS<FieldIdx, VariantIdx> {
         let dl = self.current_data_layout();
         let dl = dl.borrow();
         let b_align = b.align(dl);
@@ -31,7 +37,7 @@ pub trait LayoutCalculator {
             .max_by_key(|niche| niche.available(dl));
 
         LayoutS {
-            variants: Variants::Single { index: FIRST_VARIANT },
+            variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Arbitrary {
                 offsets: [Size::ZERO, b_offset].into(),
                 memory_index: [0, 1].into(),
@@ -45,40 +51,45 @@ pub trait LayoutCalculator {
         }
     }
 
-    fn univariant(
+    fn univariant<
+        'a,
+        FieldIdx: Idx,
+        VariantIdx: Idx,
+        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug,
+    >(
         &self,
         dl: &TargetDataLayout,
-        fields: &IndexSlice<FieldIdx, Layout<'_>>,
+        fields: &IndexSlice<FieldIdx, F>,
         repr: &ReprOptions,
         kind: StructKind,
-    ) -> Option<LayoutS> {
+    ) -> Option<LayoutS<FieldIdx, VariantIdx>> {
         let layout = univariant(self, dl, fields, repr, kind, NicheBias::Start);
-        // Enums prefer niches close to the beginning or the end of the variants so that other (smaller)
-        // data-carrying variants can be packed into the space after/before the niche.
+        // Enums prefer niches close to the beginning or the end of the variants so that other
+        // (smaller) data-carrying variants can be packed into the space after/before the niche.
         // If the default field ordering does not give us a niche at the front then we do a second
-        // run and bias niches to the right and then check which one is closer to one of the struct's
-        // edges.
+        // run and bias niches to the right and then check which one is closer to one of the
+        // struct's edges.
         if let Some(layout) = &layout {
             // Don't try to calculate an end-biased layout for unsizable structs,
             // otherwise we could end up with different layouts for
-            // Foo<Type> and Foo<dyn Trait> which would break unsizing
+            // Foo<Type> and Foo<dyn Trait> which would break unsizing.
             if !matches!(kind, StructKind::MaybeUnsized) {
                 if let Some(niche) = layout.largest_niche {
                     let head_space = niche.offset.bytes();
-                    let niche_length = niche.value.size(dl).bytes();
-                    let tail_space = layout.size.bytes() - head_space - niche_length;
+                    let niche_len = niche.value.size(dl).bytes();
+                    let tail_space = layout.size.bytes() - head_space - niche_len;
 
-                    // This may end up doing redundant work if the niche is already in the last field
-                    // (e.g. a trailing bool) and there is tail padding. But it's non-trivial to get
-                    // the unpadded size so we try anyway.
+                    // This may end up doing redundant work if the niche is already in the last
+                    // field (e.g. a trailing bool) and there is tail padding. But it's non-trivial
+                    // to get the unpadded size so we try anyway.
                     if fields.len() > 1 && head_space != 0 && tail_space > 0 {
                         let alt_layout = univariant(self, dl, fields, repr, kind, NicheBias::End)
                             .expect("alt layout should always work");
-                        let niche = alt_layout
+                        let alt_niche = alt_layout
                             .largest_niche
                             .expect("alt layout should have a niche like the regular one");
-                        let alt_head_space = niche.offset.bytes();
-                        let alt_niche_len = niche.value.size(dl).bytes();
+                        let alt_head_space = alt_niche.offset.bytes();
+                        let alt_niche_len = alt_niche.value.size(dl).bytes();
                         let alt_tail_space =
                             alt_layout.size.bytes() - alt_head_space - alt_niche_len;
 
@@ -93,7 +104,7 @@ pub trait LayoutCalculator {
                             alt_layout: {}\n",
                             layout.size.bytes(),
                             head_space,
-                            niche_length,
+                            niche_len,
                             tail_space,
                             alt_head_space,
                             alt_niche_len,
@@ -114,11 +125,13 @@ pub trait LayoutCalculator {
         layout
     }
 
-    fn layout_of_never_type(&self) -> LayoutS {
+    fn layout_of_never_type<FieldIdx: Idx, VariantIdx: Idx>(
+        &self,
+    ) -> LayoutS<FieldIdx, VariantIdx> {
         let dl = self.current_data_layout();
         let dl = dl.borrow();
         LayoutS {
-            variants: Variants::Single { index: FIRST_VARIANT },
+            variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Primitive,
             abi: Abi::Uninhabited,
             largest_niche: None,
@@ -129,10 +142,15 @@ pub trait LayoutCalculator {
         }
     }
 
-    fn layout_of_struct_or_enum(
+    fn layout_of_struct_or_enum<
+        'a,
+        FieldIdx: Idx,
+        VariantIdx: Idx,
+        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug,
+    >(
         &self,
         repr: &ReprOptions,
-        variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, Layout<'_>>>,
+        variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
         is_enum: bool,
         is_unsafe_cell: bool,
         scalar_valid_range: (Bound<u128>, Bound<u128>),
@@ -140,7 +158,7 @@ pub trait LayoutCalculator {
         discriminants: impl Iterator<Item = (VariantIdx, i128)>,
         dont_niche_optimize_enum: bool,
         always_sized: bool,
-    ) -> Option<LayoutS> {
+    ) -> Option<LayoutS<FieldIdx, VariantIdx>> {
         let dl = self.current_data_layout();
         let dl = dl.borrow();
 
@@ -155,11 +173,11 @@ pub trait LayoutCalculator {
         // but *not* an encoding of the discriminant (e.g., a tag value).
         // See issue #49298 for more details on the need to leave space
         // for non-ZST uninhabited data (mostly partial initialization).
-        let absent = |fields: &IndexSlice<FieldIdx, Layout<'_>>| {
-            let uninhabited = fields.iter().any(|f| f.abi().is_uninhabited());
+        let absent = |fields: &IndexSlice<FieldIdx, F>| {
+            let uninhabited = fields.iter().any(|f| f.abi.is_uninhabited());
             // We cannot ignore alignment; that might lead us to entirely discard a variant and
             // produce an enum that is less aligned than it should be!
-            let is_1zst = fields.iter().all(|f| f.0.is_1zst());
+            let is_1zst = fields.iter().all(|f| f.is_1zst());
             uninhabited && is_1zst
         };
         let (present_first, present_second) = {
@@ -176,7 +194,7 @@ pub trait LayoutCalculator {
             }
             // If it's a struct, still compute a layout so that we can still compute the
             // field offsets.
-            None => FIRST_VARIANT,
+            None => VariantIdx::new(0),
         };
 
         let is_struct = !is_enum ||
@@ -279,12 +297,12 @@ pub trait LayoutCalculator {
         // variant layouts, so we can't store them in the
         // overall LayoutS. Store the overall LayoutS
         // and the variant LayoutSs here until then.
-        struct TmpLayout {
-            layout: LayoutS,
-            variants: IndexVec<VariantIdx, LayoutS>,
+        struct TmpLayout<FieldIdx: Idx, VariantIdx: Idx> {
+            layout: LayoutS<FieldIdx, VariantIdx>,
+            variants: IndexVec<VariantIdx, LayoutS<FieldIdx, VariantIdx>>,
         }
 
-        let calculate_niche_filling_layout = || -> Option<TmpLayout> {
+        let calculate_niche_filling_layout = || -> Option<TmpLayout<FieldIdx, VariantIdx>> {
             if dont_niche_optimize_enum {
                 return None;
             }
@@ -322,13 +340,14 @@ pub trait LayoutCalculator {
             let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap()
                 ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap();
 
-            let count = niche_variants.size_hint().1.unwrap() as u128;
+            let count =
+                (niche_variants.end().index() as u128 - niche_variants.start().index() as u128) + 1;
 
             // Find the field with the largest niche
             let (field_index, niche, (niche_start, niche_scalar)) = variants[largest_variant_index]
                 .iter()
                 .enumerate()
-                .filter_map(|(j, field)| Some((j, field.largest_niche()?)))
+                .filter_map(|(j, field)| Some((j, field.largest_niche?)))
                 .max_by_key(|(_, niche)| niche.available(dl))
                 .and_then(|(j, niche)| Some((j, niche, niche.reserve(dl, count)?)))?;
             let niche_offset =
@@ -443,7 +462,7 @@ pub trait LayoutCalculator {
         let discr_type = repr.discr_type();
         let bits = Integer::from_attr(dl, discr_type).size().bits();
         for (i, mut val) in discriminants {
-            if variants[i].iter().any(|f| f.abi().is_uninhabited()) {
+            if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
                 continue;
             }
             if discr_type.is_signed() {
@@ -484,7 +503,7 @@ pub trait LayoutCalculator {
         if repr.c() {
             for fields in variants {
                 for field in fields {
-                    prefix_align = prefix_align.max(field.align().abi);
+                    prefix_align = prefix_align.max(field.align.abi);
                 }
             }
         }
@@ -503,9 +522,9 @@ pub trait LayoutCalculator {
                 // Find the first field we can't move later
                 // to make room for a larger discriminant.
                 for field_idx in st.fields.index_by_increasing_offset() {
-                    let field = &field_layouts[FieldIdx::from_usize(field_idx)];
-                    if !field.0.is_1zst() {
-                        start_align = start_align.min(field.align().abi);
+                    let field = &field_layouts[FieldIdx::new(field_idx)];
+                    if !field.is_1zst() {
+                        start_align = start_align.min(field.align.abi);
                         break;
                     }
                 }
@@ -587,7 +606,7 @@ pub trait LayoutCalculator {
 
         let tag_mask = ity.size().unsigned_int_max();
         let tag = Scalar::Initialized {
-            value: Int(ity, signed),
+            value: Primitive::Int(ity, signed),
             valid_range: WrappingRange {
                 start: (min as u128 & tag_mask),
                 end: (max as u128 & tag_mask),
@@ -612,7 +631,7 @@ pub trait LayoutCalculator {
                 };
                 // We skip *all* ZST here and later check if we are good in terms of alignment.
                 // This lets us handle some cases involving aligned ZST.
-                let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.0.is_zst());
+                let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst());
                 let (field, offset) = match (fields.next(), fields.next()) {
                     (None, None) => {
                         common_prim_initialized_in_all_variants = false;
@@ -624,7 +643,7 @@ pub trait LayoutCalculator {
                         break;
                     }
                 };
-                let prim = match field.abi() {
+                let prim = match field.abi {
                     Abi::Scalar(scalar) => {
                         common_prim_initialized_in_all_variants &=
                             matches!(scalar, Scalar::Initialized { .. });
@@ -655,7 +674,7 @@ pub trait LayoutCalculator {
                     // Common prim might be uninit.
                     Scalar::Union { value: prim }
                 };
-                let pair = self.scalar_pair(tag, prim_scalar);
+                let pair = self.scalar_pair::<FieldIdx, VariantIdx>(tag, prim_scalar);
                 let pair_offsets = match pair.fields {
                     FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
                         assert_eq!(memory_index.raw, [0, 1]);
@@ -663,8 +682,8 @@ pub trait LayoutCalculator {
                     }
                     _ => panic!(),
                 };
-                if pair_offsets[FieldIdx::from_u32(0)] == Size::ZERO
-                    && pair_offsets[FieldIdx::from_u32(1)] == *offset
+                if pair_offsets[FieldIdx::new(0)] == Size::ZERO
+                    && pair_offsets[FieldIdx::new(1)] == *offset
                     && align == pair.align
                     && size == pair.size
                 {
@@ -684,7 +703,8 @@ pub trait LayoutCalculator {
                 // Also do not overwrite any already existing "clever" ABIs.
                 if variant.fields.count() > 0 && matches!(variant.abi, Abi::Aggregate { .. }) {
                     variant.abi = abi;
-                    // Also need to bump up the size and alignment, so that the entire value fits in here.
+                    // Also need to bump up the size and alignment, so that the entire value fits
+                    // in here.
                     variant.size = cmp::max(variant.size, size);
                     variant.align.abi = cmp::max(variant.align.abi, align.abi);
                 }
@@ -720,8 +740,9 @@ pub trait LayoutCalculator {
                 // pick the layout with the larger niche; otherwise,
                 // pick tagged as it has simpler codegen.
                 use cmp::Ordering::*;
-                let niche_size =
-                    |tmp_l: &TmpLayout| tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl));
+                let niche_size = |tmp_l: &TmpLayout<FieldIdx, VariantIdx>| {
+                    tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl))
+                };
                 match (tl.layout.size.cmp(&nl.layout.size), niche_size(&tl).cmp(&niche_size(&nl))) {
                     (Greater, _) => nl,
                     (Equal, Less) => nl,
@@ -741,11 +762,16 @@ pub trait LayoutCalculator {
         Some(best_layout.layout)
     }
 
-    fn layout_of_union(
+    fn layout_of_union<
+        'a,
+        FieldIdx: Idx,
+        VariantIdx: Idx,
+        F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug,
+    >(
         &self,
         repr: &ReprOptions,
-        variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, Layout<'_>>>,
-    ) -> Option<LayoutS> {
+        variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
+    ) -> Option<LayoutS<FieldIdx, VariantIdx>> {
         let dl = self.current_data_layout();
         let dl = dl.borrow();
         let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
@@ -762,24 +788,24 @@ pub trait LayoutCalculator {
         };
 
         let mut size = Size::ZERO;
-        let only_variant = &variants[FIRST_VARIANT];
+        let only_variant = &variants[VariantIdx::new(0)];
         for field in only_variant {
-            if field.0.is_unsized() {
+            if field.is_unsized() {
                 self.delay_bug("unsized field in union".to_string());
             }
 
-            align = align.max(field.align());
-            max_repr_align = max_repr_align.max(field.max_repr_align());
-            size = cmp::max(size, field.size());
+            align = align.max(field.align);
+            max_repr_align = max_repr_align.max(field.max_repr_align);
+            size = cmp::max(size, field.size);
 
-            if field.0.is_zst() {
+            if field.is_zst() {
                 // Nothing more to do for ZST fields
                 continue;
             }
 
             if let Ok(common) = common_non_zst_abi_and_align {
                 // Discard valid range information and allow undef
-                let field_abi = field.abi().to_union();
+                let field_abi = field.abi.to_union();
 
                 if let Some((common_abi, common_align)) = common {
                     if common_abi != field_abi {
@@ -790,15 +816,14 @@ pub trait LayoutCalculator {
                         // have the same alignment
                         if !matches!(common_abi, Abi::Aggregate { .. }) {
                             assert_eq!(
-                                common_align,
-                                field.align().abi,
+                                common_align, field.align.abi,
                                 "non-Aggregate field with matching ABI but differing alignment"
                             );
                         }
                     }
                 } else {
                     // First non-ZST field: record its ABI and alignment
-                    common_non_zst_abi_and_align = Ok(Some((field_abi, field.align().abi)));
+                    common_non_zst_abi_and_align = Ok(Some((field_abi, field.align.abi)));
                 }
             }
         }
@@ -830,7 +855,7 @@ pub trait LayoutCalculator {
         };
 
         Some(LayoutS {
-            variants: Variants::Single { index: FIRST_VARIANT },
+            variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Union(NonZeroUsize::new(only_variant.len())?),
             abi,
             largest_niche: None,
@@ -848,14 +873,19 @@ enum NicheBias {
     End,
 }
 
-fn univariant(
+fn univariant<
+    'a,
+    FieldIdx: Idx,
+    VariantIdx: Idx,
+    F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug,
+>(
     this: &(impl LayoutCalculator + ?Sized),
     dl: &TargetDataLayout,
-    fields: &IndexSlice<FieldIdx, Layout<'_>>,
+    fields: &IndexSlice<FieldIdx, F>,
     repr: &ReprOptions,
     kind: StructKind,
     niche_bias: NicheBias,
-) -> Option<LayoutS> {
+) -> Option<LayoutS<FieldIdx, VariantIdx>> {
     let pack = repr.pack;
     let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
     let mut max_repr_align = repr.align;
@@ -868,15 +898,18 @@ fn univariant(
 
         // If `-Z randomize-layout` was enabled for the type definition we can shuffle
         // the field ordering to try and catch some code making assumptions about layouts
-        // we don't guarantee
+        // we don't guarantee.
         if repr.can_randomize_type_layout() && cfg!(feature = "randomize") {
             #[cfg(feature = "randomize")]
             {
-                // `ReprOptions.layout_seed` is a deterministic seed that we can use to
-                // randomize field ordering with
-                let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed.as_u64());
-
-                // Shuffle the ordering of the fields
+                use rand::{seq::SliceRandom, SeedableRng};
+                // `ReprOptions.layout_seed` is a deterministic seed we can use to randomize field
+                // ordering.
+                let mut rng = rand_xoshiro::Xoshiro128StarStar::seed_from_u64(
+                    repr.field_shuffle_seed.as_u64(),
+                );
+
+                // Shuffle the ordering of the fields.
                 optimizing.shuffle(&mut rng);
             }
             // Otherwise we just leave things alone and actually optimize the type's fields
@@ -884,35 +917,34 @@ fn univariant(
             // To allow unsizing `&Foo<Type>` -> `&Foo<dyn Trait>`, the layout of the struct must
             // not depend on the layout of the tail.
             let max_field_align =
-                fields_excluding_tail.iter().map(|f| f.align().abi.bytes()).max().unwrap_or(1);
+                fields_excluding_tail.iter().map(|f| f.align.abi.bytes()).max().unwrap_or(1);
             let largest_niche_size = fields_excluding_tail
                 .iter()
-                .filter_map(|f| f.largest_niche())
+                .filter_map(|f| f.largest_niche)
                 .map(|n| n.available(dl))
                 .max()
                 .unwrap_or(0);
 
-            // Calculates a sort key to group fields by their alignment or possibly some size-derived
-            // pseudo-alignment.
-            let alignment_group_key = |layout: Layout<'_>| {
+            // Calculates a sort key to group fields by their alignment or possibly some
+            // size-derived pseudo-alignment.
+            let alignment_group_key = |layout: &F| {
                 if let Some(pack) = pack {
-                    // return the packed alignment in bytes
-                    layout.align().abi.min(pack).bytes()
+                    // Return the packed alignment in bytes.
+                    layout.align.abi.min(pack).bytes()
                 } else {
-                    // returns log2(effective-align).
-                    // This is ok since `pack` applies to all fields equally.
-                    // The calculation assumes that size is an integer multiple of align, except for ZSTs.
-                    //
-                    let align = layout.align().abi.bytes();
-                    let size = layout.size().bytes();
-                    let niche_size = layout.largest_niche().map(|n| n.available(dl)).unwrap_or(0);
-                    // group [u8; 4] with align-4 or [u8; 6] with align-2 fields
+                    // Returns `log2(effective-align)`. This is ok since `pack` applies to all
+                    // fields equally. The calculation assumes that size is an integer multiple of
+                    // align, except for ZSTs.
+                    let align = layout.align.abi.bytes();
+                    let size = layout.size.bytes();
+                    let niche_size = layout.largest_niche.map(|n| n.available(dl)).unwrap_or(0);
+                    // Group [u8; 4] with align-4 or [u8; 6] with align-2 fields.
                     let size_as_align = align.max(size).trailing_zeros();
                     let size_as_align = if largest_niche_size > 0 {
                         match niche_bias {
-                            // Given `A(u8, [u8; 16])` and `B(bool, [u8; 16])` we want to bump the array
-                            // to the front in the first case (for aligned loads) but keep the bool in front
-                            // in the second case for its niches.
+                            // Given `A(u8, [u8; 16])` and `B(bool, [u8; 16])` we want to bump the
+                            // array to the front in the first case (for aligned loads) but keep
+                            // the bool in front in the second case for its niches.
                             NicheBias::Start => max_field_align.trailing_zeros().min(size_as_align),
                             // When moving niches towards the end of the struct then for
                             // A((u8, u8, u8, bool), (u8, bool, u8)) we want to keep the first tuple
@@ -931,18 +963,18 @@ fn univariant(
 
             match kind {
                 StructKind::AlwaysSized | StructKind::MaybeUnsized => {
-                    // Currently `LayoutS` only exposes a single niche so sorting is usually sufficient
-                    // to get one niche into the preferred position. If it ever supported multiple niches
-                    // then a more advanced pick-and-pack approach could provide better results.
-                    // But even for the single-niche cache it's not optimal. E.g. for
-                    // A(u32, (bool, u8), u16) it would be possible to move the bool to the front
-                    // but it would require packing the tuple together with the u16 to build a 4-byte
-                    // group so that the u32 can be placed after it without padding. This kind
-                    // of packing can't be achieved by sorting.
+                    // Currently `LayoutS` only exposes a single niche so sorting is usually
+                    // sufficient to get one niche into the preferred position. If it ever
+                    // supported multiple niches then a more advanced pick-and-pack approach could
+                    // provide better results. But even for the single-niche cache it's not
+                    // optimal. E.g. for A(u32, (bool, u8), u16) it would be possible to move the
+                    // bool to the front but it would require packing the tuple together with the
+                    // u16 to build a 4-byte group so that the u32 can be placed after it without
+                    // padding. This kind of packing can't be achieved by sorting.
                     optimizing.sort_by_key(|&x| {
-                        let f = fields[x];
-                        let field_size = f.size().bytes();
-                        let niche_size = f.largest_niche().map_or(0, |n| n.available(dl));
+                        let f = &fields[x];
+                        let field_size = f.size.bytes();
+                        let niche_size = f.largest_niche.map_or(0, |n| n.available(dl));
                         let niche_size_key = match niche_bias {
                             // large niche first
                             NicheBias::Start => !niche_size,
@@ -950,8 +982,8 @@ fn univariant(
                             NicheBias::End => niche_size,
                         };
                         let inner_niche_offset_key = match niche_bias {
-                            NicheBias::Start => f.largest_niche().map_or(0, |n| n.offset.bytes()),
-                            NicheBias::End => f.largest_niche().map_or(0, |n| {
+                            NicheBias::Start => f.largest_niche.map_or(0, |n| n.offset.bytes()),
+                            NicheBias::End => f.largest_niche.map_or(0, |n| {
                                 !(field_size - n.value.size(dl).bytes() - n.offset.bytes())
                             }),
                         };
@@ -975,8 +1007,8 @@ fn univariant(
                     // And put the largest niche in an alignment group at the end
                     // so it can be used as discriminant in jagged enums
                     optimizing.sort_by_key(|&x| {
-                        let f = fields[x];
-                        let niche_size = f.largest_niche().map_or(0, |n| n.available(dl));
+                        let f = &fields[x];
+                        let niche_size = f.largest_niche.map_or(0, |n| n.available(dl));
                         (alignment_group_key(f), niche_size)
                     });
                 }
@@ -1012,24 +1044,24 @@ fn univariant(
             ));
         }
 
-        if field.0.is_unsized() {
+        if field.is_unsized() {
             sized = false;
         }
 
         // Invariant: offset < dl.obj_size_bound() <= 1<<61
         let field_align = if let Some(pack) = pack {
-            field.align().min(AbiAndPrefAlign::new(pack))
+            field.align.min(AbiAndPrefAlign::new(pack))
         } else {
-            field.align()
+            field.align
         };
         offset = offset.align_to(field_align.abi);
         align = align.max(field_align);
-        max_repr_align = max_repr_align.max(field.max_repr_align());
+        max_repr_align = max_repr_align.max(field.max_repr_align);
 
         debug!("univariant offset: {:?} field: {:#?}", offset, field);
         offsets[i] = offset;
 
-        if let Some(mut niche) = field.largest_niche() {
+        if let Some(mut niche) = field.largest_niche {
             let available = niche.available(dl);
             // Pick up larger niches.
             let prefer_new_niche = match niche_bias {
@@ -1044,7 +1076,7 @@ fn univariant(
             }
         }
 
-        offset = offset.checked_add(field.size(), dl)?;
+        offset = offset.checked_add(field.size, dl)?;
     }
 
     // The unadjusted ABI alignment does not include repr(align), but does include repr(pack).
@@ -1068,7 +1100,7 @@ fn univariant(
         inverse_memory_index.invert_bijective_mapping()
     } else {
         debug_assert!(inverse_memory_index.iter().copied().eq(fields.indices()));
-        inverse_memory_index.into_iter().map(FieldIdx::as_u32).collect()
+        inverse_memory_index.into_iter().map(|it| it.index() as u32).collect()
     };
     let size = min_size.align_to(align.abi);
     let mut layout_of_single_non_zst_field = None;
@@ -1077,7 +1109,7 @@ fn univariant(
     if sized && size.bytes() > 0 {
         // We skip *all* ZST here and later check if we are good in terms of alignment.
         // This lets us handle some cases involving aligned ZST.
-        let mut non_zst_fields = fields.iter_enumerated().filter(|&(_, f)| !f.0.is_zst());
+        let mut non_zst_fields = fields.iter_enumerated().filter(|&(_, f)| !f.is_zst());
 
         match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
             // We have exactly one non-ZST field.
@@ -1085,18 +1117,17 @@ fn univariant(
                 layout_of_single_non_zst_field = Some(field);
 
                 // Field fills the struct and it has a scalar or scalar pair ABI.
-                if offsets[i].bytes() == 0 && align.abi == field.align().abi && size == field.size()
-                {
-                    match field.abi() {
+                if offsets[i].bytes() == 0 && align.abi == field.align.abi && size == field.size {
+                    match field.abi {
                         // For plain scalars, or vectors of them, we can't unpack
                         // newtypes for `#[repr(C)]`, as that affects C ABIs.
                         Abi::Scalar(_) | Abi::Vector { .. } if optimize => {
-                            abi = field.abi();
+                            abi = field.abi;
                         }
                         // But scalar pairs are Rust-specific and get
                         // treated as aggregates by C ABIs anyway.
                         Abi::ScalarPair(..) => {
-                            abi = field.abi();
+                            abi = field.abi;
                         }
                         _ => {}
                     }
@@ -1105,7 +1136,7 @@ fn univariant(
 
             // Two non-ZST fields, and they're both scalars.
             (Some((i, a)), Some((j, b)), None) => {
-                match (a.abi(), b.abi()) {
+                match (a.abi, b.abi) {
                     (Abi::Scalar(a), Abi::Scalar(b)) => {
                         // Order by the memory placement, not source order.
                         let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
@@ -1113,7 +1144,7 @@ fn univariant(
                         } else {
                             ((j, b), (i, a))
                         };
-                        let pair = this.scalar_pair(a, b);
+                        let pair = this.scalar_pair::<FieldIdx, VariantIdx>(a, b);
                         let pair_offsets = match pair.fields {
                             FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
                                 assert_eq!(memory_index.raw, [0, 1]);
@@ -1121,8 +1152,8 @@ fn univariant(
                             }
                             _ => panic!(),
                         };
-                        if offsets[i] == pair_offsets[FieldIdx::from_usize(0)]
-                            && offsets[j] == pair_offsets[FieldIdx::from_usize(1)]
+                        if offsets[i] == pair_offsets[FieldIdx::new(0)]
+                            && offsets[j] == pair_offsets[FieldIdx::new(1)]
                             && align == pair.align
                             && size == pair.size
                         {
@@ -1138,13 +1169,13 @@ fn univariant(
             _ => {}
         }
     }
-    if fields.iter().any(|f| f.abi().is_uninhabited()) {
+    if fields.iter().any(|f| f.abi.is_uninhabited()) {
         abi = Abi::Uninhabited;
     }
 
     let unadjusted_abi_align = if repr.transparent() {
         match layout_of_single_non_zst_field {
-            Some(l) => l.unadjusted_abi_align(),
+            Some(l) => l.unadjusted_abi_align,
             None => {
                 // `repr(transparent)` with all ZST fields.
                 align.abi
@@ -1155,7 +1186,7 @@ fn univariant(
     };
 
     Some(LayoutS {
-        variants: Variants::Single { index: FIRST_VARIANT },
+        variants: Variants::Single { index: VariantIdx::new(0) },
         fields: FieldsShape::Arbitrary { offsets, memory_index },
         abi,
         largest_niche,
@@ -1166,17 +1197,22 @@ fn univariant(
     })
 }
 
-fn format_field_niches(
-    layout: &LayoutS,
-    fields: &IndexSlice<FieldIdx, Layout<'_>>,
+fn format_field_niches<
+    'a,
+    FieldIdx: Idx,
+    VariantIdx: Idx,
+    F: Deref<Target = &'a LayoutS<FieldIdx, VariantIdx>> + fmt::Debug,
+>(
+    layout: &LayoutS<FieldIdx, VariantIdx>,
+    fields: &IndexSlice<FieldIdx, F>,
     dl: &TargetDataLayout,
 ) -> String {
     let mut s = String::new();
     for i in layout.fields.index_by_increasing_offset() {
         let offset = layout.fields.offset(i);
-        let f = fields[i.into()];
-        write!(s, "[o{}a{}s{}", offset.bytes(), f.align().abi.bytes(), f.size().bytes()).unwrap();
-        if let Some(n) = f.largest_niche() {
+        let f = &fields[FieldIdx::new(i)];
+        write!(s, "[o{}a{}s{}", offset.bytes(), f.align.abi.bytes(), f.size.bytes()).unwrap();
+        if let Some(n) = f.largest_niche {
             write!(
                 s,
                 " n{}b{}s{}",
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index b30ff058a30..45b3e76cca6 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1,23 +1,22 @@
-#![cfg_attr(feature = "nightly", feature(step_trait, rustc_attrs, min_specialization))]
+#![cfg_attr(feature = "nightly", feature(step_trait))]
 #![cfg_attr(feature = "nightly", allow(internal_features))]
 
 use std::fmt;
-#[cfg(feature = "nightly")]
-use std::iter::Step;
 use std::num::{NonZeroUsize, ParseIntError};
 use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
 use std::str::FromStr;
 
 use bitflags::bitflags;
-use rustc_data_structures::intern::Interned;
-use rustc_data_structures::stable_hasher::Hash64;
+use rustc_index::{Idx, IndexSlice, IndexVec};
+
 #[cfg(feature = "nightly")]
 use rustc_data_structures::stable_hasher::StableOrd;
-use rustc_index::{IndexSlice, IndexVec};
 #[cfg(feature = "nightly")]
 use rustc_macros::HashStable_Generic;
 #[cfg(feature = "nightly")]
 use rustc_macros::{Decodable, Encodable};
+#[cfg(feature = "nightly")]
+use std::iter::Step;
 
 mod layout;
 
@@ -28,9 +27,6 @@ pub use layout::LayoutCalculator;
 /// instead of implementing everything in `rustc_middle`.
 pub trait HashStableContext {}
 
-use Integer::*;
-use Primitive::*;
-
 bitflags! {
     #[derive(Default)]
     #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
@@ -53,10 +49,11 @@ bitflags! {
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
 pub enum IntegerType {
-    /// Pointer sized integer type, i.e. isize and usize. The field shows signedness, that
-    /// is, `Pointer(true)` is isize.
+    /// Pointer-sized integer type, i.e. `isize` and `usize`. The field shows signedness, e.g.
+    /// `Pointer(true)` means `isize`.
     Pointer(bool),
-    /// Fix sized integer type, e.g. i8, u32, i128 The bool field shows signedness, `Fixed(I8, false)` means `u8`
+    /// Fixed-sized integer type, e.g. `i8`, `u32`, `i128`. The bool field shows signedness, e.g.
+    /// `Fixed(I8, false)` means `u8`.
     Fixed(Integer, bool),
 }
 
@@ -69,7 +66,7 @@ impl IntegerType {
     }
 }
 
-/// Represents the repr options provided by the user,
+/// Represents the repr options provided by the user.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
 pub struct ReprOptions {
@@ -77,6 +74,7 @@ pub struct ReprOptions {
     pub align: Option<Align>,
     pub pack: Option<Align>,
     pub flags: ReprFlags,
+    #[cfg(feature = "randomize")]
     /// The seed to be used for randomizing a type's layout
     ///
     /// Note: This could technically be a `Hash128` which would
@@ -84,7 +82,7 @@ pub struct ReprOptions {
     /// hash without loss, but it does pay the price of being larger.
     /// Everything's a tradeoff, a 64-bit seed should be sufficient for our
     /// purposes (primarily `-Z randomize-layout`)
-    pub field_shuffle_seed: Hash64,
+    pub field_shuffle_seed: rustc_data_structures::stable_hasher::Hash64,
 }
 
 impl ReprOptions {
@@ -139,7 +137,7 @@ impl ReprOptions {
     }
 
     /// Returns `true` if this type is valid for reordering and `-Z randomize-layout`
-    /// was enabled for its declaration crate
+    /// was enabled for its declaration crate.
     pub fn can_randomize_type_layout(&self) -> bool {
         !self.inhibit_struct_field_reordering_opt()
             && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT)
@@ -217,7 +215,8 @@ pub enum TargetDataLayoutErrors<'a> {
 }
 
 impl TargetDataLayout {
-    /// Parse data layout from an [llvm data layout string](https://llvm.org/docs/LangRef.html#data-layout)
+    /// Parse data layout from an
+    /// [llvm data layout string](https://llvm.org/docs/LangRef.html#data-layout)
     ///
     /// This function doesn't fill `c_enum_min_size` and it will always be `I32` since it can not be
     /// determined from llvm string.
@@ -242,10 +241,11 @@ impl TargetDataLayout {
         };
 
         // Parse a size string.
-        let size = |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits);
+        let parse_size =
+            |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits);
 
         // Parse an alignment string.
-        let align = |s: &[&'a str], cause: &'a str| {
+        let parse_align = |s: &[&'a str], cause: &'a str| {
             if s.is_empty() {
                 return Err(TargetDataLayoutErrors::MissingAlignment { cause });
             }
@@ -269,22 +269,22 @@ impl TargetDataLayout {
                 [p] if p.starts_with('P') => {
                     dl.instruction_address_space = parse_address_space(&p[1..], "P")?
                 }
-                ["a", ref a @ ..] => dl.aggregate_align = align(a, "a")?,
-                ["f32", ref a @ ..] => dl.f32_align = align(a, "f32")?,
-                ["f64", ref a @ ..] => dl.f64_align = align(a, "f64")?,
+                ["a", ref a @ ..] => dl.aggregate_align = parse_align(a, "a")?,
+                ["f32", ref a @ ..] => dl.f32_align = parse_align(a, "f32")?,
+                ["f64", ref a @ ..] => dl.f64_align = parse_align(a, "f64")?,
                 // FIXME(erikdesjardins): we should be parsing nonzero address spaces
                 // this will require replacing TargetDataLayout::{pointer_size,pointer_align}
                 // with e.g. `fn pointer_size_in(AddressSpace)`
                 [p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => {
-                    dl.pointer_size = size(s, p)?;
-                    dl.pointer_align = align(a, p)?;
+                    dl.pointer_size = parse_size(s, p)?;
+                    dl.pointer_align = parse_align(a, p)?;
                 }
                 [s, ref a @ ..] if s.starts_with('i') => {
                     let Ok(bits) = s[1..].parse::<u64>() else {
-                        size(&s[1..], "i")?; // For the user error.
+                        parse_size(&s[1..], "i")?; // For the user error.
                         continue;
                     };
-                    let a = align(a, s)?;
+                    let a = parse_align(a, s)?;
                     match bits {
                         1 => dl.i1_align = a,
                         8 => dl.i8_align = a,
@@ -301,8 +301,8 @@ impl TargetDataLayout {
                     }
                 }
                 [s, ref a @ ..] if s.starts_with('v') => {
-                    let v_size = size(&s[1..], "v")?;
-                    let a = align(a, s)?;
+                    let v_size = parse_size(&s[1..], "v")?;
+                    let a = parse_align(a, s)?;
                     if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
                         v.1 = a;
                         continue;
@@ -339,6 +339,7 @@ impl TargetDataLayout {
 
     #[inline]
     pub fn ptr_sized_integer(&self) -> Integer {
+        use Integer::*;
         match self.pointer_size.bits() {
             16 => I16,
             32 => I32,
@@ -747,7 +748,6 @@ impl Align {
 /// A pair of alignments, ABI-mandated and preferred.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
-
 pub struct AbiAndPrefAlign {
     pub abi: Align,
     pub pref: Align,
@@ -773,7 +773,6 @@ impl AbiAndPrefAlign {
 /// Integers, also used for enum discriminants.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
-
 pub enum Integer {
     I8,
     I16,
@@ -785,6 +784,7 @@ pub enum Integer {
 impl Integer {
     #[inline]
     pub fn size(self) -> Size {
+        use Integer::*;
         match self {
             I8 => Size::from_bytes(1),
             I16 => Size::from_bytes(2),
@@ -805,6 +805,7 @@ impl Integer {
     }
 
     pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
+        use Integer::*;
         let dl = cx.data_layout();
 
         match self {
@@ -819,6 +820,7 @@ impl Integer {
     /// Returns the largest signed value that can be represented by this Integer.
     #[inline]
     pub fn signed_max(self) -> i128 {
+        use Integer::*;
         match self {
             I8 => i8::MAX as i128,
             I16 => i16::MAX as i128,
@@ -831,6 +833,7 @@ impl Integer {
     /// Finds the smallest Integer type which can represent the signed value.
     #[inline]
     pub fn fit_signed(x: i128) -> Integer {
+        use Integer::*;
         match x {
             -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8,
             -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16,
@@ -843,6 +846,7 @@ impl Integer {
     /// Finds the smallest Integer type which can represent the unsigned value.
     #[inline]
     pub fn fit_unsigned(x: u128) -> Integer {
+        use Integer::*;
         match x {
             0..=0x0000_0000_0000_00ff => I8,
             0..=0x0000_0000_0000_ffff => I16,
@@ -854,6 +858,7 @@ impl Integer {
 
     /// Finds the smallest integer with the given alignment.
     pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> {
+        use Integer::*;
         let dl = cx.data_layout();
 
         [I8, I16, I32, I64, I128].into_iter().find(|&candidate| {
@@ -863,6 +868,7 @@ impl Integer {
 
     /// Find the largest integer with the given alignment or less.
     pub fn approximate_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Integer {
+        use Integer::*;
         let dl = cx.data_layout();
 
         // FIXME(eddyb) maybe include I128 in the future, when it works everywhere.
@@ -908,6 +914,7 @@ pub enum Primitive {
 
 impl Primitive {
     pub fn size<C: HasDataLayout>(self, cx: &C) -> Size {
+        use Primitive::*;
         let dl = cx.data_layout();
 
         match self {
@@ -922,6 +929,7 @@ impl Primitive {
     }
 
     pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
+        use Primitive::*;
         let dl = cx.data_layout();
 
         match self {
@@ -937,8 +945,7 @@ impl Primitive {
 }
 
 /// Inclusive wrap-around range of valid values, that is, if
-/// start > end, it represents `start..=MAX`,
-/// followed by `0..=end`.
+/// start > end, it represents `start..=MAX`, followed by `0..=end`.
 ///
 /// That is, for an i8 primitive, a range of `254..=2` means following
 /// sequence:
@@ -970,21 +977,21 @@ impl WrappingRange {
 
     /// Returns `self` with replaced `start`
     #[inline(always)]
-    pub fn with_start(mut self, start: u128) -> Self {
+    fn with_start(mut self, start: u128) -> Self {
         self.start = start;
         self
     }
 
     /// Returns `self` with replaced `end`
     #[inline(always)]
-    pub fn with_end(mut self, end: u128) -> Self {
+    fn with_end(mut self, end: u128) -> Self {
         self.end = end;
         self
     }
 
     /// Returns `true` if `size` completely fills the range.
     #[inline]
-    pub fn is_full_for(&self, size: Size) -> bool {
+    fn is_full_for(&self, size: Size) -> bool {
         let max_value = size.unsigned_int_max();
         debug_assert!(self.start <= max_value && self.end <= max_value);
         self.start == (self.end.wrapping_add(1) & max_value)
@@ -1027,10 +1034,11 @@ pub enum Scalar {
 impl Scalar {
     #[inline]
     pub fn is_bool(&self) -> bool {
+        use Integer::*;
         matches!(
             self,
             Scalar::Initialized {
-                value: Int(I8, false),
+                value: Primitive::Int(I8, false),
                 valid_range: WrappingRange { start: 0, end: 1 }
             }
         )
@@ -1066,7 +1074,8 @@ impl Scalar {
     }
 
     #[inline]
-    /// Allows the caller to mutate the valid range. This operation will panic if attempted on a union.
+    /// Allows the caller to mutate the valid range. This operation will panic if attempted on a
+    /// union.
     pub fn valid_range_mut(&mut self) -> &mut WrappingRange {
         match self {
             Scalar::Initialized { valid_range, .. } => valid_range,
@@ -1074,7 +1083,8 @@ impl Scalar {
         }
     }
 
-    /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout
+    /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole
+    /// layout.
     #[inline]
     pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool {
         match *self {
@@ -1093,36 +1103,11 @@ impl Scalar {
     }
 }
 
-rustc_index::newtype_index! {
-    /// The *source-order* index of a field in a variant.
-    ///
-    /// This is how most code after type checking refers to fields, rather than
-    /// using names (as names have hygiene complications and more complex lookup).
-    ///
-    /// Particularly for `repr(Rust)` types, this may not be the same as *layout* order.
-    /// (It is for `repr(C)` `struct`s, however.)
-    ///
-    /// For example, in the following types,
-    /// ```rust
-    /// # enum Never {}
-    /// # #[repr(u16)]
-    /// enum Demo1 {
-    ///    Variant0 { a: Never, b: i32 } = 100,
-    ///    Variant1 { c: u8, d: u64 } = 10,
-    /// }
-    /// struct Demo2 { e: u8, f: u16, g: u8 }
-    /// ```
-    /// `b` is `FieldIdx(1)` in `VariantIdx(0)`,
-    /// `d` is `FieldIdx(1)` in `VariantIdx(1)`, and
-    /// `f` is `FieldIdx(1)` in `VariantIdx(0)`.
-    #[derive(HashStable_Generic)]
-    pub struct FieldIdx {}
-}
-
+// NOTE: This struct is generic over the FieldIdx for rust-analyzer usage.
 /// Describes how the fields of a type are located in memory.
 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
-pub enum FieldsShape {
+pub enum FieldsShape<FieldIdx: Idx> {
     /// Scalar primitives and `!`, which never have fields.
     Primitive,
 
@@ -1162,7 +1147,7 @@ pub enum FieldsShape {
     },
 }
 
-impl FieldsShape {
+impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
     #[inline]
     pub fn count(&self) -> usize {
         match *self {
@@ -1188,7 +1173,7 @@ impl FieldsShape {
                 assert!(i < count, "tried to access field {i} of array with {count} fields");
                 stride * i
             }
-            FieldsShape::Arbitrary { ref offsets, .. } => offsets[FieldIdx::from_usize(i)],
+            FieldsShape::Arbitrary { ref offsets, .. } => offsets[FieldIdx::new(i)],
         }
     }
 
@@ -1200,7 +1185,7 @@ impl FieldsShape {
             }
             FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
             FieldsShape::Arbitrary { ref memory_index, .. } => {
-                memory_index[FieldIdx::from_usize(i)].try_into().unwrap()
+                memory_index[FieldIdx::new(i)].try_into().unwrap()
             }
         }
     }
@@ -1216,7 +1201,7 @@ impl FieldsShape {
         if let FieldsShape::Arbitrary { ref memory_index, .. } = *self {
             if use_small {
                 for (field_idx, &mem_idx) in memory_index.iter_enumerated() {
-                    inverse_small[mem_idx as usize] = field_idx.as_u32() as u8;
+                    inverse_small[mem_idx as usize] = field_idx.index() as u8;
                 }
             } else {
                 inverse_big = memory_index.invert_bijective_mapping();
@@ -1229,7 +1214,7 @@ impl FieldsShape {
                 if use_small {
                     inverse_small[i] as usize
                 } else {
-                    inverse_big[i as u32].as_usize()
+                    inverse_big[i as u32].index()
                 }
             }
         })
@@ -1252,7 +1237,6 @@ impl AddressSpace {
 /// in terms of categories of C types there are ABI rules for.
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
-
 pub enum Abi {
     Uninhabited,
     Scalar(Scalar),
@@ -1373,9 +1357,10 @@ impl Abi {
     }
 }
 
+// NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage.
 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
-pub enum Variants {
+pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
     Single { index: VariantIdx },
 
@@ -1387,15 +1372,16 @@ pub enum Variants {
     /// For enums, the tag is the sole field of the layout.
     Multiple {
         tag: Scalar,
-        tag_encoding: TagEncoding,
+        tag_encoding: TagEncoding<VariantIdx>,
         tag_field: usize,
-        variants: IndexVec<VariantIdx, LayoutS>,
+        variants: IndexVec<VariantIdx, LayoutS<FieldIdx, VariantIdx>>,
     },
 }
 
+// NOTE: This struct is generic over the VariantIdx for rust-analyzer usage.
 #[derive(PartialEq, Eq, Hash, Clone, Debug)]
 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
-pub enum TagEncoding {
+pub enum TagEncoding<VariantIdx: Idx> {
     /// The tag directly stores the discriminant, but possibly with a smaller layout
     /// (so converting the tag to the discriminant can require sign extension).
     Direct,
@@ -1457,17 +1443,19 @@ impl Niche {
             return None;
         }
 
-        // Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound.
-        // Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy the niche of zero.
-        // This is accomplished by preferring enums with 2 variants(`count==1`) and always taking the shortest path to niche zero.
-        // Having `None` in niche zero can enable some special optimizations.
+        // Extend the range of valid values being reserved by moving either `v.start` or `v.end`
+        // bound. Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy
+        // the niche of zero. This is accomplished by preferring enums with 2 variants(`count==1`)
+        // and always taking the shortest path to niche zero. Having `None` in niche zero can
+        // enable some special optimizations.
         //
         // Bound selection criteria:
         // 1. Select closest to zero given wrapping semantics.
         // 2. Avoid moving past zero if possible.
         //
-        // In practice this means that enums with `count > 1` are unlikely to claim niche zero, since they have to fit perfectly.
-        // If niche zero is already reserved, the selection of bounds are of little interest.
+        // In practice this means that enums with `count > 1` are unlikely to claim niche zero,
+        // since they have to fit perfectly. If niche zero is already reserved, the selection of
+        // bounds are of little interest.
         let move_start = |v: WrappingRange| {
             let start = v.start.wrapping_sub(count) & max_value;
             Some((start, Scalar::Initialized { value, valid_range: v.with_start(start) }))
@@ -1501,29 +1489,12 @@ impl Niche {
     }
 }
 
-rustc_index::newtype_index! {
-    /// The *source-order* index of a variant in a type.
-    ///
-    /// For enums, these are always `0..variant_count`, regardless of any
-    /// custom discriminants that may have been defined, and including any
-    /// variants that may end up uninhabited due to field types.  (Some of the
-    /// variants may not be present in a monomorphized ABI [`Variants`], but
-    /// those skipped variants are always counted when determining the *index*.)
-    ///
-    /// `struct`s, `tuples`, and `unions`s are considered to have a single variant
-    /// with variant index zero, aka [`FIRST_VARIANT`].
-    #[derive(HashStable_Generic)]
-    pub struct VariantIdx {
-        /// Equivalent to `VariantIdx(0)`.
-        const FIRST_VARIANT = 0;
-    }
-}
-
+// NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage.
 #[derive(PartialEq, Eq, Hash, Clone)]
 #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
-pub struct LayoutS {
+pub struct LayoutS<FieldIdx: Idx, VariantIdx: Idx> {
     /// Says where the fields are located within the layout.
-    pub fields: FieldsShape,
+    pub fields: FieldsShape<FieldIdx>,
 
     /// Encodes information about multi-variant layouts.
     /// Even with `Multiple` variants, a layout still has its own fields! Those are then
@@ -1532,7 +1503,7 @@ pub struct LayoutS {
     ///
     /// To access all fields of this layout, both `fields` and the fields of the active variant
     /// must be taken into account.
-    pub variants: Variants,
+    pub variants: Variants<FieldIdx, VariantIdx>,
 
     /// The `abi` defines how this data is passed between functions, and it defines
     /// value restrictions via `valid_range`.
@@ -1561,13 +1532,13 @@ pub struct LayoutS {
     pub unadjusted_abi_align: Align,
 }
 
-impl LayoutS {
+impl<FieldIdx: Idx, VariantIdx: Idx> LayoutS<FieldIdx, VariantIdx> {
     pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
         let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
         let size = scalar.size(cx);
         let align = scalar.align(cx);
         LayoutS {
-            variants: Variants::Single { index: FIRST_VARIANT },
+            variants: Variants::Single { index: VariantIdx::new(0) },
             fields: FieldsShape::Primitive,
             abi: Abi::Scalar(scalar),
             largest_niche,
@@ -1579,7 +1550,11 @@ impl LayoutS {
     }
 }
 
-impl fmt::Debug for LayoutS {
+impl<FieldIdx: Idx, VariantIdx: Idx> fmt::Debug for LayoutS<FieldIdx, VariantIdx>
+where
+    FieldsShape<FieldIdx>: fmt::Debug,
+    Variants<FieldIdx, VariantIdx>: fmt::Debug,
+{
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // This is how `Layout` used to print before it become
         // `Interned<LayoutS>`. We print it like this to avoid having to update
@@ -1607,61 +1582,6 @@ impl fmt::Debug for LayoutS {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
-#[rustc_pass_by_value]
-pub struct Layout<'a>(pub Interned<'a, LayoutS>);
-
-impl<'a> fmt::Debug for Layout<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // See comment on `<LayoutS as Debug>::fmt` above.
-        self.0.0.fmt(f)
-    }
-}
-
-impl<'a> Layout<'a> {
-    pub fn fields(self) -> &'a FieldsShape {
-        &self.0.0.fields
-    }
-
-    pub fn variants(self) -> &'a Variants {
-        &self.0.0.variants
-    }
-
-    pub fn abi(self) -> Abi {
-        self.0.0.abi
-    }
-
-    pub fn largest_niche(self) -> Option<Niche> {
-        self.0.0.largest_niche
-    }
-
-    pub fn align(self) -> AbiAndPrefAlign {
-        self.0.0.align
-    }
-
-    pub fn size(self) -> Size {
-        self.0.0.size
-    }
-
-    pub fn max_repr_align(self) -> Option<Align> {
-        self.0.0.max_repr_align
-    }
-
-    pub fn unadjusted_abi_align(self) -> Align {
-        self.0.0.unadjusted_abi_align
-    }
-
-    /// Whether the layout is from a type that implements [`std::marker::PointerLike`].
-    ///
-    /// Currently, that means that the type is pointer-sized, pointer-aligned,
-    /// and has a scalar ABI.
-    pub fn is_pointer_like(self, data_layout: &TargetDataLayout) -> bool {
-        self.size() == data_layout.pointer_size
-            && self.align().abi == data_layout.pointer_align.abi
-            && matches!(self.abi(), Abi::Scalar(..))
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum PointerKind {
     /// Shared reference. `frozen` indicates the absence of any `UnsafeCell`.
@@ -1681,7 +1601,7 @@ pub struct PointeeInfo {
     pub safe: Option<PointerKind>,
 }
 
-impl LayoutS {
+impl<FieldIdx: Idx, VariantIdx: Idx> LayoutS<FieldIdx, VariantIdx> {
     /// Returns `true` if the layout corresponds to an unsized type.
     #[inline]
     pub fn is_unsized(&self) -> bool {
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs
index 23fdd272ffd..bf8a7eb293e 100644
--- a/compiler/rustc_arena/src/lib.rs
+++ b/compiler/rustc_arena/src/lib.rs
@@ -15,7 +15,6 @@
 #![feature(dropck_eyepatch)]
 #![feature(new_uninit)]
 #![feature(maybe_uninit_slice)]
-#![feature(min_specialization)]
 #![feature(decl_macro)]
 #![feature(pointer_byte_offsets)]
 #![feature(rustc_attrs)]
@@ -44,23 +43,6 @@ fn outline<F: FnOnce() -> R, R>(f: F) -> R {
     f()
 }
 
-/// An arena that can hold objects of only one type.
-pub struct TypedArena<T> {
-    /// A pointer to the next object to be allocated.
-    ptr: Cell<*mut T>,
-
-    /// A pointer to the end of the allocated area. When this pointer is
-    /// reached, a new chunk is allocated.
-    end: Cell<*mut T>,
-
-    /// A vector of arena chunks.
-    chunks: RefCell<Vec<ArenaChunk<T>>>,
-
-    /// Marker indicating that dropping the arena causes its owned
-    /// instances of `T` to be dropped.
-    _own: PhantomData<T>,
-}
-
 struct ArenaChunk<T = u8> {
     /// The raw storage for the arena chunk.
     storage: NonNull<[MaybeUninit<T>]>,
@@ -130,6 +112,23 @@ impl<T> ArenaChunk<T> {
 const PAGE: usize = 4096;
 const HUGE_PAGE: usize = 2 * 1024 * 1024;
 
+/// An arena that can hold objects of only one type.
+pub struct TypedArena<T> {
+    /// A pointer to the next object to be allocated.
+    ptr: Cell<*mut T>,
+
+    /// A pointer to the end of the allocated area. When this pointer is
+    /// reached, a new chunk is allocated.
+    end: Cell<*mut T>,
+
+    /// A vector of arena chunks.
+    chunks: RefCell<Vec<ArenaChunk<T>>>,
+
+    /// Marker indicating that dropping the arena causes its owned
+    /// instances of `T` to be dropped.
+    _own: PhantomData<T>,
+}
+
 impl<T> Default for TypedArena<T> {
     /// Creates a new `TypedArena`.
     fn default() -> TypedArena<T> {
@@ -144,77 +143,6 @@ impl<T> Default for TypedArena<T> {
     }
 }
 
-trait IterExt<T> {
-    fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T];
-}
-
-impl<I, T> IterExt<T> for I
-where
-    I: IntoIterator<Item = T>,
-{
-    // This default collects into a `SmallVec` and then allocates by copying
-    // from it. The specializations below for types like `Vec` are more
-    // efficient, copying directly without the intermediate collecting step.
-    // This default could be made more efficient, like
-    // `DroplessArena::alloc_from_iter`, but it's not hot enough to bother.
-    #[inline]
-    default fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] {
-        let vec: SmallVec<[_; 8]> = self.into_iter().collect();
-        vec.alloc_from_iter(arena)
-    }
-}
-
-impl<T, const N: usize> IterExt<T> for std::array::IntoIter<T, N> {
-    #[inline]
-    fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] {
-        let len = self.len();
-        if len == 0 {
-            return &mut [];
-        }
-        // Move the content to the arena by copying and then forgetting it.
-        unsafe {
-            let start_ptr = arena.alloc_raw_slice(len);
-            self.as_slice().as_ptr().copy_to_nonoverlapping(start_ptr, len);
-            mem::forget(self);
-            slice::from_raw_parts_mut(start_ptr, len)
-        }
-    }
-}
-
-impl<T> IterExt<T> for Vec<T> {
-    #[inline]
-    fn alloc_from_iter(mut self, arena: &TypedArena<T>) -> &mut [T] {
-        let len = self.len();
-        if len == 0 {
-            return &mut [];
-        }
-        // Move the content to the arena by copying and then forgetting it.
-        unsafe {
-            let start_ptr = arena.alloc_raw_slice(len);
-            self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
-            self.set_len(0);
-            slice::from_raw_parts_mut(start_ptr, len)
-        }
-    }
-}
-
-impl<A: smallvec::Array> IterExt<A::Item> for SmallVec<A> {
-    #[inline]
-    fn alloc_from_iter(mut self, arena: &TypedArena<A::Item>) -> &mut [A::Item] {
-        let len = self.len();
-        if len == 0 {
-            return &mut [];
-        }
-        // Move the content to the arena by copying and then forgetting it.
-        unsafe {
-            let start_ptr = arena.alloc_raw_slice(len);
-            self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
-            self.set_len(0);
-            slice::from_raw_parts_mut(start_ptr, len)
-        }
-    }
-}
-
 impl<T> TypedArena<T> {
     /// Allocates an object in the `TypedArena`, returning a reference to it.
     #[inline]
@@ -250,33 +178,55 @@ impl<T> TypedArena<T> {
         available_bytes >= additional_bytes
     }
 
-    /// Ensures there's enough space in the current chunk to fit `len` objects.
     #[inline]
-    fn ensure_capacity(&self, additional: usize) {
-        if !self.can_allocate(additional) {
-            self.grow(additional);
-            debug_assert!(self.can_allocate(additional));
-        }
-    }
-
-    #[inline]
-    unsafe fn alloc_raw_slice(&self, len: usize) -> *mut T {
+    fn alloc_raw_slice(&self, len: usize) -> *mut T {
         assert!(mem::size_of::<T>() != 0);
         assert!(len != 0);
 
-        self.ensure_capacity(len);
+        // Ensure the current chunk can fit `len` objects.
+        if !self.can_allocate(len) {
+            self.grow(len);
+            debug_assert!(self.can_allocate(len));
+        }
 
         let start_ptr = self.ptr.get();
-        // SAFETY: `self.ensure_capacity` makes sure that there is enough space
-        // for `len` elements.
+        // SAFETY: `can_allocate`/`grow` ensures that there is enough space for
+        // `len` elements.
         unsafe { self.ptr.set(start_ptr.add(len)) };
         start_ptr
     }
 
     #[inline]
     pub fn alloc_from_iter<I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
+        // This implementation is entirely separate to
+        // `DroplessIterator::alloc_from_iter`, even though conceptually they
+        // are the same.
+        //
+        // `DroplessIterator` (in the fast case) writes elements from the
+        // iterator one at a time into the allocated memory. That's easy
+        // because the elements don't implement `Drop`. But for `TypedArena`
+        // they do implement `Drop`, which means that if the iterator panics we
+        // could end up with some allocated-but-uninitialized elements, which
+        // will then cause UB in `TypedArena::drop`.
+        //
+        // Instead we use an approach where any iterator panic will occur
+        // before the memory is allocated. This function is much less hot than
+        // `DroplessArena::alloc_from_iter`, so it doesn't need to be
+        // hyper-optimized.
         assert!(mem::size_of::<T>() != 0);
-        iter.alloc_from_iter(self)
+
+        let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect();
+        if vec.is_empty() {
+            return &mut [];
+        }
+        // Move the content to the arena by copying and then forgetting it.
+        let len = vec.len();
+        let start_ptr = self.alloc_raw_slice(len);
+        unsafe {
+            vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
+            vec.set_len(0);
+            slice::from_raw_parts_mut(start_ptr, len)
+        }
     }
 
     /// Grows the arena.
@@ -407,6 +357,8 @@ impl Default for DroplessArena {
     #[inline]
     fn default() -> DroplessArena {
         DroplessArena {
+            // We set both `start` and `end` to 0 so that the first call to
+            // alloc() will trigger a grow().
             start: Cell::new(ptr::null_mut()),
             end: Cell::new(ptr::null_mut()),
             chunks: Default::default(),
@@ -415,9 +367,11 @@ impl Default for DroplessArena {
 }
 
 impl DroplessArena {
+    #[inline(never)]
+    #[cold]
     fn grow(&self, layout: Layout) {
         // Add some padding so we can align `self.end` while
-        // stilling fitting in a `layout` allocation.
+        // still fitting in a `layout` allocation.
         let additional = layout.size() + cmp::max(DROPLESS_ALIGNMENT, layout.align()) - 1;
 
         unsafe {
@@ -441,7 +395,7 @@ impl DroplessArena {
             let mut chunk = ArenaChunk::new(align_up(new_cap, PAGE));
             self.start.set(chunk.start());
 
-            // Align the end to DROPLESS_ALIGNMENT
+            // Align the end to DROPLESS_ALIGNMENT.
             let end = align_down(chunk.end().addr(), DROPLESS_ALIGNMENT);
 
             // Make sure we don't go past `start`. This should not happen since the allocation
@@ -454,55 +408,40 @@ impl DroplessArena {
         }
     }
 
-    #[inline(never)]
-    #[cold]
-    fn grow_and_alloc_raw(&self, layout: Layout) -> *mut u8 {
-        self.grow(layout);
-        self.alloc_raw_without_grow(layout).unwrap()
-    }
-
-    #[inline(never)]
-    #[cold]
-    fn grow_and_alloc<T>(&self) -> *mut u8 {
-        self.grow_and_alloc_raw(Layout::new::<T>())
-    }
-
-    /// Allocates a byte slice with specified layout from the current memory
-    /// chunk. Returns `None` if there is no free space left to satisfy the
-    /// request.
-    #[inline]
-    fn alloc_raw_without_grow(&self, layout: Layout) -> Option<*mut u8> {
-        let start = self.start.get().addr();
-        let old_end = self.end.get();
-        let end = old_end.addr();
-
-        // Align allocated bytes so that `self.end` stays aligned to DROPLESS_ALIGNMENT
-        let bytes = align_up(layout.size(), DROPLESS_ALIGNMENT);
-
-        // Tell LLVM that `end` is aligned to DROPLESS_ALIGNMENT
-        unsafe { intrinsics::assume(end == align_down(end, DROPLESS_ALIGNMENT)) };
-
-        let new_end = align_down(end.checked_sub(bytes)?, layout.align());
-        if start <= new_end {
-            let new_end = old_end.with_addr(new_end);
-            // `new_end` is aligned to DROPLESS_ALIGNMENT as `align_down` preserves alignment
-            // as both `end` and `bytes` are already aligned to DROPLESS_ALIGNMENT.
-            self.end.set(new_end);
-            Some(new_end)
-        } else {
-            None
-        }
-    }
-
     #[inline]
     pub fn alloc_raw(&self, layout: Layout) -> *mut u8 {
         assert!(layout.size() != 0);
-        if let Some(a) = self.alloc_raw_without_grow(layout) {
-            return a;
+
+        // This loop executes once or twice: if allocation fails the first
+        // time, the `grow` ensures it will succeed the second time.
+        loop {
+            let start = self.start.get().addr();
+            let old_end = self.end.get();
+            let end = old_end.addr();
+
+            // Align allocated bytes so that `self.end` stays aligned to
+            // DROPLESS_ALIGNMENT.
+            let bytes = align_up(layout.size(), DROPLESS_ALIGNMENT);
+
+            // Tell LLVM that `end` is aligned to DROPLESS_ALIGNMENT.
+            unsafe { intrinsics::assume(end == align_down(end, DROPLESS_ALIGNMENT)) };
+
+            if let Some(sub) = end.checked_sub(bytes) {
+                let new_end = align_down(sub, layout.align());
+                if start <= new_end {
+                    let new_end = old_end.with_addr(new_end);
+                    // `new_end` is aligned to DROPLESS_ALIGNMENT as `align_down`
+                    // preserves alignment as both `end` and `bytes` are already
+                    // aligned to DROPLESS_ALIGNMENT.
+                    self.end.set(new_end);
+                    return new_end;
+                }
+            }
+
+            // No free space left. Allocate a new chunk to satisfy the request.
+            // On failure the grow will panic or abort.
+            self.grow(layout);
         }
-        // No free space left. Allocate a new chunk to satisfy the request.
-        // On failure the grow will panic or abort.
-        self.grow_and_alloc_raw(layout)
     }
 
     #[inline]
@@ -510,13 +449,7 @@ impl DroplessArena {
         assert!(!mem::needs_drop::<T>());
         assert!(mem::size_of::<T>() != 0);
 
-        let mem = if let Some(a) = self.alloc_raw_without_grow(Layout::for_value::<T>(&object)) {
-            a
-        } else {
-            // No free space left. Allocate a new chunk to satisfy the request.
-            // On failure the grow will panic or abort.
-            self.grow_and_alloc::<T>()
-        } as *mut T;
+        let mem = self.alloc_raw(Layout::new::<T>()) as *mut T;
 
         unsafe {
             // Write into uninitialized memory.
@@ -713,10 +646,10 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
         }
 
         #[allow(clippy::mut_from_ref)]
-        pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, C>, C>(
-            &'a self,
+        pub fn alloc_from_iter<T: ArenaAllocatable<'tcx, C>, C>(
+            &self,
             iter: impl ::std::iter::IntoIterator<Item = T>,
-        ) -> &'a mut [T] {
+        ) -> &mut [T] {
             T::allocate_from_iter(self, iter)
         }
     }
diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs
index 3370146193a..2dd5e96e513 100644
--- a/compiler/rustc_ast/src/entry.rs
+++ b/compiler/rustc_ast/src/entry.rs
@@ -1,3 +1,7 @@
+use crate::{attr, Attribute};
+use rustc_span::symbol::sym;
+use rustc_span::Symbol;
+
 #[derive(Debug)]
 pub enum EntryPointType {
     None,
@@ -6,3 +10,26 @@ pub enum EntryPointType {
     Start,
     OtherMain, // Not an entry point, but some other function named main
 }
+
+pub fn entry_point_type(
+    attrs: &[Attribute],
+    at_root: bool,
+    name: Option<Symbol>,
+) -> EntryPointType {
+    if attr::contains_name(attrs, sym::start) {
+        EntryPointType::Start
+    } else if attr::contains_name(attrs, sym::rustc_main) {
+        EntryPointType::RustcMainAttr
+    } else {
+        if let Some(name) = name && name == sym::main {
+            if at_root {
+                // This is a top-level function so it can be `main`.
+                EntryPointType::MainNamed
+            } else {
+                EntryPointType::OtherMain
+            }
+        } else {
+            EntryPointType::None
+        }
+    }
+}
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 300b1486f9b..09bfbd02198 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -446,7 +446,7 @@ impl Token {
         }
     }
 
-    /// Returns `true` if the token can appear at the start of an pattern.
+    /// Returns `true` if the token can appear at the start of a pattern.
     ///
     /// Shamelessly borrowed from `can_begin_expr`, only used for diagnostics right now.
     pub fn can_begin_pattern(&self) -> bool {
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index 8115c4b55b0..aaeef1ff77d 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -99,7 +99,7 @@ ast_lowering_misplaced_double_dot =
     .note = only allowed in tuple, tuple struct, and slice patterns
 
 ast_lowering_misplaced_impl_trait =
-    `impl Trait` only allowed in function and inherent method return types, not in {$position}
+    `impl Trait` only allowed in function and inherent method argument and return types, not in {$position}
 
 ast_lowering_misplaced_relax_trait_bound =
     `?Trait` bounds are only permitted at the point where a type parameter is declared
diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs
index afcf8b15cd8..45a9bebfcf6 100644
--- a/compiler/rustc_ast_lowering/src/format.rs
+++ b/compiler/rustc_ast_lowering/src/format.rs
@@ -410,15 +410,11 @@ fn expand_format_args<'hir>(
     let format_options = use_format_options.then(|| {
         // Generate:
         //     &[format_spec_0, format_spec_1, format_spec_2]
-        let elements: Vec<_> = fmt
-            .template
-            .iter()
-            .filter_map(|piece| {
-                let FormatArgsPiece::Placeholder(placeholder) = piece else { return None };
-                Some(make_format_spec(ctx, macsp, placeholder, &mut argmap))
-            })
-            .collect();
-        ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements))
+        let elements = ctx.arena.alloc_from_iter(fmt.template.iter().filter_map(|piece| {
+            let FormatArgsPiece::Placeholder(placeholder) = piece else { return None };
+            Some(make_format_spec(ctx, macsp, placeholder, &mut argmap))
+        }));
+        ctx.expr_array_ref(macsp, elements)
     });
 
     let arguments = fmt.arguments.all_args();
@@ -477,10 +473,8 @@ fn expand_format_args<'hir>(
         //         <core::fmt::Argument>::new_debug(&arg2),
         //         …
         //     ]
-        let elements: Vec<_> = arguments
-            .iter()
-            .zip(argmap)
-            .map(|(arg, ((_, ty), placeholder_span))| {
+        let elements = ctx.arena.alloc_from_iter(arguments.iter().zip(argmap).map(
+            |(arg, ((_, ty), placeholder_span))| {
                 let placeholder_span =
                     placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt());
                 let arg_span = match arg.kind {
@@ -493,9 +487,9 @@ fn expand_format_args<'hir>(
                     hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg),
                 ));
                 make_argument(ctx, placeholder_span, ref_arg, ty)
-            })
-            .collect();
-        ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements))
+            },
+        ));
+        ctx.expr_array_ref(macsp, elements)
     } else {
         // Generate:
         //     &match (&arg0, &arg1, &…) {
@@ -528,19 +522,14 @@ fn expand_format_args<'hir>(
                 make_argument(ctx, placeholder_span, arg, ty)
             },
         ));
-        let elements: Vec<_> = arguments
-            .iter()
-            .map(|arg| {
-                let arg_expr = ctx.lower_expr(&arg.expr);
-                ctx.expr(
-                    arg.expr.span.with_ctxt(macsp.ctxt()),
-                    hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg_expr),
-                )
-            })
-            .collect();
-        let args_tuple = ctx
-            .arena
-            .alloc(ctx.expr(macsp, hir::ExprKind::Tup(ctx.arena.alloc_from_iter(elements))));
+        let elements = ctx.arena.alloc_from_iter(arguments.iter().map(|arg| {
+            let arg_expr = ctx.lower_expr(&arg.expr);
+            ctx.expr(
+                arg.expr.span.with_ctxt(macsp.ctxt()),
+                hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg_expr),
+            )
+        }));
+        let args_tuple = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Tup(elements)));
         let array = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Array(args)));
         let match_arms = ctx.arena.alloc_from_iter([ctx.arm(args_pat, array)]);
         let match_expr = ctx.arena.alloc(ctx.expr_match(
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 85ab5e7223b..7e3ada9c123 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1824,7 +1824,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             }
 
             let fn_def_id = self.local_def_id(fn_node_id);
-            self.lower_async_fn_ret_ty(&decl.output, fn_def_id, ret_id, kind)
+            self.lower_async_fn_ret_ty(&decl.output, fn_def_id, ret_id, kind, fn_span)
         } else {
             match &decl.output {
                 FnRetTy::Ty(ty) => {
@@ -1901,8 +1901,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         fn_def_id: LocalDefId,
         opaque_ty_node_id: NodeId,
         fn_kind: FnDeclKind,
+        fn_span: Span,
     ) -> hir::FnRetTy<'hir> {
-        let span = self.lower_span(output.span());
+        let span = self.lower_span(fn_span);
         let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
 
         let captured_lifetimes: Vec<_> = self
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 7bc685a5450..743fad8e865 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -52,7 +52,8 @@ struct AstValidator<'a> {
     /// Are we inside a trait impl?
     in_trait_impl: bool,
 
-    in_const_trait_impl: bool,
+    /// Are we inside a const trait defn or impl?
+    in_const_trait_or_impl: bool,
 
     has_proc_macro_decls: bool,
 
@@ -78,11 +79,19 @@ impl<'a> AstValidator<'a> {
         f: impl FnOnce(&mut Self),
     ) {
         let old = mem::replace(&mut self.in_trait_impl, is_in);
-        let old_const =
-            mem::replace(&mut self.in_const_trait_impl, matches!(constness, Some(Const::Yes(_))));
+        let old_const = mem::replace(
+            &mut self.in_const_trait_or_impl,
+            matches!(constness, Some(Const::Yes(_))),
+        );
         f(self);
         self.in_trait_impl = old;
-        self.in_const_trait_impl = old_const;
+        self.in_const_trait_or_impl = old_const;
+    }
+
+    fn with_in_trait(&mut self, is_const: bool, f: impl FnOnce(&mut Self)) {
+        let old = mem::replace(&mut self.in_const_trait_or_impl, is_const);
+        f(self);
+        self.in_const_trait_or_impl = old;
     }
 
     fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
@@ -933,23 +942,26 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 }
             }
             ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
-                if *is_auto == IsAuto::Yes {
-                    // Auto traits cannot have generics, super traits nor contain items.
-                    self.deny_generic_params(generics, item.ident.span);
-                    self.deny_super_traits(bounds, item.ident.span);
-                    self.deny_where_clause(&generics.where_clause, item.ident.span);
-                    self.deny_items(items, item.ident.span);
-                }
+                let is_const_trait = attr::contains_name(&item.attrs, sym::const_trait);
+                self.with_in_trait(is_const_trait, |this| {
+                    if *is_auto == IsAuto::Yes {
+                        // Auto traits cannot have generics, super traits nor contain items.
+                        this.deny_generic_params(generics, item.ident.span);
+                        this.deny_super_traits(bounds, item.ident.span);
+                        this.deny_where_clause(&generics.where_clause, item.ident.span);
+                        this.deny_items(items, item.ident.span);
+                    }
 
-                // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
-                // context for the supertraits.
-                self.visit_vis(&item.vis);
-                self.visit_ident(item.ident);
-                self.visit_generics(generics);
-                self.with_tilde_const_allowed(|this| {
-                    walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
+                    // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
+                    // context for the supertraits.
+                    this.visit_vis(&item.vis);
+                    this.visit_ident(item.ident);
+                    this.visit_generics(generics);
+                    this.with_tilde_const_allowed(|this| {
+                        walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
+                    });
+                    walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
                 });
-                walk_list!(self, visit_assoc_item, items, AssocCtxt::Trait);
                 walk_list!(self, visit_attribute, &item.attrs);
                 return; // Avoid visiting again
             }
@@ -1278,7 +1290,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
         let tilde_const_allowed =
             matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
-                || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
+                || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl);
 
         let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
 
@@ -1363,7 +1375,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 walk_list!(self, visit_ty, ty);
             }
             AssocItemKind::Fn(box Fn { sig, generics, body, .. })
-                if self.in_const_trait_impl
+                if self.in_const_trait_or_impl
                     || ctxt == AssocCtxt::Trait
                     || matches!(sig.header.constness, Const::Yes(_)) =>
             {
@@ -1510,7 +1522,7 @@ pub fn check_crate(
         features,
         extern_mod: None,
         in_trait_impl: false,
-        in_const_trait_impl: false,
+        in_const_trait_or_impl: false,
         has_proc_macro_decls: false,
         outer_impl_trait: None,
         disallow_tilde_const: None,
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 62dc7ae58a2..5d279943f1e 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -603,6 +603,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
         "exclusive range pattern syntax is experimental"
     );
     gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable");
+    gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable");
 
     visit::walk_crate(&mut visitor, krate);
 }
diff --git a/compiler/rustc_attr/Cargo.toml b/compiler/rustc_attr/Cargo.toml
index 2c4c3a0c263..a14d2796817 100644
--- a/compiler/rustc_attr/Cargo.toml
+++ b/compiler/rustc_attr/Cargo.toml
@@ -6,14 +6,14 @@ edition = "2021"
 [lib]
 
 [dependencies]
+rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
-rustc_serialize = { path = "../rustc_serialize" }
-rustc_errors = { path = "../rustc_errors" }
-rustc_fluent_macro = { path = "../rustc_fluent_macro" }
-rustc_span = { path = "../rustc_span" }
 rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_lexer = { path = "../rustc_lexer" }
 rustc_macros = { path = "../rustc_macros" }
+rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
-rustc_ast = { path = "../rustc_ast" }
+rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index ca4b3662a08..6f82d6f9323 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -162,7 +162,7 @@ pub enum StabilityLevel {
         is_soft: bool,
         /// If part of a feature is stabilized and a new feature is added for the remaining parts,
         /// then the `implied_by` attribute is used to indicate which now-stable feature previously
-        /// contained a item.
+        /// contained an item.
         ///
         /// ```pseudo-Rust
         /// #[unstable(feature = "foo", issue = "...")]
@@ -846,7 +846,7 @@ pub fn find_deprecation(
                                 ),
                             );
                         } else {
-                            sess.emit_err(session_diagnostics::IncorrectMetaItem2 {
+                            sess.emit_err(session_diagnostics::IncorrectMetaItem {
                                 span: meta.span,
                             });
                         }
diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs
index ee79545e304..86f27254db2 100644
--- a/compiler/rustc_attr/src/session_diagnostics.rs
+++ b/compiler/rustc_attr/src/session_diagnostics.rs
@@ -165,15 +165,6 @@ pub(crate) struct MissingIssue {
     pub span: Span,
 }
 
-// FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring the error code. Consider
-// changing this to `IncorrectMetaItem`. See #51489.
-#[derive(Diagnostic)]
-#[diag(attr_incorrect_meta_item, code = "E0551")]
-pub(crate) struct IncorrectMetaItem2 {
-    #[primary_span]
-    pub span: Span,
-}
-
 // FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
 // It is more similar to `IncorrectReprFormatGeneric`.
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 48d09f2c2b2..4488276e0e7 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1364,7 +1364,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     err.note(format!(
                         "a for loop advances the iterator for you, the result is stored in `{loop_bind}`."
                     ));
-                    err.help("if you want to call `next` on a iterator within the loop, consider using `while let`.");
+                    err.help("if you want to call `next` on an iterator within the loop, consider using `while let`.");
         }
     }
 
@@ -2828,6 +2828,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         }
                         ProjectionElem::ConstantIndex { .. }
                         | ProjectionElem::Subslice { .. }
+                        | ProjectionElem::Subtype(_)
                         | ProjectionElem::Index(_) => kind,
                     },
                     place_ty.projection_ty(tcx, elem),
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index f70263e9dcf..c3cf7db32b1 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -242,6 +242,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 ProjectionElem::Downcast(..) if opt.including_downcast => return None,
                 ProjectionElem::Downcast(..) => (),
                 ProjectionElem::OpaqueCast(..) => (),
+                ProjectionElem::Subtype(..) => (),
                 ProjectionElem::Field(field, _ty) => {
                     // FIXME(project-rfc_2229#36): print capture precisely here.
                     if let Some(field) = self.is_upvar_field_projection(PlaceRef {
@@ -322,7 +323,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
                 }
                 ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
-                ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(*ty),
+                ProjectionElem::Subtype(ty) | ProjectionElem::OpaqueCast(ty) => {
+                    PlaceTy::from_ty(*ty)
+                }
                 ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
             },
         };
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index a0edeec59d0..e6bde6a8c54 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -159,6 +159,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     [
                         ..,
                         ProjectionElem::Index(_)
+                        | ProjectionElem::Subtype(_)
                         | ProjectionElem::ConstantIndex { .. }
                         | ProjectionElem::OpaqueCast { .. }
                         | ProjectionElem::Subslice { .. }
@@ -1358,9 +1359,9 @@ fn suggest_ampmut<'tcx>(
         None => (false, decl_span),
     };
 
-    // if the binding already exists and is a reference with a explicit
+    // if the binding already exists and is a reference with an explicit
     // lifetime, then we can suggest adding ` mut`. this is special-cased from
-    // the path without a explicit lifetime.
+    // the path without an explicit lifetime.
     if let Ok(src) = tcx.sess.source_map().span_to_snippet(span)
         && src.starts_with("&'")
         // note that `&     'a T` is invalid so this is correct.
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 8115c61e89d..9c77767e7a7 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -1803,6 +1803,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         for (place_base, elem) in place.iter_projections().rev() {
             match elem {
                 ProjectionElem::Index(_/*operand*/) |
+                ProjectionElem::Subtype(_) |
                 ProjectionElem::OpaqueCast(_) |
                 ProjectionElem::ConstantIndex { .. } |
                 // assigning to P[i] requires P to be valid.
@@ -1966,7 +1967,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { kind: mut_borrow_kind }))
             | Write(WriteKind::MutableBorrow(BorrowKind::Mut { kind: mut_borrow_kind })) => {
                 let is_local_mutation_allowed = match mut_borrow_kind {
-                    // `ClosureCapture` is used for mutable variable with a immutable binding.
+                    // `ClosureCapture` is used for mutable variable with an immutable binding.
                     // This is only behaviour difference between `ClosureCapture` and mutable borrows.
                     MutBorrowKind::ClosureCapture => LocalMutationIsAllowed::Yes,
                     MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow => {
@@ -2191,6 +2192,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     | ProjectionElem::Index(..)
                     | ProjectionElem::ConstantIndex { .. }
                     | ProjectionElem::Subslice { .. }
+                    | ProjectionElem::Subtype(..)
                     | ProjectionElem::OpaqueCast { .. }
                     | ProjectionElem::Downcast(..) => {
                         let upvar_field_projection = self.is_upvar_field_projection(place);
diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index c02f6f3b687..539d0837659 100644
--- a/compiler/rustc_borrowck/src/places_conflict.rs
+++ b/compiler/rustc_borrowck/src/places_conflict.rs
@@ -249,6 +249,7 @@ fn place_components_conflict<'tcx>(
                 | (ProjectionElem::ConstantIndex { .. }, _, _)
                 | (ProjectionElem::Subslice { .. }, _, _)
                 | (ProjectionElem::OpaqueCast { .. }, _, _)
+                | (ProjectionElem::Subtype(_), _, _)
                 | (ProjectionElem::Downcast { .. }, _, _) => {
                     // Recursive case. This can still be disjoint on a
                     // further iteration if this a shallow access and
@@ -508,6 +509,7 @@ fn place_projection_conflict<'tcx>(
             | ProjectionElem::Field(..)
             | ProjectionElem::Index(..)
             | ProjectionElem::ConstantIndex { .. }
+            | ProjectionElem::Subtype(_)
             | ProjectionElem::OpaqueCast { .. }
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Downcast(..),
diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs
index 6f281349863..e9c9709bd1f 100644
--- a/compiler/rustc_borrowck/src/prefixes.rs
+++ b/compiler/rustc_borrowck/src/prefixes.rs
@@ -89,6 +89,9 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
                             cursor = cursor_base;
                             continue 'cursor;
                         }
+                        ProjectionElem::Subtype(..) => {
+                            panic!("Subtype projection is not allowed before borrow check")
+                        }
                         ProjectionElem::Deref => {
                             // (handled below)
                         }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 9b952f3fe36..e7b1a489f5d 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -716,6 +716,9 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 }
                 PlaceTy::from_ty(fty)
             }
+            ProjectionElem::Subtype(_) => {
+                bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
+            }
             ProjectionElem::OpaqueCast(ty) => {
                 let ty = self.sanitize_type(place, ty);
                 let ty = self.cx.normalize(ty, location);
@@ -2563,6 +2566,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 | ProjectionElem::Subslice { .. } => {
                     // other field access
                 }
+                ProjectionElem::Subtype(_) => {
+                    bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
+                }
             }
         }
     }
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index af437f36b9f..c73192f4404 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -164,7 +164,7 @@ struct UniversalRegionIndices<'tcx> {
     /// be able to map them to our internal `RegionVid`. This is
     /// basically equivalent to an `GenericArgs`, except that it also
     /// contains an entry for `ReStatic` -- it might be nice to just
-    /// use a args, and then handle `ReStatic` another way.
+    /// use an args, and then handle `ReStatic` another way.
     indices: FxHashMap<ty::Region<'tcx>, RegionVid>,
 
     /// The vid assigned to `'static`. Used only for diagnostics.
@@ -290,7 +290,7 @@ impl<'tcx> UniversalRegions<'tcx> {
         (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize)
     }
 
-    /// Returns `true` if `r` is classified as an local region.
+    /// Returns `true` if `r` is classified as a local region.
     pub fn is_local_free_region(&self, r: RegionVid) -> bool {
         self.region_classification(r) == Some(RegionClassification::Local)
     }
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 53ff089d7b4..9c57f68f0b8 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -169,29 +169,15 @@ impl<'a> Visitor<'a> for InnerItemLinter<'_> {
     }
 }
 
-// Beware, this is duplicated in librustc_passes/entry.rs (with
-// `rustc_hir::Item`), so make sure to keep them in sync.
-fn entry_point_type(item: &ast::Item, depth: usize) -> EntryPointType {
+fn entry_point_type(item: &ast::Item, at_root: bool) -> EntryPointType {
     match item.kind {
         ast::ItemKind::Fn(..) => {
-            if attr::contains_name(&item.attrs, sym::start) {
-                EntryPointType::Start
-            } else if attr::contains_name(&item.attrs, sym::rustc_main) {
-                EntryPointType::RustcMainAttr
-            } else if item.ident.name == sym::main {
-                if depth == 0 {
-                    // This is a top-level function so can be 'main'
-                    EntryPointType::MainNamed
-                } else {
-                    EntryPointType::OtherMain
-                }
-            } else {
-                EntryPointType::None
-            }
+            rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(item.ident.name))
         }
         _ => EntryPointType::None,
     }
 }
+
 /// A folder used to remove any entry points (like fn main) because the harness
 /// generator will provide its own
 struct EntryPointCleaner<'a> {
@@ -210,7 +196,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
         // Remove any #[rustc_main] or #[start] from the AST so it doesn't
         // clash with the one we're going to add, but mark it as
         // #[allow(dead_code)] to avoid printing warnings.
-        let item = match entry_point_type(&item, self.depth) {
+        let item = match entry_point_type(&item, self.depth == 0) {
             EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => {
                 item.map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| {
                     let allow_dead_code = attr::mk_attr_nested_word(
diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
index e6bbac647e5..f09b9ef12de 100644
--- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
@@ -31,7 +31,7 @@ index d95b5b7f17f..00b6f0e3635 100644
 EOF
 
 cat > config.toml <<EOF
-changelog-seen = 2
+change-id = 115898
 
 [llvm]
 ninja = false
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 5d775b9b532..5c7d7b20c5d 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -30,7 +30,7 @@ fn clif_sig_from_fn_abi<'tcx>(
     let inputs = fn_abi.args.iter().flat_map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter());
 
     let (return_ptr, returns) = fn_abi.ret.get_abi_return(tcx);
-    // Sometimes the first param is an pointer to the place where the return value needs to be stored.
+    // Sometimes the first param is a pointer to the place where the return value needs to be stored.
     let params: Vec<_> = return_ptr.into_iter().chain(inputs).collect();
 
     Signature { params, returns, call_conv }
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 6d55fdc3074..0a451dad9d2 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -876,6 +876,7 @@ pub(crate) fn codegen_place<'tcx>(
                 cplace = cplace.place_deref(fx);
             }
             PlaceElem::OpaqueCast(ty) => bug!("encountered OpaqueCast({ty}) in codegen"),
+            PlaceElem::Subtype(ty) => cplace = cplace.place_transmute_type(fx, fx.monomorphize(ty)),
             PlaceElem::Field(field, _ty) => {
                 cplace = cplace.place_field(fx, field);
             }
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index d4273c0b593..45893a4f3ac 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -674,6 +674,16 @@ impl<'tcx> CPlace<'tcx> {
         }
     }
 
+    /// Used for `ProjectionElem::Subtype`, `ty` has to be monomorphized before
+    /// passed on.
+    pub(crate) fn place_transmute_type(
+        self,
+        fx: &mut FunctionCx<'_, '_, 'tcx>,
+        ty: Ty<'tcx>,
+    ) -> CPlace<'tcx> {
+        CPlace { inner: self.inner, layout: fx.layout_of(ty) }
+    }
+
     pub(crate) fn place_field(
         self,
         fx: &mut FunctionCx<'_, '_, 'tcx>,
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 308cb04cac3..ecc293aee23 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1420,7 +1420,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.cx
     }
 
-    fn do_not_inline(&mut self, _llret: RValue<'gcc>) {
+    fn apply_attrs_to_cleanup_callsite(&mut self, _llret: RValue<'gcc>) {
         // FIXME(bjorn3): implement
     }
 
diff --git a/compiler/rustc_codegen_gcc/test.sh b/compiler/rustc_codegen_gcc/test.sh
index 592997b8ab9..b462e5d156b 100755
--- a/compiler/rustc_codegen_gcc/test.sh
+++ b/compiler/rustc_codegen_gcc/test.sh
@@ -214,7 +214,7 @@ function setup_rustc() {
     rm config.toml || true
 
     cat > config.toml <<EOF
-changelog-seen = 2
+change-id = 115898
 
 [rust]
 codegen-backends = []
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index ac6d8f84142..4f9b86ec20a 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -3,6 +3,7 @@ use crate::attributes;
 use crate::common::Funclet;
 use crate::context::CodegenCx;
 use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True};
+use crate::llvm_util;
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
@@ -1225,9 +1226,16 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unsafe { llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED) }
     }
 
-    fn do_not_inline(&mut self, llret: &'ll Value) {
-        let noinline = llvm::AttributeKind::NoInline.create_attr(self.llcx);
-        attributes::apply_to_callsite(llret, llvm::AttributePlace::Function, &[noinline]);
+    fn apply_attrs_to_cleanup_callsite(&mut self, llret: &'ll Value) {
+        if llvm_util::get_version() < (17, 0, 2) {
+            // Work around https://github.com/llvm/llvm-project/issues/66984.
+            let noinline = llvm::AttributeKind::NoInline.create_attr(self.llcx);
+            attributes::apply_to_callsite(llret, llvm::AttributePlace::Function, &[noinline]);
+        } else {
+            // Cleanup is always the cold path.
+            let cold_inline = llvm::AttributeKind::Cold.create_attr(self.llcx);
+            attributes::apply_to_callsite(llret, llvm::AttributePlace::Function, &[cold_inline]);
+        }
     }
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs
index e83110dcad4..55f43aa5341 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs
@@ -11,7 +11,7 @@ pub struct Expression {
     lhs: Operand,
     op: Op,
     rhs: Operand,
-    region: Option<CodeRegion>,
+    code_regions: Vec<CodeRegion>,
 }
 
 /// Collects all of the coverage regions associated with (a) injected counters, (b) counter
@@ -30,7 +30,7 @@ pub struct FunctionCoverage<'tcx> {
     instance: Instance<'tcx>,
     source_hash: u64,
     is_used: bool,
-    counters: IndexVec<CounterId, Option<CodeRegion>>,
+    counters: IndexVec<CounterId, Option<Vec<CodeRegion>>>,
     expressions: IndexVec<ExpressionId, Option<Expression>>,
     unreachable_regions: Vec<CodeRegion>,
 }
@@ -77,28 +77,40 @@ impl<'tcx> FunctionCoverage<'tcx> {
         }
     }
 
-    /// Adds a code region to be counted by an injected counter intrinsic.
-    pub fn add_counter(&mut self, id: CounterId, region: CodeRegion) {
-        if let Some(previous_region) = self.counters[id].replace(region.clone()) {
-            assert_eq!(previous_region, region, "add_counter: code region for id changed");
+    /// Adds code regions to be counted by an injected counter intrinsic.
+    #[instrument(level = "debug", skip(self))]
+    pub(crate) fn add_counter(&mut self, id: CounterId, code_regions: &[CodeRegion]) {
+        if code_regions.is_empty() {
+            return;
+        }
+
+        let slot = &mut self.counters[id];
+        match slot {
+            None => *slot = Some(code_regions.to_owned()),
+            // If this counter ID slot has already been filled, it should
+            // contain identical information.
+            Some(ref previous_regions) => assert_eq!(
+                previous_regions, code_regions,
+                "add_counter: code regions for id changed"
+            ),
         }
     }
 
+    /// Adds information about a coverage expression, along with zero or more
+    /// code regions mapped to that expression.
+    ///
     /// Both counters and "counter expressions" (or simply, "expressions") can be operands in other
     /// expressions. These are tracked as separate variants of `Operand`, so there is no ambiguity
     /// between operands that are counter IDs and operands that are expression IDs.
-    pub fn add_counter_expression(
+    #[instrument(level = "debug", skip(self))]
+    pub(crate) fn add_counter_expression(
         &mut self,
         expression_id: ExpressionId,
         lhs: Operand,
         op: Op,
         rhs: Operand,
-        region: Option<CodeRegion>,
+        code_regions: &[CodeRegion],
     ) {
-        debug!(
-            "add_counter_expression({:?}, lhs={:?}, op={:?}, rhs={:?} at {:?}",
-            expression_id, lhs, op, rhs, region
-        );
         debug_assert!(
             expression_id.as_usize() < self.expressions.len(),
             "expression_id {} is out of range for expressions.len() = {}
@@ -107,23 +119,25 @@ impl<'tcx> FunctionCoverage<'tcx> {
             self.expressions.len(),
             self,
         );
-        if let Some(previous_expression) = self.expressions[expression_id].replace(Expression {
-            lhs,
-            op,
-            rhs,
-            region: region.clone(),
-        }) {
-            assert_eq!(
-                previous_expression,
-                Expression { lhs, op, rhs, region },
+
+        let expression = Expression { lhs, op, rhs, code_regions: code_regions.to_owned() };
+        let slot = &mut self.expressions[expression_id];
+        match slot {
+            None => *slot = Some(expression),
+            // If this expression ID slot has already been filled, it should
+            // contain identical information.
+            Some(ref previous_expression) => assert_eq!(
+                previous_expression, &expression,
                 "add_counter_expression: expression for id changed"
-            );
+            ),
         }
     }
 
-    /// Add a region that will be marked as "unreachable", with a constant "zero counter".
-    pub fn add_unreachable_region(&mut self, region: CodeRegion) {
-        self.unreachable_regions.push(region)
+    /// Adds regions that will be marked as "unreachable", with a constant "zero counter".
+    #[instrument(level = "debug", skip(self))]
+    pub(crate) fn add_unreachable_regions(&mut self, code_regions: &[CodeRegion]) {
+        assert!(!code_regions.is_empty(), "unreachable regions always have code regions");
+        self.unreachable_regions.extend_from_slice(code_regions);
     }
 
     /// Perform some simplifications to make the final coverage mappings
@@ -212,11 +226,16 @@ impl<'tcx> FunctionCoverage<'tcx> {
     }
 
     fn counter_regions(&self) -> impl Iterator<Item = (Counter, &CodeRegion)> {
-        self.counters.iter_enumerated().filter_map(|(index, entry)| {
-            // Option::map() will return None to filter out missing counters. This may happen
-            // if, for example, a MIR-instrumented counter is removed during an optimization.
-            entry.as_ref().map(|region| (Counter::counter_value_reference(index), region))
-        })
+        self.counters
+            .iter_enumerated()
+            // Filter out counter IDs that we never saw during MIR traversal.
+            // This can happen if a counter was optimized out by MIR transforms
+            // (and replaced with `CoverageKind::Unreachable` instead).
+            .filter_map(|(id, maybe_code_regions)| Some((id, maybe_code_regions.as_ref()?)))
+            .flat_map(|(id, code_regions)| {
+                let counter = Counter::counter_value_reference(id);
+                code_regions.iter().map(move |region| (counter, region))
+            })
     }
 
     /// Convert this function's coverage expression data into a form that can be
@@ -254,13 +273,17 @@ impl<'tcx> FunctionCoverage<'tcx> {
 
     fn expression_regions(&self) -> Vec<(Counter, &CodeRegion)> {
         // Find all of the expression IDs that weren't optimized out AND have
-        // an attached code region, and return the corresponding mapping as a
-        // counter/region pair.
+        // one or more attached code regions, and return the corresponding
+        // mappings as counter/region pairs.
         self.expressions
             .iter_enumerated()
-            .filter_map(|(id, expression)| {
-                let code_region = expression.as_ref()?.region.as_ref()?;
-                Some((Counter::expression(id), code_region))
+            .filter_map(|(id, maybe_expression)| {
+                let code_regions = &maybe_expression.as_ref()?.code_regions;
+                Some((id, code_regions))
+            })
+            .flat_map(|(id, code_regions)| {
+                let counter = Counter::expression(id);
+                code_regions.iter().map(move |code_region| (counter, code_region))
             })
             .collect::<Vec<_>>()
     }
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index c70cb670e96..dd2ce9b525b 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -89,9 +89,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
     /// `function_coverage_map` (keyed by function `Instance`) during codegen.
     /// But in this case, since the unused function was _not_ previously
     /// codegenned, collect the coverage `CodeRegion`s from the MIR and add
-    /// them. The first `CodeRegion` is used to add a single counter, with the
-    /// same counter ID used in the injected `instrprof.increment` intrinsic
-    /// call. Since the function is never called, all other `CodeRegion`s can be
+    /// them. Since the function is never called, all of its `CodeRegion`s can be
     /// added as `unreachable_region`s.
     fn define_unused_fn(&self, def_id: DefId) {
         let instance = declare_unused_fn(self, def_id);
@@ -110,25 +108,15 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
             .entry(instance)
             .or_insert_with(|| FunctionCoverage::new(bx.tcx(), instance));
 
-        let Coverage { kind, code_region } = coverage.clone();
-        match kind {
+        let Coverage { kind, code_regions } = coverage;
+        match *kind {
             CoverageKind::Counter { function_source_hash, id } => {
                 debug!(
                     "ensuring function source hash is set for instance={:?}; function_source_hash={}",
                     instance, function_source_hash,
                 );
                 func_coverage.set_function_source_hash(function_source_hash);
-
-                if let Some(code_region) = code_region {
-                    // Note: Some counters do not have code regions, but may still be referenced
-                    // from expressions. In that case, don't add the counter to the coverage map,
-                    // but do inject the counter intrinsic.
-                    debug!(
-                        "adding counter to coverage_map: instance={:?}, id={:?}, region={:?}",
-                        instance, id, code_region,
-                    );
-                    func_coverage.add_counter(id, code_region);
-                }
+                func_coverage.add_counter(id, code_regions);
                 // We need to explicitly drop the `RefMut` before calling into `instrprof_increment`,
                 // as that needs an exclusive borrow.
                 drop(coverage_map);
@@ -146,20 +134,10 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
                 bx.instrprof_increment(fn_name, hash, num_counters, index);
             }
             CoverageKind::Expression { id, lhs, op, rhs } => {
-                debug!(
-                    "adding counter expression to coverage_map: instance={:?}, id={:?}, {:?} {:?} {:?}; region: {:?}",
-                    instance, id, lhs, op, rhs, code_region,
-                );
-                func_coverage.add_counter_expression(id, lhs, op, rhs, code_region);
+                func_coverage.add_counter_expression(id, lhs, op, rhs, code_regions);
             }
             CoverageKind::Unreachable => {
-                let code_region =
-                    code_region.expect("unreachable regions always have code regions");
-                debug!(
-                    "adding unreachable code to coverage_map: instance={:?}, at {:?}",
-                    instance, code_region,
-                );
-                func_coverage.add_unreachable_region(code_region);
+                func_coverage.add_unreachable_regions(code_regions);
             }
         }
     }
@@ -227,14 +205,9 @@ fn add_unused_function_coverage<'tcx>(
     let tcx = cx.tcx;
 
     let mut function_coverage = FunctionCoverage::unused(tcx, instance);
-    for (index, &code_region) in tcx.covered_code_regions(def_id).iter().enumerate() {
-        if index == 0 {
-            // Insert at least one real counter so the LLVM CoverageMappingReader will find expected
-            // definitions.
-            function_coverage.add_counter(UNUSED_FUNCTION_COUNTER_ID, code_region.clone());
-        } else {
-            function_coverage.add_unreachable_region(code_region.clone());
-        }
+    for &code_region in tcx.covered_code_regions(def_id) {
+        let code_region = std::slice::from_ref(code_region);
+        function_coverage.add_unreachable_regions(code_region);
     }
 
     if let Some(coverage_context) = cx.coverage_context() {
diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs
index 8db6195d931..06b7703672f 100644
--- a/compiler/rustc_codegen_llvm/src/type_.rs
+++ b/compiler/rustc_codegen_llvm/src/type_.rs
@@ -112,7 +112,7 @@ impl<'ll> CodegenCx<'ll, '_> {
         }
     }
 
-    /// Return a LLVM type that has at most the required alignment,
+    /// Return an LLVM type that has at most the required alignment,
     /// and exactly the required size, as a best-effort padding array.
     pub(crate) fn type_padding_filler(&self, size: Size, align: Align) -> &'ll Type {
         let unit = Integer::approximate_align(self, align);
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index bd0707edfd9..a0cb97d51a0 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -213,7 +213,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
                 self.funclet(fx),
             );
             if fx.mir[self.bb].is_cleanup {
-                bx.do_not_inline(invokeret);
+                bx.apply_attrs_to_cleanup_callsite(invokeret);
             }
 
             if let Some((ret_dest, target)) = destination {
@@ -228,11 +228,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         } else {
             let llret = bx.call(fn_ty, fn_attrs, Some(&fn_abi), fn_ptr, &llargs, self.funclet(fx));
             if fx.mir[self.bb].is_cleanup {
-                // Cleanup is always the cold path. Don't inline
-                // drop glue. Also, when there is a deeply-nested
-                // struct, there are "symmetry" issues that cause
-                // exponential inlining - see issue #41696.
-                bx.do_not_inline(llret);
+                bx.apply_attrs_to_cleanup_callsite(llret);
             }
 
             if let Some((ret_dest, target)) = destination {
@@ -1627,7 +1623,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let fn_ty = bx.fn_decl_backend_type(&fn_abi);
 
         let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref());
-        bx.do_not_inline(llret);
+        bx.apply_attrs_to_cleanup_callsite(llret);
 
         bx.unreachable();
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index f775711f870..eb590a45a63 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -466,6 +466,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 mir::ProjectionElem::OpaqueCast(ty) => {
                     bug!("encountered OpaqueCast({ty}) in codegen")
                 }
+                mir::ProjectionElem::Subtype(ty) => cg_base.project_type(bx, self.monomorphize(ty)),
                 mir::ProjectionElem::Index(index) => {
                     let index = &mir::Operand::Copy(mir::Place::from(index));
                     let index = self.codegen_operand(bx, index);
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 853c6934c2c..aa411f002a0 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -332,5 +332,5 @@ pub trait BuilderMethods<'a, 'tcx>:
     ) -> Self::Value;
     fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
 
-    fn do_not_inline(&mut self, llret: Self::Value);
+    fn apply_attrs_to_cleanup_callsite(&mut self, llret: Self::Value);
 }
diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs
index dc3dbd9d819..b1fde8e4d86 100644
--- a/compiler/rustc_codegen_ssa/src/traits/type_.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs
@@ -30,7 +30,7 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
     fn type_ptr_ext(&self, address_space: AddressSpace) -> Self::Type;
     fn element_type(&self, ty: Self::Type) -> Self::Type;
 
-    /// Returns the number of elements in `self` if it is a LLVM vector type.
+    /// Returns the number of elements in `self` if it is an LLVM vector type.
     fn vector_length(&self, ty: Self::Type) -> usize;
 
     fn float_width(&self, ty: Self::Type) -> usize;
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 14b9894aad5..865e01d0aee 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -207,7 +207,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
         let def_id = instance.def_id();
 
-        if Some(def_id) == self.tcx.lang_items().panic_display()
+        if self.tcx.has_attr(def_id, sym::rustc_const_panic_str)
             || Some(def_id) == self.tcx.lang_items().begin_panic_fn()
         {
             let args = self.copy_fn_args(args)?;
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 94a5cc67d31..af7dfbef2ff 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -13,7 +13,7 @@ use rustc_middle::ty::layout::{
     self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers,
     TyAndLayout,
 };
-use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, Variance};
 use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_session::Limit;
 use rustc_span::Span;
@@ -384,7 +384,7 @@ pub(super) fn mir_assign_valid_types<'tcx>(
     // all normal lifetimes are erased, higher-ranked types with their
     // late-bound lifetimes are still around and can lead to type
     // differences.
-    if util::is_subtype(tcx, param_env, src.ty, dest.ty) {
+    if util::relate_types(tcx, param_env, Variance::Covariant, src.ty, dest.ty) {
         // Make sure the layout is equal, too -- just to be safe. Miri really
         // needs layout equality. For performance reason we skip this check when
         // the types are equal. Equal types *can* have different layouts when
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index a32ea204f98..99dba977a43 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -670,19 +670,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
         trace!("eval_place_to_op: got {:?}", op);
         // Sanity-check the type we ended up with.
-        debug_assert!(
-            mir_assign_valid_types(
+        if cfg!(debug_assertions) {
+            let normalized_place_ty = self.subst_from_current_frame_and_normalize_erasing_regions(
+                mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
+            )?;
+            if !mir_assign_valid_types(
                 *self.tcx,
                 self.param_env,
-                self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
-                    mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty
-                )?)?,
+                self.layout_of(normalized_place_ty)?,
                 op.layout,
-            ),
-            "eval_place of a MIR place with type {:?} produced an interpreter operand with type {}",
-            mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
-            op.layout.ty,
-        );
+            ) {
+                span_bug!(
+                    self.cur_span(),
+                    "eval_place of a MIR place with type {} produced an interpreter operand with type {}",
+                    normalized_place_ty,
+                    op.layout.ty,
+                )
+            }
+        }
         Ok(op)
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 503004cbbe1..79448f07cae 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -573,19 +573,24 @@ where
 
         trace!("{:?}", self.dump_place(&place));
         // Sanity-check the type we ended up with.
-        debug_assert!(
-            mir_assign_valid_types(
+        if cfg!(debug_assertions) {
+            let normalized_place_ty = self.subst_from_current_frame_and_normalize_erasing_regions(
+                mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
+            )?;
+            if !mir_assign_valid_types(
                 *self.tcx,
                 self.param_env,
-                self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
-                    mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty
-                )?)?,
+                self.layout_of(normalized_place_ty)?,
                 place.layout,
-            ),
-            "eval_place of a MIR place with type {:?} produced an interpreter place with type {}",
-            mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty,
-            place.layout.ty,
-        );
+            ) {
+                span_bug!(
+                    self.cur_span(),
+                    "eval_place of a MIR place with type {} produced an interpreter place with type {}",
+                    normalized_place_ty,
+                    place.layout.ty,
+                )
+            }
+        }
         Ok(place)
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index f462c13816e..70df3d8fd78 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -319,6 +319,8 @@ where
             OpaqueCast(ty) => {
                 span_bug!(self.cur_span(), "OpaqueCast({ty}) encountered after borrowck")
             }
+            // We don't want anything happening here, this is here as a dummy.
+            Subtype(_) => base.transmute(base.layout(), self)?,
             Field(field, _) => self.project_field(base, field.index())?,
             Downcast(_, variant) => self.project_downcast(base, variant)?,
             Deref => self.deref_pointer(&base.to_op(self)?)?.into(),
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 129e74425b6..c4d806c5161 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -237,7 +237,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
         if self.const_kind() == hir::ConstContext::ConstFn {
             for (idx, local) in body.local_decls.iter_enumerated() {
                 // Handle the return place below.
-                if idx == RETURN_PLACE || local.internal {
+                if idx == RETURN_PLACE {
                     continue;
                 }
 
@@ -664,6 +664,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
             | ProjectionElem::Downcast(..)
             | ProjectionElem::OpaqueCast(..)
             | ProjectionElem::Subslice { .. }
+            | ProjectionElem::Subtype(..)
             | ProjectionElem::Field(..)
             | ProjectionElem::Index(_) => {}
         }
@@ -886,7 +887,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                 // At this point, we are calling a function, `callee`, whose `DefId` is known...
 
-                // `begin_panic` and `panic_display` are generic functions that accept
+                // `begin_panic` and `#[rustc_const_panic_str]` functions accept generic
                 // types other than str. Check to enforce that only str can be used in
                 // const-eval.
 
@@ -898,8 +899,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                     }
                 }
 
-                // const-eval of the `panic_display` fn assumes the argument is `&&str`
-                if Some(callee) == tcx.lang_items().panic_display() {
+                // const-eval of `#[rustc_const_panic_str]` functions assumes the argument is `&&str`
+                if tcx.has_attr(callee, sym::rustc_const_panic_str) {
                     match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
                         ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
                         {
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 34e9b76c484..de3186a53c1 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -306,6 +306,7 @@ where
             ProjectionElem::Index(index) if in_local(index) => return true,
 
             ProjectionElem::Deref
+            | ProjectionElem::Subtype(_)
             | ProjectionElem::Field(_, _)
             | ProjectionElem::OpaqueCast(_)
             | ProjectionElem::ConstantIndex { .. }
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index 4a9977add78..8ede3bdd2b6 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -357,7 +357,9 @@ impl<'tcx> Validator<'_, 'tcx> {
                         return Err(Unpromotable);
                     }
 
-                    ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {}
+                    ProjectionElem::ConstantIndex { .. }
+                    | ProjectionElem::Subtype(_)
+                    | ProjectionElem::Subslice { .. } => {}
 
                     ProjectionElem::Index(local) => {
                         let mut promotable = false;
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 18b22882e7d..4711f7b47cc 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -7,7 +7,7 @@ use rustc_infer::traits::Reveal;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance};
 use rustc_mir_dataflow::impls::MaybeStorageLive;
 use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_mir_dataflow::{Analysis, ResultsCursor};
@@ -16,6 +16,8 @@ use rustc_target::spec::abi::Abi;
 
 use crate::util::is_within_packed;
 
+use crate::util::relate_types;
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 enum EdgeKind {
     Unwind,
@@ -602,7 +604,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             return true;
         }
 
-        crate::util::is_subtype(self.tcx, self.param_env, src, dest)
+        // After borrowck subtyping should be fully explicit via
+        // `Subtype` projections.
+        let variance = if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
+            Variance::Invariant
+        } else {
+            Variance::Covariant
+        };
+
+        crate::util::relate_types(self.tcx, self.param_env, variance, src, dest)
     }
 }
 
@@ -753,6 +763,23 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     }
                 }
             }
+            ProjectionElem::Subtype(ty) => {
+                if !relate_types(
+                    self.tcx,
+                    self.param_env,
+                    Variance::Covariant,
+                    ty,
+                    place_ref.ty(&self.body.local_decls, self.tcx).ty,
+                ) {
+                    self.fail(
+                        location,
+                        format!(
+                            "Failed subtyping {ty:#?} and {:#?}",
+                            place_ref.ty(&self.body.local_decls, self.tcx).ty
+                        ),
+                    )
+                }
+            }
             _ => {}
         }
         self.super_projection_elem(place_ref, elem, context, location);
@@ -1088,6 +1115,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 // LHS and RHS of the assignment must have the same type.
                 let left_ty = dest.ty(&self.body.local_decls, self.tcx).ty;
                 let right_ty = rvalue.ty(&self.body.local_decls, self.tcx);
+
                 if !self.mir_assign_valid_types(right_ty, left_ty) {
                     self.fail(
                         location,
diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs
index 83376c8e992..265ca0c7884 100644
--- a/compiler/rustc_const_eval/src/util/compare_types.rs
+++ b/compiler/rustc_const_eval/src/util/compare_types.rs
@@ -5,7 +5,7 @@
 
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::traits::{DefiningAnchor, ObligationCause};
-use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, Variance};
 use rustc_trait_selection::traits::ObligationCtxt;
 
 /// Returns whether the two types are equal up to subtyping.
@@ -24,16 +24,22 @@ pub fn is_equal_up_to_subtyping<'tcx>(
     }
 
     // Check for subtyping in either direction.
-    is_subtype(tcx, param_env, src, dest) || is_subtype(tcx, param_env, dest, src)
+    relate_types(tcx, param_env, Variance::Covariant, src, dest)
+        || relate_types(tcx, param_env, Variance::Covariant, dest, src)
 }
 
 /// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
 ///
+/// When validating assignments, the variance should be `Covariant`. When checking
+/// during `MirPhase` >= `MirPhase::Runtime(RuntimePhase::Initial)` variance should be `Invariant`
+/// because we want to check for type equality.
+///
 /// This mostly ignores opaque types as it can be used in constraining contexts
 /// while still computing the final underlying type.
-pub fn is_subtype<'tcx>(
+pub fn relate_types<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ParamEnv<'tcx>,
+    variance: Variance,
     src: Ty<'tcx>,
     dest: Ty<'tcx>,
 ) -> bool {
@@ -48,7 +54,7 @@ pub fn is_subtype<'tcx>(
     let cause = ObligationCause::dummy();
     let src = ocx.normalize(&cause, param_env, src);
     let dest = ocx.normalize(&cause, param_env, dest);
-    match ocx.sub(&cause, param_env, src, dest) {
+    match ocx.relate(&cause, param_env, variance, src, dest) {
         Ok(()) => {}
         Err(_) => return false,
     };
diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs
index 0aef7fa469e..040b3071e6f 100644
--- a/compiler/rustc_const_eval/src/util/mod.rs
+++ b/compiler/rustc_const_eval/src/util/mod.rs
@@ -7,7 +7,7 @@ mod type_name;
 
 pub use self::alignment::{is_disaligned, is_within_packed};
 pub use self::check_validity_requirement::check_validity_requirement;
-pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
+pub use self::compare_types::{is_equal_up_to_subtyping, relate_types};
 pub use self::type_name::type_name;
 
 /// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
diff --git a/compiler/rustc_error_codes/src/error_codes/E0551.md b/compiler/rustc_error_codes/src/error_codes/E0551.md
index 53db559a4fc..0e078fe71bf 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0551.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0551.md
@@ -1,8 +1,10 @@
+#### Note: this error code is no longer emitted by the compiler
+
 An invalid meta-item was used inside an attribute.
 
 Erroneous code example:
 
-```compile_fail,E0551
+```compile_fail,E0539
 #[deprecated(note)] // error!
 fn i_am_deprecated() {}
 ```
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index b747a62b864..665b5d6adec 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -1376,16 +1376,16 @@ impl HandlerInner {
                 self.emitted_diagnostic_codes.insert(code.clone());
             }
 
-            let already_emitted = |this: &mut Self| {
+            let already_emitted = {
                 let mut hasher = StableHasher::new();
                 diagnostic.hash(&mut hasher);
                 let diagnostic_hash = hasher.finish();
-                !this.emitted_diagnostics.insert(diagnostic_hash)
+                !self.emitted_diagnostics.insert(diagnostic_hash)
             };
 
             // Only emit the diagnostic if we've been asked to deduplicate or
             // haven't already emitted an equivalent diagnostic.
-            if !(self.flags.deduplicate_diagnostics && already_emitted(self)) {
+            if !(self.flags.deduplicate_diagnostics && already_emitted) {
                 debug!(?diagnostic);
                 debug!(?self.emitted_diagnostics);
                 let already_emitted_sub = |sub: &mut SubDiagnostic| {
@@ -1401,6 +1401,11 @@ impl HandlerInner {
                 };
 
                 diagnostic.children.extract_if(already_emitted_sub).for_each(|_| {});
+                if already_emitted {
+                    diagnostic.note(
+                        "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`",
+                    );
+                }
 
                 self.emitter.emit_diagnostic(diagnostic);
                 if diagnostic.is_error() {
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 18397af565f..65e697c8f3b 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -666,6 +666,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(
         rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
     ),
+    // Ensure the argument to this function is &&str during const-check.
+    rustc_attr!(
+        rustc_const_panic_str, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
+    ),
 
     // ==========================================================================
     // Internal attributes, Layout related:
diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs
index 56e23ac2775..7479e4ef2b3 100644
--- a/compiler/rustc_fluent_macro/src/fluent.rs
+++ b/compiler/rustc_fluent_macro/src/fluent.rs
@@ -40,26 +40,35 @@ fn invocation_relative_path_to_absolute(span: Span, path: &str) -> PathBuf {
     }
 }
 
-/// Tokens to be returned when the macro cannot proceed.
-fn failed(crate_name: &Ident) -> proc_macro::TokenStream {
+/// Final tokens.
+fn finish(body: TokenStream, resource: TokenStream) -> proc_macro::TokenStream {
     quote! {
-        pub static DEFAULT_LOCALE_RESOURCE: &'static str = "";
+        /// Raw content of Fluent resource for this crate, generated by `fluent_messages` macro,
+        /// imported by `rustc_driver` to include all crates' resources in one bundle.
+        pub static DEFAULT_LOCALE_RESOURCE: &'static str = #resource;
 
         #[allow(non_upper_case_globals)]
         #[doc(hidden)]
+        /// Auto-generated constants for type-checked references to Fluent messages.
         pub(crate) mod fluent_generated {
-            pub mod #crate_name {
-            }
+            #body
 
+            /// Constants expected to exist by the diagnostic derive macros to use as default Fluent
+            /// identifiers for different subdiagnostic kinds.
             pub mod _subdiag {
+                /// Default for `#[help]`
                 pub const help: crate::SubdiagnosticMessage =
                     crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help"));
+                /// Default for `#[note]`
                 pub const note: crate::SubdiagnosticMessage =
                     crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note"));
+                /// Default for `#[warn]`
                 pub const warn: crate::SubdiagnosticMessage =
                     crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("warn"));
+                /// Default for `#[label]`
                 pub const label: crate::SubdiagnosticMessage =
                     crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label"));
+                /// Default for `#[suggestion]`
                 pub const suggestion: crate::SubdiagnosticMessage =
                     crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion"));
             }
@@ -68,6 +77,11 @@ fn failed(crate_name: &Ident) -> proc_macro::TokenStream {
     .into()
 }
 
+/// Tokens to be returned when the macro cannot proceed.
+fn failed(crate_name: &Ident) -> proc_macro::TokenStream {
+    finish(quote! { pub mod #crate_name {} }, quote! { "" })
+}
+
 /// See [rustc_fluent_macro::fluent_messages].
 pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
     let crate_name = std::env::var("CARGO_PKG_NAME")
@@ -311,39 +325,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
         }
     }
 
-    quote! {
-        /// Raw content of Fluent resource for this crate, generated by `fluent_messages` macro,
-        /// imported by `rustc_driver` to include all crates' resources in one bundle.
-        pub static DEFAULT_LOCALE_RESOURCE: &'static str = include_str!(#relative_ftl_path);
-
-        #[allow(non_upper_case_globals)]
-        #[doc(hidden)]
-        /// Auto-generated constants for type-checked references to Fluent messages.
-        pub(crate) mod fluent_generated {
-            #constants
-
-            /// Constants expected to exist by the diagnostic derive macros to use as default Fluent
-            /// identifiers for different subdiagnostic kinds.
-            pub mod _subdiag {
-                /// Default for `#[help]`
-                pub const help: crate::SubdiagnosticMessage =
-                    crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help"));
-                /// Default for `#[note]`
-                pub const note: crate::SubdiagnosticMessage =
-                    crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note"));
-                /// Default for `#[warn]`
-                pub const warn: crate::SubdiagnosticMessage =
-                    crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("warn"));
-                /// Default for `#[label]`
-                pub const label: crate::SubdiagnosticMessage =
-                    crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label"));
-                /// Default for `#[suggestion]`
-                pub const suggestion: crate::SubdiagnosticMessage =
-                    crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion"));
-            }
-        }
-    }
-    .into()
+    finish(constants, quote! { include_str!(#relative_ftl_path) })
 }
 
 fn variable_references<'a>(msg: &Message<&'a str>) -> Vec<&'a str> {
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 23b20543d53..4a89a6f7e39 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -230,7 +230,6 @@ language_item_table! {
     Panic,                   sym::panic,               panic_fn,                   Target::Fn,             GenericRequirement::Exact(0);
     PanicNounwind,           sym::panic_nounwind,      panic_nounwind,             Target::Fn,             GenericRequirement::Exact(0);
     PanicFmt,                sym::panic_fmt,           panic_fmt,                  Target::Fn,             GenericRequirement::None;
-    PanicDisplay,            sym::panic_display,       panic_display,              Target::Fn,             GenericRequirement::None;
     ConstPanicFmt,           sym::const_panic_fmt,     const_panic_fmt,            Target::Fn,             GenericRequirement::None;
     PanicBoundsCheck,        sym::panic_bounds_check,  panic_bounds_check_fn,      Target::Fn,             GenericRequirement::Exact(0);
     PanicMisalignedPointerDereference,        sym::panic_misaligned_pointer_dereference,  panic_misaligned_pointer_dereference_fn,      Target::Fn,             GenericRequirement::Exact(0);
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 1c926533a27..ee475e3de7e 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -96,8 +96,6 @@ hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed
     .label = overflowed on value after {$discr}
     .note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome
 
-hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
-
 hir_analysis_field_already_declared =
     field `{$field_name}` is already declared
     .label = field already declared
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index d081b0e35c6..6a1da615055 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -16,6 +16,7 @@ use rustc_infer::traits::util;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::util::ExplicitSelf;
+use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::{
     self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
 };
@@ -1188,7 +1189,7 @@ fn report_trait_method_mismatch<'tcx>(
                     let ap = Applicability::MachineApplicable;
                     match sig.decl.output {
                         hir::FnRetTy::DefaultReturn(sp) => {
-                            let sugg = format!("-> {} ", trait_sig.output());
+                            let sugg = format!(" -> {}", trait_sig.output());
                             diag.span_suggestion_verbose(sp, msg, sugg, ap);
                         }
                         hir::FnRetTy::Return(hir_ty) => {
@@ -2279,16 +2280,16 @@ pub(super) fn check_type_bounds<'tcx>(
                 //
                 // impl<T> X for T where T: X { type Y = <T as X>::Y; }
             }
-            _ => predicates.push(ty::Clause::from_projection_clause(
-                tcx,
+            _ => predicates.push(
                 ty::Binder::bind_with_vars(
                     ty::ProjectionPredicate {
                         projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_args),
                         term: normalize_impl_ty.into(),
                     },
                     bound_vars,
-                ),
-            )),
+                )
+                .to_predicate(tcx),
+            ),
         };
         ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
     };
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index d9e0e87eb47..bc5029a1d5e 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -23,8 +23,12 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
     if !tcx.impl_method_has_trait_impl_trait_tys(impl_m.def_id) {
         return;
     }
-    // crate-private traits don't have any library guarantees, there's no need to do this check.
-    if !tcx.visibility(trait_m.container_id(tcx)).is_public() {
+    // unreachable traits don't have any library guarantees, there's no need to do this check.
+    if trait_m
+        .container_id(tcx)
+        .as_local()
+        .is_some_and(|trait_def_id| !tcx.effective_visibilities(()).is_reachable(trait_def_id))
+    {
         return;
     }
 
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index c4fdffb0261..de6ca0d61dc 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1130,11 +1130,11 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
     let wf_obligations =
         bounds.instantiate_identity_iter_copied().flat_map(|(bound, bound_span)| {
             let normalized_bound = wfcx.normalize(span, None, bound);
-            traits::wf::predicate_obligations(
+            traits::wf::clause_obligations(
                 wfcx.infcx,
                 wfcx.param_env,
                 wfcx.body_def_id,
-                normalized_bound.as_predicate(),
+                normalized_bound,
                 bound_span,
             )
         });
@@ -1234,7 +1234,7 @@ fn check_impl<'tcx>(
                     wfcx.infcx,
                     wfcx.param_env,
                     wfcx.body_def_id,
-                    &trait_pred,
+                    trait_pred,
                     ast_trait_ref.path.span,
                     item,
                 );
@@ -1443,13 +1443,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
     debug!(?predicates.predicates);
     assert_eq!(predicates.predicates.len(), predicates.spans.len());
     let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
-        traits::wf::predicate_obligations(
-            infcx,
-            wfcx.param_env,
-            wfcx.body_def_id,
-            p.as_predicate(),
-            sp,
-        )
+        traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p, sp)
     });
     let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
     wfcx.register_obligations(obligations);
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 3760195a5e8..dbd38e1b1fe 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
@@ -376,9 +376,9 @@ fn check_predicates<'tcx>(
     let always_applicable_traits = impl1_predicates
         .iter()
         .copied()
-        .filter(|(clause, _span)| {
+        .filter(|&(clause, _span)| {
             matches!(
-                trait_predicate_kind(tcx, clause.as_predicate()),
+                trait_specialization_kind(tcx, clause),
                 Some(TraitSpecializationKind::AlwaysApplicable)
             )
         })
@@ -402,7 +402,7 @@ fn check_predicates<'tcx>(
             .iter()
             .any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span))
         {
-            check_specialization_on(tcx, clause.as_predicate(), span)
+            check_specialization_on(tcx, clause, span)
         }
     }
 }
@@ -441,19 +441,16 @@ fn trait_predicates_eq<'tcx>(
 }
 
 #[instrument(level = "debug", skip(tcx))]
-fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, span: Span) {
-    match predicate.kind().skip_binder() {
+fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, span: Span) {
+    match clause.kind().skip_binder() {
         // Global predicates are either always true or always false, so we
         // are fine to specialize on.
-        _ if predicate.is_global() => (),
+        _ if clause.is_global() => (),
         // We allow specializing on explicitly marked traits with no associated
         // items.
-        ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
-            trait_ref,
-            polarity: _,
-        })) => {
+        ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
             if !matches!(
-                trait_predicate_kind(tcx, predicate),
+                trait_specialization_kind(tcx, clause),
                 Some(TraitSpecializationKind::Marker)
             ) {
                 tcx.sess
@@ -467,10 +464,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
                     .emit();
             }
         }
-        ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
-            projection_ty,
-            term,
-        })) => {
+        ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
             tcx.sess
                 .struct_span_err(
                     span,
@@ -478,7 +472,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
                 )
                 .emit();
         }
-        ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => {
+        ty::ClauseKind::ConstArgHasType(..) => {
             // FIXME(min_specialization), FIXME(const_generics):
             // It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure
             // about the actual rules that would be sound. Can't just always error here because otherwise
@@ -490,33 +484,25 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
         }
         _ => {
             tcx.sess
-                .struct_span_err(span, format!("cannot specialize on predicate `{predicate}`"))
+                .struct_span_err(span, format!("cannot specialize on predicate `{clause}`"))
                 .emit();
         }
     }
 }
 
-fn trait_predicate_kind<'tcx>(
+fn trait_specialization_kind<'tcx>(
     tcx: TyCtxt<'tcx>,
-    predicate: ty::Predicate<'tcx>,
+    clause: ty::Clause<'tcx>,
 ) -> Option<TraitSpecializationKind> {
-    match predicate.kind().skip_binder() {
-        ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
-            trait_ref,
-            polarity: _,
-        })) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind),
-        ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_))
-        | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(_))
-        | ty::PredicateKind::Clause(ty::ClauseKind::Projection(_))
-        | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
-        | ty::PredicateKind::AliasRelate(..)
-        | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_))
-        | ty::PredicateKind::Subtype(_)
-        | ty::PredicateKind::Coerce(_)
-        | ty::PredicateKind::ObjectSafe(_)
-        | ty::PredicateKind::ClosureKind(..)
-        | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
-        | ty::PredicateKind::ConstEquate(..)
-        | ty::PredicateKind::Ambiguous => None,
+    match clause.kind().skip_binder() {
+        ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
+            Some(tcx.trait_def(trait_ref.def_id).specialization_kind)
+        }
+        ty::ClauseKind::RegionOutlives(_)
+        | ty::ClauseKind::TypeOutlives(_)
+        | ty::ClauseKind::Projection(_)
+        | ty::ClauseKind::ConstArgHasType(..)
+        | ty::ClauseKind::WellFormed(_)
+        | ty::ClauseKind::ConstEvaluatable(..) => None,
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 85e0000ab47..9fb39a0e93b 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -192,5 +192,5 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
             }
         }
     }
-    tcx.arena.alloc_from_iter(collector.variances.into_iter())
+    tcx.arena.alloc_from_iter(collector.variances)
 }
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 1fa0ec173a7..c8ffd7d1506 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -113,7 +113,11 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     fcx.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
 
-    fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
+    let return_or_body_span = match decl.output {
+        hir::FnRetTy::DefaultReturn(_) => body.value.span,
+        hir::FnRetTy::Return(ty) => ty.span,
+    };
+    fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType);
     fcx.check_return_expr(&body.value, false);
 
     // We insert the deferred_generator_interiors entry after visiting the body.
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index d97691369c9..5c3f2b85966 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -14,7 +14,7 @@ use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable};
+use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable, TypeVisitableExt};
 use rustc_span::symbol::sym;
 use rustc_span::{BytePos, Span, DUMMY_SP};
 use rustc_trait_selection::infer::InferCtxtExt as _;
@@ -504,12 +504,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // incompatible fix at the original mismatch site.
                     if matches!(source, TypeMismatchSource::Ty(_))
                         && let Some(ideal_method) = ideal_method
+                        && let ideal_arg_ty = self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1])
+                        // HACK(compiler-errors): We don't actually consider the implications
+                        // of our inference guesses in `emit_type_mismatch_suggestions`, so
+                        // only suggest things when we know our type error is precisely due to
+                        // a type mismatch, and not via some projection or something. See #116155.
+                        && !ideal_arg_ty.has_non_region_infer()
                     {
                         self.emit_type_mismatch_suggestions(
                             err,
                             arg_expr,
                             arg_ty,
-                            self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1]),
+                            ideal_arg_ty,
                             None,
                             None,
                         );
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 1526988fbd9..8efccd5ba3e 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -110,7 +110,7 @@ pub struct AddressOfTemporaryTaken {
 pub enum AddReturnTypeSuggestion {
     #[suggestion(
         hir_typeck_add_return_type_add,
-        code = "-> {found} ",
+        code = " -> {found}",
         applicability = "machine-applicable"
     )]
     Add {
@@ -120,7 +120,7 @@ pub enum AddReturnTypeSuggestion {
     },
     #[suggestion(
         hir_typeck_add_return_type_missing_here,
-        code = "-> _ ",
+        code = " -> _",
         applicability = "has-placeholders"
     )]
     MissingHere {
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index eead4da5e3e..d9d0dd93010 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -41,7 +41,6 @@ use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::infer::InferOk;
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::ObligationCause;
-use rustc_middle::middle::stability;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
 use rustc_middle::ty::error::{
     ExpectedFound,
@@ -1585,12 +1584,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.check_expr_struct_fields(
             adt_ty,
             expected,
-            expr.hir_id,
+            expr,
             qpath.span(),
             variant,
             fields,
             base_expr,
-            expr.span,
         );
 
         self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized);
@@ -1601,12 +1599,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         adt_ty: Ty<'tcx>,
         expected: Expectation<'tcx>,
-        expr_id: hir::HirId,
+        expr: &hir::Expr<'_>,
         span: Span,
         variant: &'tcx ty::VariantDef,
         ast_fields: &'tcx [hir::ExprField<'tcx>],
         base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
-        expr_span: Span,
     ) {
         let tcx = self.tcx;
 
@@ -1646,7 +1643,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // struct-like enums (yet...), but it's definitely not
                 // a bug to have constructed one.
                 if adt_kind != AdtKind::Enum {
-                    tcx.check_stability(v_field.did, Some(expr_id), field.span, None);
+                    tcx.check_stability(v_field.did, Some(expr.hir_id), field.span, None);
                 }
 
                 self.field_ty(field.span, v_field, args)
@@ -1662,10 +1659,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.report_unknown_field(
                         adt_ty,
                         variant,
+                        expr,
                         field,
                         ast_fields,
                         adt.variant_descr(),
-                        expr_span,
                     )
                 };
 
@@ -1731,7 +1728,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .iter()
                         .map(|f| {
                             let fru_ty = self
-                                .normalize(expr_span, self.field_ty(base_expr.span, f, fresh_args));
+                                .normalize(expr.span, self.field_ty(base_expr.span, f, fresh_args));
                             let ident = self.tcx.adjust_ident(f.ident(self.tcx), variant.def_id);
                             if let Some(_) = remaining_fields.remove(&ident) {
                                 let target_ty = self.field_ty(base_expr.span, f, args);
@@ -1814,7 +1811,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     ty::Adt(adt, args) if adt.is_struct() => variant
                         .fields
                         .iter()
-                        .map(|f| self.normalize(expr_span, f.ty(self.tcx, args)))
+                        .map(|f| self.normalize(expr.span, f.ty(self.tcx, args)))
                         .collect(),
                     _ => {
                         self.tcx
@@ -1824,13 +1821,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 }
             };
-            self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr_id, fru_tys);
+            self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr.hir_id, fru_tys);
         } else if adt_kind != AdtKind::Union && !remaining_fields.is_empty() {
             debug!(?remaining_fields);
             let private_fields: Vec<&ty::FieldDef> = variant
                 .fields
                 .iter()
-                .filter(|field| !field.vis.is_accessible_from(tcx.parent_module(expr_id), tcx))
+                .filter(|field| !field.vis.is_accessible_from(tcx.parent_module(expr.hir_id), tcx))
                 .collect();
 
             if !private_fields.is_empty() {
@@ -2049,16 +2046,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         ty: Ty<'tcx>,
         variant: &'tcx ty::VariantDef,
+        expr: &hir::Expr<'_>,
         field: &hir::ExprField<'_>,
         skip_fields: &[hir::ExprField<'_>],
         kind_name: &str,
-        expr_span: Span,
     ) -> ErrorGuaranteed {
         if variant.is_recovered() {
             let guar = self
                 .tcx
                 .sess
-                .delay_span_bug(expr_span, "parser recovered but no error was emitted");
+                .delay_span_bug(expr.span, "parser recovered but no error was emitted");
             self.set_tainted_by_errors(guar);
             return guar;
         }
@@ -2102,7 +2099,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     );
                     err.span_label(field.ident.span, "field does not exist");
                     err.span_suggestion_verbose(
-                        expr_span,
+                        expr.span,
                         format!(
                             "`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
                             adt = ty,
@@ -2120,7 +2117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     err.span_label(variant_ident_span, format!("`{ty}` defined here"));
                     err.span_label(field.ident.span, "field does not exist");
                     err.span_suggestion_verbose(
-                        expr_span,
+                        expr.span,
                         format!("`{ty}` is a tuple {kind_name}, use the appropriate syntax",),
                         format!("{ty}(/* fields */)"),
                         Applicability::HasPlaceholders,
@@ -2129,9 +2126,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             },
             _ => {
                 // prevent all specified fields from being suggested
-                let skip_fields: Vec<_> = skip_fields.iter().map(|x| x.ident.name).collect();
+                let available_field_names = self.available_field_names(variant, expr, skip_fields);
                 if let Some(field_name) =
-                    self.suggest_field_name(variant, field.ident.name, &skip_fields, expr_span)
+                    find_best_match_for_name(&available_field_names, field.ident.name, None)
                 {
                     err.span_suggestion(
                         field.ident.span,
@@ -2153,10 +2150,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                     format!("`{ty}` does not have this field"),
                                 );
                             }
-                            let mut available_field_names =
-                                self.available_field_names(variant, expr_span);
-                            available_field_names
-                                .retain(|name| skip_fields.iter().all(|skip| name != skip));
                             if available_field_names.is_empty() {
                                 err.note("all struct fields are already assigned");
                             } else {
@@ -2174,63 +2167,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err.emit()
     }
 
-    // Return a hint about the closest match in field names
-    fn suggest_field_name(
-        &self,
-        variant: &'tcx ty::VariantDef,
-        field: Symbol,
-        skip: &[Symbol],
-        // The span where stability will be checked
-        span: Span,
-    ) -> Option<Symbol> {
-        let names = variant
-            .fields
-            .iter()
-            .filter_map(|field| {
-                // ignore already set fields and private fields from non-local crates
-                // and unstable fields.
-                if skip.iter().any(|&x| x == field.name)
-                    || (!variant.def_id.is_local() && !field.vis.is_public())
-                    || matches!(
-                        self.tcx.eval_stability(field.did, None, span, None),
-                        stability::EvalResult::Deny { .. }
-                    )
-                {
-                    None
-                } else {
-                    Some(field.name)
-                }
-            })
-            .collect::<Vec<Symbol>>();
-
-        find_best_match_for_name(&names, field, None)
-    }
-
     fn available_field_names(
         &self,
         variant: &'tcx ty::VariantDef,
-        access_span: Span,
+        expr: &hir::Expr<'_>,
+        skip_fields: &[hir::ExprField<'_>],
     ) -> Vec<Symbol> {
-        let body_owner_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
         variant
             .fields
             .iter()
             .filter(|field| {
-                let def_scope = self
-                    .tcx
-                    .adjust_ident_and_get_scope(
-                        field.ident(self.tcx),
-                        variant.def_id,
-                        body_owner_hir_id,
-                    )
-                    .1;
-                field.vis.is_accessible_from(def_scope, self.tcx)
-                    && !matches!(
-                        self.tcx.eval_stability(field.did, None, access_span, None),
-                        stability::EvalResult::Deny { .. }
-                    )
+                skip_fields.iter().all(|&skip| skip.ident.name != field.name)
+                    && self.is_field_suggestable(field, expr.hir_id, expr.span)
             })
-            .filter(|field| !self.tcx.is_doc_hidden(field.did))
             .map(|field| field.name)
             .collect()
     }
@@ -2460,7 +2409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.suggest_first_deref_field(&mut err, expr, base, ident);
             }
             ty::Adt(def, _) if !def.is_enum() => {
-                self.suggest_fields_on_recordish(&mut err, def, ident, expr.span);
+                self.suggest_fields_on_recordish(&mut err, expr, def, ident);
             }
             ty::Param(param_ty) => {
                 self.point_at_param_definition(&mut err, param_ty);
@@ -2622,12 +2571,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn suggest_fields_on_recordish(
         &self,
         err: &mut Diagnostic,
+        expr: &hir::Expr<'_>,
         def: ty::AdtDef<'tcx>,
         field: Ident,
-        access_span: Span,
     ) {
+        let available_field_names = self.available_field_names(def.non_enum_variant(), expr, &[]);
         if let Some(suggested_field_name) =
-            self.suggest_field_name(def.non_enum_variant(), field.name, &[], access_span)
+            find_best_match_for_name(&available_field_names, field.name, None)
         {
             err.span_suggestion(
                 field.span,
@@ -2637,12 +2587,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             );
         } else {
             err.span_label(field.span, "unknown field");
-            let struct_variant_def = def.non_enum_variant();
-            let field_names = self.available_field_names(struct_variant_def, access_span);
-            if !field_names.is_empty() {
+            if !available_field_names.is_empty() {
                 err.note(format!(
                     "available fields are: {}",
-                    self.name_series_display(field_names),
+                    self.name_series_display(available_field_names),
                 ));
             }
         }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index abb68989218..9999fa2e59c 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -782,8 +782,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
             hir::FnRetTy::Return(hir_ty) => {
-                let span = hir_ty.span;
-
                 if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind
                     && let hir::Node::Item(hir::Item {
                         kind: hir::ItemKind::OpaqueTy(op_ty),
@@ -799,28 +797,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     debug!(?found);
                     if found.is_suggestable(self.tcx, false) {
                         if term.span.is_empty() {
-                            err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() });
+                            err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span: term.span, found: found.to_string() });
                             return true;
                         } else {
-                            err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span, expected });
+                            err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span: term.span, expected });
                         }
                     }
-                }
-
-                // Only point to return type if the expected type is the return type, as if they
-                // are not, the expectation must have been caused by something else.
-                debug!("return type {:?}", hir_ty);
-                let ty = self.astconv().ast_ty_to_ty(hir_ty);
-                debug!("return type {:?}", ty);
-                debug!("expected type {:?}", expected);
-                let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into());
-                let ty = Binder::bind_with_vars(ty, bound_vars);
-                let ty = self.normalize(span, ty);
-                let ty = self.tcx.erase_late_bound_regions(ty);
-                if self.can_coerce(expected, ty) {
-                    err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span, expected });
-                    self.try_suggest_return_impl_trait(err, expected, ty, fn_id);
-                    return true;
+                } else {
+                    // Only point to return type if the expected type is the return type, as if they
+                    // are not, the expectation must have been caused by something else.
+                    debug!("return type {:?}", hir_ty);
+                    let ty = self.astconv().ast_ty_to_ty(hir_ty);
+                    debug!("return type {:?}", ty);
+                    debug!("expected type {:?}", expected);
+                    let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into());
+                    let ty = Binder::bind_with_vars(ty, bound_vars);
+                    let ty = self.normalize(hir_ty.span, ty);
+                    let ty = self.tcx.erase_late_bound_regions(ty);
+                    if self.can_coerce(expected, ty) {
+                        err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected });
+                        self.try_suggest_return_impl_trait(err, expected, ty, fn_id);
+                        return true;
+                    }
                 }
             }
             _ => {}
@@ -1687,4 +1685,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             false
         }
     }
+
+    pub(crate) fn is_field_suggestable(
+        &self,
+        field: &ty::FieldDef,
+        hir_id: HirId,
+        span: Span,
+    ) -> bool {
+        // The field must be visible in the containing module.
+        field.vis.is_accessible_from(self.tcx.parent_module(hir_id), self.tcx)
+            // The field must not be unstable.
+            && !matches!(
+                self.tcx.eval_stability(field.did, None, rustc_span::DUMMY_SP, None),
+                rustc_middle::middle::stability::EvalResult::Deny { .. }
+            )
+            // If the field is from an external crate it must not be `doc(hidden)`.
+            && (field.did.is_local() || !self.tcx.is_doc_hidden(field.did))
+            // If the field is hygienic it must come from the same syntax context.
+            && self.tcx.def_ident_span(field.did).unwrap().normalize_to_macros_2_0().eq_ctxt(span)
+    }
 }
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 6873382c4ac..cd6adb345e7 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -5,7 +5,6 @@
 #![feature(box_patterns)]
 #![feature(min_specialization)]
 #![feature(control_flow_enum)]
-#![feature(option_as_slice)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 07c48ec6392..a4bbb16026a 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2494,10 +2494,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Try alternative arbitrary self types that could fulfill this call.
             // FIXME: probe for all types that *could* be arbitrary self-types, not
             // just this list.
-            for (rcvr_ty, post) in &[
-                (rcvr_ty, ""),
-                (Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
-                (Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
+            for (rcvr_ty, post, pin_call) in &[
+                (rcvr_ty, "", None),
+                (
+                    Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty),
+                    "&mut ",
+                    Some("as_mut"),
+                ),
+                (
+                    Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty),
+                    "&",
+                    Some("as_ref"),
+                ),
             ] {
                 match self.lookup_probe_for_diagnostic(
                     item_name,
@@ -2531,6 +2539,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     Err(_) => (),
                 }
 
+                let pred = ty::TraitRef::new(
+                    self.tcx,
+                    self.tcx.lang_items().unpin_trait().unwrap(),
+                    [*rcvr_ty],
+                );
+                let unpin = self.predicate_must_hold_considering_regions(&Obligation::new(
+                    self.tcx,
+                    ObligationCause::misc(rcvr.span, self.body_id),
+                    self.param_env,
+                    pred,
+                ));
                 for (rcvr_ty, pre) in &[
                     (Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::OwnedBox), "Box::new"),
                     (Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::Pin), "Pin::new"),
@@ -2554,7 +2573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
                         // implement the `AsRef` trait.
                         let skip = skippable.contains(&did)
-                            || (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
+                            || (("Pin::new" == *pre) && ((sym::as_ref == item_name.name) || !unpin))
                             || inputs_len.is_some_and(|inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() != inputs_len);
                         // Make sure the method is defined for the *actual* receiver: we don't
                         // want to treat `Box<Self>` as a receiver if it only works because of
@@ -2566,7 +2585,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             );
                             err.multipart_suggestion(
                                 "consider wrapping the receiver expression with the \
-                                    appropriate type",
+                                 appropriate type",
                                 vec![
                                     (rcvr.span.shrink_to_lo(), format!("{pre}({post}")),
                                     (rcvr.span.shrink_to_hi(), ")".to_string()),
@@ -2578,6 +2597,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                 }
+                // We special case the situation where `Pin::new` wouldn't work, and instead
+                // suggest using the `pin!()` macro instead.
+                if let Some(new_rcvr_t) = Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::Pin)
+                    // We didn't find an alternative receiver for the method.
+                    && !alt_rcvr_sugg
+                    // `T: !Unpin`
+                    && !unpin
+                    // The method isn't `as_ref`, as it would provide a wrong suggestion for `Pin`.
+                    && sym::as_ref != item_name.name
+                    // Either `Pin::as_ref` or `Pin::as_mut`.
+                    && let Some(pin_call) = pin_call
+                    // Search for `item_name` as a method accessible on `Pin<T>`.
+                    && let Ok(pick) = self.lookup_probe_for_diagnostic(
+                        item_name,
+                        new_rcvr_t,
+                        rcvr,
+                        ProbeScope::AllTraits,
+                        return_type,
+                    )
+                    // We skip some common traits that we don't want to consider because autoderefs
+                    // would take care of them.
+                    && !skippable.contains(&Some(pick.item.container_id(self.tcx)))
+                    // We don't want to go through derefs.
+                    && pick.autoderefs == 0
+                    // Check that the method of the same name that was found on the new `Pin<T>`
+                    // receiver has the same number of arguments that appear in the user's code.
+                    && inputs_len.is_some_and(|inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() == inputs_len)
+                {
+                    let indent = self.tcx.sess
+                        .source_map()
+                        .indentation_before(rcvr.span)
+                        .unwrap_or_else(|| " ".to_string());
+                    err.multipart_suggestion(
+                        "consider pinning the expression",
+                        vec![
+                            (rcvr.span.shrink_to_lo(), format!("let mut pinned = std::pin::pin!(")),
+                            (rcvr.span.shrink_to_hi(), format!(");\n{indent}pinned.{pin_call}()")),
+                        ],
+                        Applicability::MaybeIncorrect,
+                    );
+                    // We don't care about the other suggestions.
+                    alt_rcvr_sugg = true;
+                }
             }
         }
         if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 8fc236f46b2..3f9c9b3381b 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -12,7 +12,6 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::{HirId, Pat, PatKind};
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeVisitableExt};
 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_span::edit_distance::find_best_match_for_name;
@@ -1408,6 +1407,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 adt.variant_descr(),
                 &inexistent_fields,
                 &mut unmentioned_fields,
+                pat,
                 variant,
                 args,
             ))
@@ -1434,15 +1434,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let accessible_unmentioned_fields: Vec<_> = unmentioned_fields
                 .iter()
                 .copied()
-                .filter(|(field, _)| {
-                    field.vis.is_accessible_from(tcx.parent_module(pat.hir_id), tcx)
-                        && !matches!(
-                            tcx.eval_stability(field.did, None, DUMMY_SP, None),
-                            EvalResult::Deny { .. }
-                        )
-                        // We only want to report the error if it is hidden and not local
-                        && !(tcx.is_doc_hidden(field.did) && !field.did.is_local())
-                })
+                .filter(|(field, _)| self.is_field_suggestable(field, pat.hir_id, pat.span))
                 .collect();
 
             if !has_rest_pat {
@@ -1578,12 +1570,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         kind_name: &str,
         inexistent_fields: &[&hir::PatField<'tcx>],
         unmentioned_fields: &mut Vec<(&'tcx ty::FieldDef, Ident)>,
+        pat: &'tcx Pat<'tcx>,
         variant: &ty::VariantDef,
         args: &'tcx ty::List<ty::GenericArg<'tcx>>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let tcx = self.tcx;
-        let (field_names, t, plural) = if inexistent_fields.len() == 1 {
-            (format!("a field named `{}`", inexistent_fields[0].ident), "this", "")
+        let (field_names, t, plural) = if let [field] = inexistent_fields {
+            (format!("a field named `{}`", field.ident), "this", "")
         } else {
             (
                 format!(
@@ -1620,10 +1613,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ),
             );
 
-            if unmentioned_fields.len() == 1 {
-                let input =
-                    unmentioned_fields.iter().map(|(_, field)| field.name).collect::<Vec<_>>();
-                let suggested_name = find_best_match_for_name(&input, pat_field.ident.name, None);
+            if let [(field_def, field)] = unmentioned_fields.as_slice()
+                && self.is_field_suggestable(field_def, pat.hir_id, pat.span)
+            {
+                let suggested_name =
+                    find_best_match_for_name(&[field.name], pat_field.ident.name, None);
                 if let Some(suggested_name) = suggested_name {
                     err.span_suggestion(
                         pat_field.ident.span,
@@ -1646,22 +1640,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         PatKind::Lit(expr)
                             if !self.can_coerce(
                                 self.typeck_results.borrow().expr_ty(expr),
-                                self.field_ty(
-                                    unmentioned_fields[0].1.span,
-                                    unmentioned_fields[0].0,
-                                    args,
-                                ),
+                                self.field_ty(field.span, field_def, args),
                             ) => {}
                         _ => {
-                            let unmentioned_field = unmentioned_fields[0].1.name;
                             err.span_suggestion_short(
                                 pat_field.ident.span,
                                 format!(
                                     "`{}` has a field named `{}`",
                                     tcx.def_path_str(variant.def_id),
-                                    unmentioned_field
+                                    field.name,
                                 ),
-                                unmentioned_field.to_string(),
+                                field.name,
                                 Applicability::MaybeIncorrect,
                             );
                         }
@@ -1871,8 +1860,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         fields: &'tcx [hir::PatField<'tcx>],
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let inaccessible = if have_inaccessible_fields { " and inaccessible fields" } else { "" };
-        let field_names = if unmentioned_fields.len() == 1 {
-            format!("field `{}`{}", unmentioned_fields[0].1, inaccessible)
+        let field_names = if let [(_, field)] = unmentioned_fields {
+            format!("field `{field}`{inaccessible}")
         } else {
             let fields = unmentioned_fields
                 .iter()
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index 46558997f72..b36fb6a4dba 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -66,7 +66,6 @@ infer_await_both_futures = consider `await`ing on both `Future`s
 infer_await_future = consider `await`ing on the `Future`
 infer_await_note = calling an async function returns a future
 
-infer_borrowed_too_long = a value of type `{$ty}` is borrowed for too long
 infer_but_calling_introduces = {$has_param_name ->
     [true] `{$param_name}`
     *[false] `fn` parameter
@@ -181,8 +180,6 @@ infer_more_targeted = {$has_param_name ->
 } but calling `{$ident}` introduces an implicit `'static` lifetime requirement
 
 infer_msl_introduces_static = introduces a `'static` lifetime requirement
-infer_msl_trait_note = this has an implicit `'static` lifetime requirement
-infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement
 infer_msl_unmet_req = because this has an unmet lifetime requirement
 infer_need_type_info_in_generator =
     type inside {$generator_kind ->
@@ -233,7 +230,6 @@ infer_prlf_known_limitation = this is a known limitation that will be removed in
 infer_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
 infer_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here
 infer_reborrow = ...so that reference does not outlive borrowed content
-infer_reborrow_upvar = ...so that closure can access `{$name}`
 infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
 
 infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index ad4525c922b..3ff1a5c0c14 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -194,13 +194,13 @@ impl<'a> SourceKindMultiSuggestion<'a> {
         data: &'a FnRetTy<'a>,
         should_wrap_expr: Option<Span>,
     ) -> Self {
-        let (arrow, post) = match data {
-            FnRetTy::DefaultReturn(_) => ("-> ", " "),
-            _ => ("", ""),
+        let arrow = match data {
+            FnRetTy::DefaultReturn(_) => " -> ",
+            _ => "",
         };
         let (start_span, start_span_code, end_span) = match should_wrap_expr {
-            Some(end_span) => (data.span(), format!("{arrow}{ty_info}{post}{{ "), Some(end_span)),
-            None => (data.span(), format!("{arrow}{ty_info}{post}"), None),
+            Some(end_span) => (data.span(), format!("{arrow}{ty_info} {{"), Some(end_span)),
+            None => (data.span(), format!("{arrow}{ty_info}"), None),
         };
         Self::ClosureReturn { start_span, start_span_code, end_span }
     }
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index fefa8959545..2d6b88226ad 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -44,7 +44,7 @@ pub fn extract_verify_if_eq<'tcx>(
     test_ty: Ty<'tcx>,
 ) -> Option<ty::Region<'tcx>> {
     assert!(!verify_if_eq_b.has_escaping_bound_vars());
-    let mut m = Match::new(tcx, param_env);
+    let mut m = MatchAgainstHigherRankedOutlives::new(tcx, param_env);
     let verify_if_eq = verify_if_eq_b.skip_binder();
     m.relate(verify_if_eq.ty, test_ty).ok()?;
 
@@ -87,24 +87,32 @@ pub(super) fn can_match_erased_ty<'tcx>(
         // pointless micro-optimization
         true
     } else {
-        Match::new(tcx, param_env).relate(outlives_ty, erased_ty).is_ok()
+        MatchAgainstHigherRankedOutlives::new(tcx, param_env).relate(outlives_ty, erased_ty).is_ok()
     }
 }
 
-struct Match<'tcx> {
+struct MatchAgainstHigherRankedOutlives<'tcx> {
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     pattern_depth: ty::DebruijnIndex,
     map: FxHashMap<ty::BoundRegion, ty::Region<'tcx>>,
 }
 
-impl<'tcx> Match<'tcx> {
-    fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Match<'tcx> {
-        Match { tcx, param_env, pattern_depth: ty::INNERMOST, map: FxHashMap::default() }
+impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> {
+    fn new(
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> MatchAgainstHigherRankedOutlives<'tcx> {
+        MatchAgainstHigherRankedOutlives {
+            tcx,
+            param_env,
+            pattern_depth: ty::INNERMOST,
+            map: FxHashMap::default(),
+        }
     }
 }
 
-impl<'tcx> Match<'tcx> {
+impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> {
     /// Creates the "Error" variant that signals "no match".
     fn no_match<T>(&self) -> RelateResult<'tcx, T> {
         Err(TypeError::Mismatch)
@@ -134,7 +142,7 @@ impl<'tcx> Match<'tcx> {
     }
 }
 
-impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
+impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> {
     fn tag(&self) -> &'static str {
         "Match"
     }
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 7377c6e2f35..fa4b8e4c36b 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -5,6 +5,10 @@ lint_array_into_iter =
     .use_explicit_into_iter_suggestion =
         or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
 
+lint_async_fn_in_trait = use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified
+    .note = you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future`
+    .suggestion = you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`
+
 lint_atomic_ordering_fence = memory fences cannot have `Relaxed` ordering
     .help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`
 
@@ -319,6 +323,8 @@ lint_invalid_reference_casting_borrow_as_mut = casting `&T` to `&mut T` is undef
 
 lint_invalid_reference_casting_note_book = for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
+lint_invalid_reference_casting_note_ty_has_interior_mutability = even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get`
+
 lint_lintpass_by_hand = implementing `LintPass` by hand
     .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
 
diff --git a/compiler/rustc_lint/src/async_fn_in_trait.rs b/compiler/rustc_lint/src/async_fn_in_trait.rs
new file mode 100644
index 00000000000..ff4c81e2fc9
--- /dev/null
+++ b/compiler/rustc_lint/src/async_fn_in_trait.rs
@@ -0,0 +1,128 @@
+use crate::lints::AsyncFnInTraitDiag;
+use crate::LateContext;
+use crate::LateLintPass;
+use rustc_hir as hir;
+use rustc_trait_selection::traits::error_reporting::suggestions::suggest_desugaring_async_fn_to_impl_future_in_trait;
+
+declare_lint! {
+    /// The `async_fn_in_trait` lint detects use of `async fn` in the
+    /// definition of a publicly-reachable trait.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// # #![feature(async_fn_in_trait)]
+    /// pub trait Trait {
+    ///     async fn method(&self);
+    /// }
+    /// # fn main() {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// When `async fn` is used in a trait definition, the trait does not
+    /// promise that the opaque [`Future`] returned by the associated function
+    /// or method will implement any [auto traits] such as [`Send`]. This may
+    /// be surprising and may make the associated functions or methods on the
+    /// trait less useful than intended. On traits exposed publicly from a
+    /// crate, this may affect downstream crates whose authors cannot alter
+    /// the trait definition.
+    ///
+    /// For example, this code is invalid:
+    ///
+    /// ```rust,compile_fail
+    /// # #![feature(async_fn_in_trait)]
+    /// pub trait Trait {
+    ///     async fn method(&self) {}
+    /// }
+    ///
+    /// fn test<T: Trait>(x: T) {
+    ///     fn spawn<T: Send>(_: T) {}
+    ///     spawn(x.method()); // Not OK.
+    /// }
+    /// ```
+    ///
+    /// This lint exists to warn authors of publicly-reachable traits that
+    /// they may want to consider desugaring the `async fn` to a normal `fn`
+    /// that returns an opaque `impl Future<..> + Send` type.
+    ///
+    /// For example, instead of:
+    ///
+    /// ```rust
+    /// # #![feature(async_fn_in_trait)]
+    /// pub trait Trait {
+    ///     async fn method(&self) {}
+    /// }
+    /// ```
+    ///
+    /// The author of the trait may want to write:
+    ///
+    ///
+    /// ```rust
+    /// # #![feature(return_position_impl_trait_in_trait)]
+    /// use core::future::Future;
+    /// pub trait Trait {
+    ///     fn method(&self) -> impl Future<Output = ()> + Send { async {} }
+    /// }
+    /// ```
+    ///
+    /// This still allows the use of `async fn` within impls of the trait.
+    /// However, it also means that the trait will never be compatible with
+    /// impls where the returned [`Future`] of the method does not implement
+    /// `Send`.
+    ///
+    /// Conversely, if the trait is used only locally, if it is never used in
+    /// generic functions, or if it is only used in single-threaded contexts
+    /// that do not care whether the returned [`Future`] implements [`Send`],
+    /// then the lint may be suppressed.
+    ///
+    /// [`Future`]: https://doc.rust-lang.org/core/future/trait.Future.html
+    /// [`Send`]: https://doc.rust-lang.org/core/marker/trait.Send.html
+    /// [auto traits]: https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits
+    pub ASYNC_FN_IN_TRAIT,
+    Warn,
+    "use of `async fn` in definition of a publicly-reachable trait"
+}
+
+declare_lint_pass!(
+    /// Lint for use of `async fn` in the definition of a publicly-reachable
+    /// trait.
+    AsyncFnInTrait => [ASYNC_FN_IN_TRAIT]
+);
+
+impl<'tcx> LateLintPass<'tcx> for AsyncFnInTrait {
+    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'tcx>) {
+        if let hir::TraitItemKind::Fn(sig, body) = item.kind
+            && let hir::IsAsync::Async(async_span) = sig.header.asyncness
+        {
+            // RTN can be used to bound `async fn` in traits in a better way than "always"
+            if cx.tcx.features().return_type_notation {
+                return;
+            }
+
+            // Only need to think about library implications of reachable traits
+            if !cx.tcx.effective_visibilities(()).is_reachable(item.owner_id.def_id) {
+                return;
+            }
+
+            let hir::FnRetTy::Return(hir::Ty { kind: hir::TyKind::OpaqueDef(def, ..), .. }) =
+                sig.decl.output
+            else {
+                // This should never happen, but let's not ICE.
+                return;
+            };
+            let sugg = suggest_desugaring_async_fn_to_impl_future_in_trait(
+                cx.tcx,
+                sig,
+                body,
+                def.owner_id.def_id,
+                " + Send",
+            );
+            cx.tcx.emit_spanned_lint(ASYNC_FN_IN_TRAIT, item.hir_id(), async_span, AsyncFnInTraitDiag {
+                sugg
+            });
+        }
+    }
+}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 72c103f2d4a..af2132fb899 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -50,6 +50,7 @@ extern crate rustc_session;
 extern crate tracing;
 
 mod array_into_iter;
+mod async_fn_in_trait;
 pub mod builtin;
 mod context;
 mod deref_into_dyn_supertrait;
@@ -96,6 +97,7 @@ use rustc_session::lint::builtin::{
 };
 
 use array_into_iter::ArrayIntoIter;
+use async_fn_in_trait::AsyncFnInTrait;
 use builtin::*;
 use deref_into_dyn_supertrait::*;
 use drop_forget_useless::*;
@@ -234,6 +236,7 @@ late_lint_methods!(
             MapUnitFn: MapUnitFn,
             MissingDebugImplementations: MissingDebugImplementations,
             MissingDoc: MissingDoc,
+            AsyncFnInTrait: AsyncFnInTrait,
         ]
     ]
 );
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index c091c260a47..c776d3bb7fe 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -771,12 +771,16 @@ pub enum InvalidReferenceCastingDiag {
     BorrowAsMut {
         #[label]
         orig_cast: Option<Span>,
+        #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)]
+        ty_has_interior_mutability: Option<()>,
     },
     #[diag(lint_invalid_reference_casting_assign_to_ref)]
     #[note(lint_invalid_reference_casting_note_book)]
     AssignToRef {
         #[label]
         orig_cast: Option<Span>,
+        #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)]
+        ty_has_interior_mutability: Option<()>,
     },
 }
 
@@ -1818,3 +1822,24 @@ pub struct UnusedAllocationDiag;
 #[derive(LintDiagnostic)]
 #[diag(lint_unused_allocation_mut)]
 pub struct UnusedAllocationMutDiag;
+
+pub struct AsyncFnInTraitDiag {
+    pub sugg: Option<Vec<(Span, String)>>,
+}
+
+impl<'a> DecorateLint<'a, ()> for AsyncFnInTraitDiag {
+    fn decorate_lint<'b>(
+        self,
+        diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
+    ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
+        diag.note(fluent::lint_note);
+        if let Some(sugg) = self.sugg {
+            diag.multipart_suggestion(fluent::lint_suggestion, sugg, Applicability::MaybeIncorrect);
+        }
+        diag
+    }
+
+    fn msg(&self) -> rustc_errors::DiagnosticMessage {
+        fluent::lint_async_fn_in_trait
+    }
+}
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index 79b0b32bef2..c24846ca939 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -37,8 +37,6 @@ declare_lint! {
     ///     type Assoc: Duh;
     /// }
     ///
-    /// struct Struct;
-    ///
     /// impl<F: Duh> Trait for F {
     ///     type Assoc = F;
     /// }
@@ -53,12 +51,12 @@ declare_lint! {
     /// {{produces}}
     ///
     /// In this example, `test` declares that the associated type `Assoc` for
-    /// `impl Trait` is `impl Sized`, which does not satisfy the `Send` bound
+    /// `impl Trait` is `impl Sized`, which does not satisfy the bound `Duh`
     /// on the associated type.
     ///
     /// Although the hidden type, `i32` does satisfy this bound, we do not
     /// consider the return type to be well-formed with this lint. It can be
-    /// fixed by changing `Tait = impl Sized` into `Tait = impl Sized + Send`.
+    /// fixed by changing `Tait = impl Sized` into `Tait = impl Sized + Duh`.
     pub OPAQUE_HIDDEN_INFERRED_BOUND,
     Warn,
     "detects the use of nested `impl Trait` types in associated type bounds that are not general enough"
@@ -79,9 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
         for (pred, pred_span) in
             cx.tcx.explicit_item_bounds(def_id).instantiate_identity_iter_copied()
         {
-            // Liberate bound regions in the predicate since we
-            // don't actually care about lifetimes in this check.
-            let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind());
+            let predicate = infcx.instantiate_binder_with_placeholders(pred.kind());
             let ty::ClauseKind::Projection(proj) = predicate else {
                 continue;
             };
diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs
index 39def599be8..0c52fbaf78c 100644
--- a/compiler/rustc_lint/src/reference_casting.rs
+++ b/compiler/rustc_lint/src/reference_casting.rs
@@ -43,19 +43,19 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
 
         let init = cx.expr_or_init(e);
 
-        let orig_cast = if is_cast_from_const_to_mut(cx, init) {
-            if init.span != e.span { Some(init.span) } else { None }
-        } else {
+        let Some(ty_has_interior_mutability) = is_cast_from_const_to_mut(cx, init) else {
             return;
         };
+        let orig_cast = if init.span != e.span { Some(init.span) } else { None };
+        let ty_has_interior_mutability = ty_has_interior_mutability.then_some(());
 
         cx.emit_spanned_lint(
             INVALID_REFERENCE_CASTING,
             expr.span,
             if is_assignment {
-                InvalidReferenceCastingDiag::AssignToRef { orig_cast }
+                InvalidReferenceCastingDiag::AssignToRef { orig_cast, ty_has_interior_mutability }
             } else {
-                InvalidReferenceCastingDiag::BorrowAsMut { orig_cast }
+                InvalidReferenceCastingDiag::BorrowAsMut { orig_cast, ty_has_interior_mutability }
             },
         );
     }
@@ -104,7 +104,10 @@ fn is_operation_we_care_about<'tcx>(
     deref_assign_or_addr_of(e).or_else(|| ptr_write(cx, e))
 }
 
-fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, orig_expr: &'tcx Expr<'tcx>) -> bool {
+fn is_cast_from_const_to_mut<'tcx>(
+    cx: &LateContext<'tcx>,
+    orig_expr: &'tcx Expr<'tcx>,
+) -> Option<bool> {
     let mut need_check_freeze = false;
     let mut e = orig_expr;
 
@@ -112,7 +115,7 @@ fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, orig_expr: &'tcx Expr
 
     // Bail out early if the end type is **not** a mutable pointer.
     if !matches!(end_ty.kind(), ty::RawPtr(TypeAndMut { ty: _, mutbl: Mutability::Mut })) {
-        return false;
+        return None;
     }
 
     loop {
@@ -155,10 +158,11 @@ fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, orig_expr: &'tcx Expr
         //
         // We also consider non concrete skeleton types (ie generics)
         // to be an issue since there is no way to make it safe for abitrary types.
-        !need_check_freeze
-            || inner_ty.is_freeze(cx.tcx, cx.param_env)
-            || !inner_ty.has_concrete_skeleton()
+        let inner_ty_has_interior_mutability =
+            !inner_ty.is_freeze(cx.tcx, cx.param_env) && inner_ty.has_concrete_skeleton();
+        (!need_check_freeze || !inner_ty_has_interior_mutability)
+            .then_some(inner_ty_has_interior_mutability)
     } else {
-        false
+        None
     }
 }
diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml
index 34556df3c6d..3880f25a9ba 100644
--- a/compiler/rustc_llvm/Cargo.toml
+++ b/compiler/rustc_llvm/Cargo.toml
@@ -3,10 +3,6 @@ name = "rustc_llvm"
 version = "0.0.0"
 edition = "2021"
 
-[features]
-static-libstdcpp = []
-emscripten = []
-
 [dependencies]
 libc = "0.2.73"
 
diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs
index e7b80c64184..3e43bcb3b8f 100644
--- a/compiler/rustc_log/src/lib.rs
+++ b/compiler/rustc_log/src/lib.rs
@@ -23,10 +23,10 @@
 //! }
 //! ```
 //!
-//! Now `LOG=debug cargo run` will run your minimal main.rs and show
+//! Now `LOG=debug cargo +nightly run` will run your minimal main.rs and show
 //! rustc's debug logging. In a workflow like this, one might also add
 //! `std::env::set_var("LOG", "debug")` to the top of main so that `cargo
-//! run` by itself is sufficient to get logs.
+//! +nightly run` by itself is sufficient to get logs.
 //!
 //! The reason rustc_log is a tiny separate crate, as opposed to exposing the
 //! same things in rustc_driver only, is to enable the above workflow. If you
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 952c796f52e..1d573a746b9 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -8,7 +8,7 @@
 macro_rules! arena_types {
     ($macro:path) => (
         $macro!([
-            [] layout: rustc_target::abi::LayoutS,
+            [] layout: rustc_target::abi::LayoutS<rustc_target::abi::FieldIdx, rustc_target::abi::VariantIdx>,
             [] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
             // AdtDef are interned and compared by address
             [decode] adt_def: rustc_middle::ty::AdtDefData,
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 7c8a57b840b..8f63ed757ba 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -288,7 +288,16 @@ impl<'tcx> Const<'tcx> {
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Option<ScalarInt> {
-        self.try_eval_scalar(tcx, param_env)?.try_to_int().ok()
+        match self {
+            // If the constant is already evaluated, we shortcut here.
+            Const::Ty(c) if let ty::ConstKind::Value(valtree) = c.kind() => {
+                valtree.try_to_scalar_int()
+            },
+            // This is a more general form of the previous case.
+            _ => {
+                self.try_eval_scalar(tcx, param_env)?.try_to_int().ok()
+            },
+        }
     }
 
     #[inline]
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index 9ef67392291..a6d6f6f5df4 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -18,11 +18,6 @@ rustc_index::newtype_index! {
 
 impl CounterId {
     pub const START: Self = Self::from_u32(0);
-
-    #[inline(always)]
-    pub fn next_id(self) -> Self {
-        Self::from_u32(self.as_u32() + 1)
-    }
 }
 
 rustc_index::newtype_index! {
@@ -38,11 +33,6 @@ rustc_index::newtype_index! {
 
 impl ExpressionId {
     pub const START: Self = Self::from_u32(0);
-
-    #[inline(always)]
-    pub fn next_id(self) -> Self {
-        Self::from_u32(self.as_u32() + 1)
-    }
 }
 
 /// Operand of a coverage-counter expression.
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 0bb1c66da0c..7534c9c0a68 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -830,22 +830,6 @@ pub struct LocalDecl<'tcx> {
     // FIXME(matthewjasper) Don't store in this in `Body`
     pub local_info: ClearCrossCrate<Box<LocalInfo<'tcx>>>,
 
-    /// `true` if this is an internal local.
-    ///
-    /// These locals are not based on types in the source code and are only used
-    /// for a few desugarings at the moment.
-    ///
-    /// The generator transformation will sanity check the locals which are live
-    /// across a suspension point against the type components of the generator
-    /// which type checking knows are live across a suspension point. We need to
-    /// flag drop flags to avoid triggering this check as they are introduced
-    /// outside of type inference.
-    ///
-    /// This should be sound because the drop flags are fully algebraic, and
-    /// therefore don't affect the auto-trait or outlives properties of the
-    /// generator.
-    pub internal: bool,
-
     /// The type of this local.
     pub ty: Ty<'tcx>,
 
@@ -1058,7 +1042,7 @@ impl<'tcx> LocalDecl<'tcx> {
         self.source_info.span.desugaring_kind().is_some()
     }
 
-    /// Creates a new `LocalDecl` for a temporary: mutable, non-internal.
+    /// Creates a new `LocalDecl` for a temporary, mutable.
     #[inline]
     pub fn new(ty: Ty<'tcx>, span: Span) -> Self {
         Self::with_source_info(ty, SourceInfo::outermost(span))
@@ -1070,20 +1054,12 @@ impl<'tcx> LocalDecl<'tcx> {
         LocalDecl {
             mutability: Mutability::Mut,
             local_info: ClearCrossCrate::Set(Box::new(LocalInfo::Boring)),
-            internal: false,
             ty,
             user_ty: None,
             source_info,
         }
     }
 
-    /// Converts `self` into same `LocalDecl` except tagged as internal.
-    #[inline]
-    pub fn internal(mut self) -> Self {
-        self.internal = true;
-        self
-    }
-
     /// Converts `self` into same `LocalDecl` except tagged as immutable.
     #[inline]
     pub fn immutable(mut self) -> Self {
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index da486c3465a..ce2ddec0116 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -127,7 +127,7 @@ impl<'tcx> MirPatch<'tcx> {
         Location { block: bb, statement_index: offset }
     }
 
-    pub fn new_internal_with_info(
+    pub fn new_local_with_info(
         &mut self,
         ty: Ty<'tcx>,
         span: Span,
@@ -135,7 +135,7 @@ impl<'tcx> MirPatch<'tcx> {
     ) -> Local {
         let index = self.next_local;
         self.next_local += 1;
-        let mut new_decl = LocalDecl::new(ty, span).internal();
+        let mut new_decl = LocalDecl::new(ty, span);
         **new_decl.local_info.as_mut().assert_crate_local() = local_info;
         self.new_locals.push(new_decl);
         Local::new(index)
@@ -148,13 +148,6 @@ impl<'tcx> MirPatch<'tcx> {
         Local::new(index)
     }
 
-    pub fn new_internal(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
-        let index = self.next_local;
-        self.next_local += 1;
-        self.new_locals.push(LocalDecl::new(ty, span).internal());
-        Local::new(index)
-    }
-
     pub fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock {
         let block = BasicBlock::new(self.patch_map.len());
         debug!("MirPatch: new_block: {:?}: {:?}", block, data);
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 76567c3f6b0..c5e3ee575e1 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -16,7 +16,7 @@ use rustc_middle::mir::interpret::{
     Pointer, Provenance,
 };
 use rustc_middle::mir::visit::Visitor;
-use rustc_middle::mir::*;
+use rustc_middle::mir::{self, *};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_target::abi::Size;
 
@@ -685,10 +685,13 @@ impl Debug for Statement<'_> {
             AscribeUserType(box (ref place, ref c_ty), ref variance) => {
                 write!(fmt, "AscribeUserType({place:?}, {variance:?}, {c_ty:?})")
             }
-            Coverage(box self::Coverage { ref kind, code_region: Some(ref rgn) }) => {
-                write!(fmt, "Coverage::{kind:?} for {rgn:?}")
+            Coverage(box mir::Coverage { ref kind, ref code_regions }) => {
+                if code_regions.is_empty() {
+                    write!(fmt, "Coverage::{kind:?}")
+                } else {
+                    write!(fmt, "Coverage::{kind:?} for {code_regions:?}")
+                }
             }
-            Coverage(box ref coverage) => write!(fmt, "Coverage::{:?}", coverage.kind),
             Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"),
             ConstEvalCounter => write!(fmt, "ConstEvalCounter"),
             Nop => write!(fmt, "nop"),
@@ -1103,6 +1106,7 @@ fn pre_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) ->
     for &elem in projection.iter().rev() {
         match elem {
             ProjectionElem::OpaqueCast(_)
+            | ProjectionElem::Subtype(_)
             | ProjectionElem::Downcast(_, _)
             | ProjectionElem::Field(_, _) => {
                 write!(fmt, "(").unwrap();
@@ -1125,6 +1129,9 @@ fn post_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) ->
             ProjectionElem::OpaqueCast(ty) => {
                 write!(fmt, " as {ty})")?;
             }
+            ProjectionElem::Subtype(ty) => {
+                write!(fmt, " as subtype {ty})")?;
+            }
             ProjectionElem::Downcast(Some(name), _index) => {
                 write!(fmt, " as {name})")?;
             }
diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs
index 5ac108bc829..5864acaed7b 100644
--- a/compiler/rustc_middle/src/mir/statement.rs
+++ b/compiler/rustc_middle/src/mir/statement.rs
@@ -57,6 +57,7 @@ impl<V, T> ProjectionElem<V, T> {
             Self::Field(_, _)
             | Self::Index(_)
             | Self::OpaqueCast(_)
+            | Self::Subtype(_)
             | Self::ConstantIndex { .. }
             | Self::Subslice { .. }
             | Self::Downcast(_, _) => false,
@@ -70,6 +71,7 @@ impl<V, T> ProjectionElem<V, T> {
             Self::Deref | Self::Index(_) => false,
             Self::Field(_, _)
             | Self::OpaqueCast(_)
+            | Self::Subtype(_)
             | Self::ConstantIndex { .. }
             | Self::Subslice { .. }
             | Self::Downcast(_, _) => true,
@@ -95,6 +97,7 @@ impl<V, T> ProjectionElem<V, T> {
             | Self::Field(_, _) => true,
             Self::ConstantIndex { from_end: true, .. }
             | Self::Index(_)
+            | Self::Subtype(_)
             | Self::OpaqueCast(_)
             | Self::Subslice { .. } => false,
         }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 55f895f73b4..30fc69caa3b 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -514,7 +514,7 @@ pub enum FakeReadCause {
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct Coverage {
     pub kind: CoverageKind,
-    pub code_region: Option<CodeRegion>,
+    pub code_regions: Vec<CodeRegion>,
 }
 
 #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
@@ -996,7 +996,7 @@ pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
 ///
 /// [UCG#319]: https://github.com/rust-lang/unsafe-code-guidelines/issues/319
 ///
-/// Rust currently requires that every place obey those two rules. This is checked by MIRI and taken
+/// Rust currently requires that every place obey those two rules. This is checked by Miri and taken
 /// advantage of by codegen (via `gep inbounds`). That is possibly subject to change.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, HashStable, TypeFoldable, TypeVisitable)]
 pub struct Place<'tcx> {
@@ -1075,6 +1075,18 @@ pub enum ProjectionElem<V, T> {
     /// Like an explicit cast from an opaque type to a concrete type, but without
     /// requiring an intermediate variable.
     OpaqueCast(T),
+
+    /// A `Subtype(T)` projection is applied to any `StatementKind::Assign` where
+    /// type of lvalue doesn't match the type of rvalue, the primary goal is making subtyping
+    /// explicit during optimizations and codegen.
+    ///
+    /// This projection doesn't impact the runtime behavior of the program except for potentially changing
+    /// some type metadata of the interpreter or codegen backend.
+    ///
+    /// This goal is achieved with mir_transform pass `Subtyper`, which runs right after
+    /// borrowchecker, as we only care about subtyping that can affect trait selection and
+    /// `TypeId`.
+    Subtype(T),
 }
 
 /// Alias for projections as they appear in places, where the base is a place
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 01c04f63890..44ae75e2de7 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -69,7 +69,7 @@ impl<'tcx> PlaceTy<'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         elem: &ProjectionElem<V, T>,
         mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>,
-        mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>,
+        mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>,
     ) -> PlaceTy<'tcx>
     where
         V: ::std::fmt::Debug,
@@ -110,7 +110,12 @@ impl<'tcx> PlaceTy<'tcx> {
                 PlaceTy { ty: self.ty, variant_index: Some(index) }
             }
             ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
-            ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast(&self, ty)),
+            ProjectionElem::OpaqueCast(ty) => {
+                PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
+            }
+            ProjectionElem::Subtype(ty) => {
+                PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
+            }
         };
         debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
         answer
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 51ec6da1ac8..9bd682d37ab 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -815,7 +815,6 @@ macro_rules! make_mir_visitor {
                     ty,
                     user_ty,
                     source_info,
-                    internal: _,
                     local_info: _,
                 } = local_decl;
 
@@ -1109,6 +1108,11 @@ macro_rules! visit_place_fns {
                     self.visit_ty(&mut new_ty, TyContext::Location(location));
                     if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None }
                 }
+                PlaceElem::Subtype(ty) => {
+                    let mut new_ty = ty;
+                    self.visit_ty(&mut new_ty, TyContext::Location(location));
+                    if ty != new_ty { Some(PlaceElem::Subtype(new_ty)) } else { None }
+                }
                 PlaceElem::Deref
                 | PlaceElem::ConstantIndex { .. }
                 | PlaceElem::Subslice { .. }
@@ -1175,7 +1179,9 @@ macro_rules! visit_place_fns {
             location: Location,
         ) {
             match elem {
-                ProjectionElem::OpaqueCast(ty) | ProjectionElem::Field(_, ty) => {
+                ProjectionElem::OpaqueCast(ty)
+                | ProjectionElem::Subtype(ty)
+                | ProjectionElem::Field(_, ty) => {
                     self.visit_ty(ty, TyContext::Location(location));
                 }
                 ProjectionElem::Index(local) => {
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index 09517200b0d..85181720d17 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -18,20 +18,20 @@ use crate::ty::{self, InferConst, Ty, TyCtxt};
 /// Like subtyping, matching is really a binary relation, so the only
 /// important thing about the result is Ok/Err. Also, matching never
 /// affects any type variables or unification state.
-pub struct Match<'tcx> {
+pub struct MatchAgainstFreshVars<'tcx> {
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
 }
 
-impl<'tcx> Match<'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Match<'tcx> {
-        Match { tcx, param_env }
+impl<'tcx> MatchAgainstFreshVars<'tcx> {
+    pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> MatchAgainstFreshVars<'tcx> {
+        MatchAgainstFreshVars { tcx, param_env }
     }
 }
 
-impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
+impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
     fn tag(&self) -> &'static str {
-        "Match"
+        "MatchAgainstFreshVars"
     }
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index dff7ff8c66b..e4069e11df2 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -348,9 +348,10 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> {
 
 impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [ty::ValTree<'tcx>] {
     fn decode(decoder: &mut D) -> &'tcx Self {
-        decoder.interner().arena.alloc_from_iter(
-            (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(),
-        )
+        decoder
+            .interner()
+            .arena
+            .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
     }
 }
 
@@ -368,9 +369,10 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AdtDef<'tcx> {
 
 impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] {
     fn decode(decoder: &mut D) -> &'tcx Self {
-        decoder.interner().arena.alloc_from_iter(
-            (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(),
-        )
+        decoder
+            .interner()
+            .arena
+            .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index c06b8b2dfa0..83adbc3c790 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -152,7 +152,7 @@ pub struct CtxtInterners<'tcx> {
     const_: InternedSet<'tcx, ConstData<'tcx>>,
     const_allocation: InternedSet<'tcx, Allocation>,
     bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
-    layout: InternedSet<'tcx, LayoutS>,
+    layout: InternedSet<'tcx, LayoutS<FieldIdx, VariantIdx>>,
     adt_def: InternedSet<'tcx, AdtDefData>,
     external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
     predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>,
@@ -1521,7 +1521,7 @@ direct_interners! {
     region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
     const_: intern_const(ConstData<'tcx>): Const -> Const<'tcx>,
     const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
-    layout: pub mk_layout(LayoutS): Layout -> Layout<'tcx>,
+    layout: pub mk_layout(LayoutS<FieldIdx, VariantIdx>): Layout -> Layout<'tcx>,
     adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
     external_constraints: pub mk_external_constraints(ExternalConstraintsData<'tcx>):
         ExternalConstraints -> ExternalConstraints<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 0b0a708e42b..0a425be52ff 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -617,12 +617,17 @@ impl<'tcx> Instance<'tcx> {
         v: EarlyBinder<T>,
     ) -> Result<T, NormalizationError<'tcx>>
     where
-        T: TypeFoldable<TyCtxt<'tcx>> + Clone,
+        T: TypeFoldable<TyCtxt<'tcx>>,
     {
         if let Some(args) = self.args_for_mir_body() {
             tcx.try_instantiate_and_normalize_erasing_regions(args, param_env, v)
         } else {
-            tcx.try_normalize_erasing_regions(param_env, v.skip_binder())
+            // We're using `instantiate_identity` as e.g.
+            // `FnPtrShim` is separately generated for every
+            // instantiation of the `FnDef`, so the MIR body
+            // is already instantiated. Any generic parameters it
+            // contains are generic parameters from the caller.
+            tcx.try_normalize_erasing_regions(param_env, v.instantiate_identity())
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index aa1e7f216a0..b7d2e3d9493 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -578,11 +578,6 @@ impl rustc_errors::IntoDiagnosticArg for Clause<'_> {
 pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>);
 
 impl<'tcx> Clause<'tcx> {
-    pub fn from_projection_clause(tcx: TyCtxt<'tcx>, pred: PolyProjectionPredicate<'tcx>) -> Self {
-        let pred: Predicate<'tcx> = pred.to_predicate(tcx);
-        pred.expect_clause()
-    }
-
     pub fn as_predicate(self) -> Predicate<'tcx> {
         Predicate(self.0)
     }
@@ -1296,12 +1291,25 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef
     }
 }
 
+impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+        PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx)
+    }
+}
+
 impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx)
     }
 }
 
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> {
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+        let p: Predicate<'tcx> = self.to_predicate(tcx);
+        p.expect_clause()
+    }
+}
+
 impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
         let p: Predicate<'tcx> = self.to_predicate(tcx);
@@ -1340,9 +1348,10 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ProjectionPredicate<'tcx> {
     }
 }
 
-impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx)
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> {
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+        let p: Predicate<'tcx> = self.to_predicate(tcx);
+        p.expect_clause()
     }
 }
 
@@ -1743,30 +1752,9 @@ impl<'tcx> ParamEnv<'tcx> {
         Self::new(List::empty(), self.reveal())
     }
 
-    /// Creates a suitable environment in which to perform trait
-    /// queries on the given value. When type-checking, this is simply
-    /// the pair of the environment plus value. But when reveal is set to
-    /// All, then if `value` does not reference any type parameters, we will
-    /// pair it with the empty environment. This improves caching and is generally
-    /// invisible.
-    ///
-    /// N.B., we preserve the environment when type-checking because it
-    /// is possible for the user to have wacky where-clauses like
-    /// `where Box<u32>: Copy`, which are clearly never
-    /// satisfiable. We generally want to behave as if they were true,
-    /// although the surrounding function is never reachable.
+    /// Creates a pair of param-env and value for use in queries.
     pub fn and<T: TypeVisitable<TyCtxt<'tcx>>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
-        match self.reveal() {
-            Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
-
-            Reveal::All => {
-                if value.is_global() {
-                    ParamEnvAnd { param_env: self.without_caller_bounds(), value }
-                } else {
-                    ParamEnvAnd { param_env: self, value }
-                }
-            }
-        }
+        ParamEnvAnd { param_env: self, value }
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 1e57392e0e7..e5f418bbb4b 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -725,7 +725,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
                 self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx)
             }
             ExistentialPredicate::Projection(p) => {
-                ty::Clause::from_projection_clause(tcx, self.rebind(p.with_self_ty(tcx, self_ty)))
+                self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx)
             }
             ExistentialPredicate::AutoTrait(did) => {
                 let generics = tcx.generics_of(did);
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 2e7ef265a93..4aff406b376 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -102,7 +102,7 @@ fn convert_to_hir_projections_and_truncate_for_capture(
                 continue;
             }
             // These do not affect anything, they just make sure we know the right type.
-            ProjectionElem::OpaqueCast(_) => continue,
+            ProjectionElem::OpaqueCast(_) | ProjectionElem::Subtype(..) => continue,
             ProjectionElem::Index(..)
             | ProjectionElem::ConstantIndex { .. }
             | ProjectionElem::Subslice { .. } => {
@@ -709,6 +709,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     ProjectionElem::Field(..)
                     | ProjectionElem::Downcast(..)
                     | ProjectionElem::OpaqueCast(..)
+                    | ProjectionElem::Subtype(..)
                     | ProjectionElem::ConstantIndex { .. }
                     | ProjectionElem::Subslice { .. } => (),
                 }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index d4089eef483..afb65ffbe8c 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -183,7 +183,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // The `Box<T>` temporary created here is not a part of the HIR,
                 // and therefore is not considered during generator auto-trait
                 // determination. See the comment about `box` at `yield_in_scope`.
-                let result = this.local_decls.push(LocalDecl::new(expr.ty, expr_span).internal());
+                let result = this.local_decls.push(LocalDecl::new(expr.ty, expr_span));
                 this.cfg.push(
                     block,
                     Statement { source_info, kind: StatementKind::StorageLive(result) },
diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
index c8910c272b1..a4ab365fa9a 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
@@ -52,12 +52,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             let local_info = match expr.kind {
                 ExprKind::StaticRef { def_id, .. } => {
                     assert!(!this.tcx.is_thread_local_static(def_id));
-                    local_decl.internal = true;
                     LocalInfo::StaticRef { def_id, is_thread_local: false }
                 }
                 ExprKind::ThreadLocalRef(def_id) => {
                     assert!(this.tcx.is_thread_local_static(def_id));
-                    local_decl.internal = true;
                     LocalInfo::StaticRef { def_id, is_thread_local: true }
                 }
                 ExprKind::NamedConst { def_id, .. } | ExprKind::ConstParam { def_id, .. } => {
diff --git a/compiler/rustc_mir_build/src/build/expr/mod.rs b/compiler/rustc_mir_build/src/build/expr/mod.rs
index f5ae060d603..dfe85b858cd 100644
--- a/compiler/rustc_mir_build/src/build/expr/mod.rs
+++ b/compiler/rustc_mir_build/src/build/expr/mod.rs
@@ -44,7 +44,7 @@
 //! the most suitable spot to implement it, and then just let the
 //! other fns cycle around. The handoff works like this:
 //!
-//! - `into(place)` -> fallback is to create a rvalue with `as_rvalue` and assign it to `place`
+//! - `into(place)` -> fallback is to create an rvalue with `as_rvalue` and assign it to `place`
 //! - `as_rvalue` -> fallback is to create an Operand with `as_operand` and use `Rvalue::use`
 //! - `as_operand` -> either invokes `as_constant` or `as_temp`
 //! - `as_constant` -> (no fallback)
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 921a5ca1175..eb1c6a9824a 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -1798,7 +1798,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let fake_borrow_ty =
                     Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fake_borrow_deref_ty);
                 let mut fake_borrow_temp = LocalDecl::new(fake_borrow_ty, temp_span);
-                fake_borrow_temp.internal = self.local_decls[matched_place.local].internal;
                 fake_borrow_temp.local_info = ClearCrossCrate::Set(Box::new(LocalInfo::FakeBorrow));
                 let fake_borrow_temp = self.local_decls.push(fake_borrow_temp);
 
@@ -2268,7 +2267,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             ty: var_ty,
             user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) },
             source_info,
-            internal: false,
             local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::Var(
                 VarBindingForm {
                     binding_mode,
@@ -2298,7 +2296,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 ty: Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, var_ty),
                 user_ty: None,
                 source_info,
-                internal: false,
                 local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(
                     BindingForm::RefForGuard,
                 ))),
diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs
index c96e99ef0e7..c263de79c3b 100644
--- a/compiler/rustc_mir_build/src/build/misc.rs
+++ b/compiler/rustc_mir_build/src/build/misc.rs
@@ -15,9 +15,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// N.B., **No cleanup is scheduled for this temporary.** You should
     /// call `schedule_drop` once the temporary is initialized.
     pub(crate) fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
-        // Mark this local as internal to avoid temporaries with types not present in the
-        // user's code resulting in ICEs from the generator transform.
-        let temp = self.local_decls.push(LocalDecl::new(ty, span).internal());
+        let temp = self.local_decls.push(LocalDecl::new(ty, span));
         let place = Place::from(temp);
         debug!("temp: created temp {:?} with type {:?}", place, self.local_decls[temp].ty);
         place
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 4cf6a349af7..bc151cc7058 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -725,7 +725,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     // Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue`
     // statement.
     fn add_dummy_assignment(&mut self, span: Span, block: BasicBlock, source_info: SourceInfo) {
-        let local_decl = LocalDecl::new(Ty::new_unit(self.tcx), span).internal();
+        let local_decl = LocalDecl::new(Ty::new_unit(self.tcx), span);
         let temp_place = Place::from(self.local_decls.push(local_decl));
         self.cfg.push_assign_unit(block, source_info, temp_place, self.tcx);
     }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index b79beb1c537..3ee4befa121 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -50,6 +50,7 @@ use std::ops::RangeInclusive;
 
 use smallvec::{smallvec, SmallVec};
 
+use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS};
 use rustc_data_structures::captures::Captures;
 use rustc_hir::{HirId, RangeEnd};
 use rustc_index::Idx;
@@ -60,12 +61,11 @@ use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef};
 use rustc_session::lint;
 use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi::{FieldIdx, Integer, Size, VariantIdx, FIRST_VARIANT};
+use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT};
 
 use self::Constructor::*;
 use self::SliceKind::*;
 
-use super::compare_const_vals;
 use super::usefulness::{MatchCheckCtxt, PatCtxt};
 use crate::errors::{Overlap, OverlappingRangeEndpoints};
 
@@ -99,10 +99,6 @@ fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> {
 #[derive(Clone, PartialEq, Eq)]
 pub(crate) struct IntRange {
     range: RangeInclusive<u128>,
-    /// Keeps the bias used for encoding the range. It depends on the type of the range and
-    /// possibly the pointer size of the current architecture. The algorithm ensures we never
-    /// compare `IntRange`s with different types/architectures.
-    bias: u128,
 }
 
 impl IntRange {
@@ -120,37 +116,12 @@ impl IntRange {
     }
 
     #[inline]
-    fn integral_size_and_signed_bias(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Size, u128)> {
-        match *ty.kind() {
-            ty::Bool => Some((Size::from_bytes(1), 0)),
-            ty::Char => Some((Size::from_bytes(4), 0)),
-            ty::Int(ity) => {
-                let size = Integer::from_int_ty(&tcx, ity).size();
-                Some((size, 1u128 << (size.bits() as u128 - 1)))
-            }
-            ty::Uint(uty) => Some((Integer::from_uint_ty(&tcx, uty).size(), 0)),
-            _ => None,
-        }
-    }
-
-    #[inline]
-    fn from_constant<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        value: mir::Const<'tcx>,
-    ) -> Option<IntRange> {
-        let ty = value.ty();
-        let (target_size, bias) = Self::integral_size_and_signed_bias(tcx, ty)?;
-        let val = match value {
-            mir::Const::Ty(c) if let ty::ConstKind::Value(valtree) = c.kind() => {
-                valtree.unwrap_leaf().to_bits(target_size).ok()
-            },
-            // This is a more general form of the previous case.
-            _ => value.try_eval_bits(tcx, param_env),
-        }?;
-
-        let val = val ^ bias;
-        Some(IntRange { range: val..=val, bias })
+    fn from_bits<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, bits: u128) -> IntRange {
+        let bias = IntRange::signed_bias(tcx, ty);
+        // Perform a shift if the underlying types are signed,
+        // which makes the interval arithmetic simpler.
+        let val = bits ^ bias;
+        IntRange { range: val..=val }
     }
 
     #[inline]
@@ -159,20 +130,18 @@ impl IntRange {
         lo: u128,
         hi: u128,
         ty: Ty<'tcx>,
-        end: &RangeEnd,
-    ) -> Option<IntRange> {
-        Self::is_integral(ty).then(|| {
-            // Perform a shift if the underlying types are signed,
-            // which makes the interval arithmetic simpler.
-            let bias = IntRange::signed_bias(tcx, ty);
-            let (lo, hi) = (lo ^ bias, hi ^ bias);
-            let offset = (*end == RangeEnd::Excluded) as u128;
-            if lo > hi || (lo == hi && *end == RangeEnd::Excluded) {
-                // This should have been caught earlier by E0030.
-                bug!("malformed range pattern: {}..={}", lo, (hi - offset));
-            }
-            IntRange { range: lo..=(hi - offset), bias }
-        })
+        end: RangeEnd,
+    ) -> IntRange {
+        // Perform a shift if the underlying types are signed,
+        // which makes the interval arithmetic simpler.
+        let bias = IntRange::signed_bias(tcx, ty);
+        let (lo, hi) = (lo ^ bias, hi ^ bias);
+        let offset = (end == RangeEnd::Excluded) as u128;
+        if lo > hi || (lo == hi && end == RangeEnd::Excluded) {
+            // This should have been caught earlier by E0030.
+            bug!("malformed range pattern: {}..={}", lo, (hi - offset));
+        }
+        IntRange { range: lo..=(hi - offset) }
     }
 
     // The return value of `signed_bias` should be XORed with an endpoint to encode/decode it.
@@ -194,7 +163,7 @@ impl IntRange {
         let (lo, hi) = self.boundaries();
         let (other_lo, other_hi) = other.boundaries();
         if lo <= other_hi && other_lo <= hi {
-            Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), bias: self.bias })
+            Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi) })
         } else {
             None
         }
@@ -221,7 +190,7 @@ impl IntRange {
     fn to_pat<'tcx>(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Pat<'tcx> {
         let (lo, hi) = self.boundaries();
 
-        let bias = self.bias;
+        let bias = IntRange::signed_bias(tcx, ty);
         let (lo, hi) = (lo ^ bias, hi ^ bias);
 
         let env = ty::ParamEnv::empty().and(ty);
@@ -304,8 +273,6 @@ impl IntRange {
 impl fmt::Debug for IntRange {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let (lo, hi) = self.boundaries();
-        let bias = self.bias;
-        let (lo, hi) = (lo ^ bias, hi ^ bias);
         write!(f, "{lo}")?;
         write!(f, "{}", RangeEnd::Included)?;
         write!(f, "{hi}")
@@ -402,7 +369,7 @@ impl SplitIntRange {
                     (JustBefore(n), AfterMax) => n..=u128::MAX,
                     _ => unreachable!(), // Ruled out by the sorting and filtering we did
                 };
-                IntRange { range, bias: self.range.bias }
+                IntRange { range }
             })
     }
 }
@@ -619,7 +586,8 @@ pub(super) enum Constructor<'tcx> {
     /// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
     IntRange(IntRange),
     /// Ranges of floating-point literal values (`2.0..=5.2`).
-    FloatRange(mir::Const<'tcx>, mir::Const<'tcx>, RangeEnd),
+    F32Range(IeeeFloat<SingleS>, IeeeFloat<SingleS>, RangeEnd),
+    F64Range(IeeeFloat<DoubleS>, IeeeFloat<DoubleS>, RangeEnd),
     /// String literals. Strings are not quite the same as `&[u8]` so we treat them separately.
     Str(mir::Const<'tcx>),
     /// Array and slice patterns.
@@ -634,7 +602,9 @@ pub(super) enum Constructor<'tcx> {
     /// Stands for constructors that are not seen in the matrix, as explained in the documentation
     /// for [`SplitWildcard`]. The carried `bool` is used for the `non_exhaustive_omitted_patterns`
     /// lint.
-    Missing { nonexhaustive_enum_missing_real_variants: bool },
+    Missing {
+        nonexhaustive_enum_missing_real_variants: bool,
+    },
     /// Wildcard pattern.
     Wildcard,
     /// Or-pattern.
@@ -722,7 +692,8 @@ impl<'tcx> Constructor<'tcx> {
             },
             Slice(slice) => slice.arity(),
             Str(..)
-            | FloatRange(..)
+            | F32Range(..)
+            | F64Range(..)
             | IntRange(..)
             | NonExhaustive
             | Opaque
@@ -795,21 +766,21 @@ impl<'tcx> Constructor<'tcx> {
             (Variant(self_id), Variant(other_id)) => self_id == other_id,
 
             (IntRange(self_range), IntRange(other_range)) => self_range.is_covered_by(other_range),
-            (
-                FloatRange(self_from, self_to, self_end),
-                FloatRange(other_from, other_to, other_end),
-            ) => {
-                match (
-                    compare_const_vals(pcx.cx.tcx, *self_to, *other_to, pcx.cx.param_env),
-                    compare_const_vals(pcx.cx.tcx, *self_from, *other_from, pcx.cx.param_env),
-                ) {
-                    (Some(to), Some(from)) => {
-                        (from == Ordering::Greater || from == Ordering::Equal)
-                            && (to == Ordering::Less
-                                || (other_end == self_end && to == Ordering::Equal))
+            (F32Range(self_from, self_to, self_end), F32Range(other_from, other_to, other_end)) => {
+                self_from.ge(other_from)
+                    && match self_to.partial_cmp(other_to) {
+                        Some(Ordering::Less) => true,
+                        Some(Ordering::Equal) => other_end == self_end,
+                        _ => false,
+                    }
+            }
+            (F64Range(self_from, self_to, self_end), F64Range(other_from, other_to, other_end)) => {
+                self_from.ge(other_from)
+                    && match self_to.partial_cmp(other_to) {
+                        Some(Ordering::Less) => true,
+                        Some(Ordering::Equal) => other_end == self_end,
+                        _ => false,
                     }
-                    _ => false,
-                }
             }
             (Str(self_val), Str(other_val)) => {
                 // FIXME Once valtrees are available we can directly use the bytes
@@ -859,7 +830,7 @@ impl<'tcx> Constructor<'tcx> {
                 .any(|other| slice.is_covered_by(other)),
             // This constructor is never covered by anything else
             NonExhaustive => false,
-            Str(..) | FloatRange(..) | Opaque | Missing { .. } | Wildcard | Or => {
+            Str(..) | F32Range(..) | F64Range(..) | Opaque | Missing { .. } | Wildcard | Or => {
                 span_bug!(pcx.span, "found unexpected ctor in all_ctors: {:?}", self)
             }
         }
@@ -896,7 +867,7 @@ impl<'tcx> SplitWildcard<'tcx> {
         let make_range = |start, end| {
             IntRange(
                 // `unwrap()` is ok because we know the type is an integer.
-                IntRange::from_range(cx.tcx, start, end, pcx.ty, &RangeEnd::Included).unwrap(),
+                IntRange::from_range(cx.tcx, start, end, pcx.ty, RangeEnd::Included),
             )
         };
         // This determines the set of all possible constructors for the type `pcx.ty`. For numbers,
@@ -1203,7 +1174,8 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
                 _ => bug!("bad slice pattern {:?} {:?}", constructor, pcx),
             },
             Str(..)
-            | FloatRange(..)
+            | F32Range(..)
+            | F64Range(..)
             | IntRange(..)
             | NonExhaustive
             | Opaque
@@ -1343,50 +1315,78 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
                 }
             }
             PatKind::Constant { value } => {
-                if let Some(int_range) = IntRange::from_constant(cx.tcx, cx.param_env, *value) {
-                    ctor = IntRange(int_range);
-                    fields = Fields::empty();
-                } else {
-                    match pat.ty.kind() {
-                        ty::Float(_) => {
-                            ctor = FloatRange(*value, *value, RangeEnd::Included);
-                            fields = Fields::empty();
-                        }
-                        ty::Ref(_, t, _) if t.is_str() => {
-                            // We want a `&str` constant to behave like a `Deref` pattern, to be compatible
-                            // with other `Deref` patterns. This could have been done in `const_to_pat`,
-                            // but that causes issues with the rest of the matching code.
-                            // So here, the constructor for a `"foo"` pattern is `&` (represented by
-                            // `Single`), and has one field. That field has constructor `Str(value)` and no
-                            // fields.
-                            // Note: `t` is `str`, not `&str`.
-                            let subpattern =
-                                DeconstructedPat::new(Str(*value), Fields::empty(), *t, pat.span);
-                            ctor = Single;
-                            fields = Fields::singleton(cx, subpattern)
-                        }
-                        // All constants that can be structurally matched have already been expanded
-                        // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
-                        // opaque.
-                        _ => {
-                            ctor = Opaque;
-                            fields = Fields::empty();
-                        }
+                match pat.ty.kind() {
+                    ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) => {
+                        ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
+                            Some(bits) => IntRange(IntRange::from_bits(cx.tcx, pat.ty, bits)),
+                            None => Opaque,
+                        };
+                        fields = Fields::empty();
+                    }
+                    ty::Float(ty::FloatTy::F32) => {
+                        ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
+                            Some(bits) => {
+                                use rustc_apfloat::Float;
+                                let value = rustc_apfloat::ieee::Single::from_bits(bits);
+                                F32Range(value, value, RangeEnd::Included)
+                            }
+                            None => Opaque,
+                        };
+                        fields = Fields::empty();
+                    }
+                    ty::Float(ty::FloatTy::F64) => {
+                        ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
+                            Some(bits) => {
+                                use rustc_apfloat::Float;
+                                let value = rustc_apfloat::ieee::Double::from_bits(bits);
+                                F64Range(value, value, RangeEnd::Included)
+                            }
+                            None => Opaque,
+                        };
+                        fields = Fields::empty();
+                    }
+                    ty::Ref(_, t, _) if t.is_str() => {
+                        // We want a `&str` constant to behave like a `Deref` pattern, to be compatible
+                        // with other `Deref` patterns. This could have been done in `const_to_pat`,
+                        // but that causes issues with the rest of the matching code.
+                        // So here, the constructor for a `"foo"` pattern is `&` (represented by
+                        // `Single`), and has one field. That field has constructor `Str(value)` and no
+                        // fields.
+                        // Note: `t` is `str`, not `&str`.
+                        let subpattern =
+                            DeconstructedPat::new(Str(*value), Fields::empty(), *t, pat.span);
+                        ctor = Single;
+                        fields = Fields::singleton(cx, subpattern)
+                    }
+                    // All constants that can be structurally matched have already been expanded
+                    // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
+                    // opaque.
+                    _ => {
+                        ctor = Opaque;
+                        fields = Fields::empty();
                     }
                 }
             }
-            &PatKind::Range(box PatRange { lo, hi, end }) => {
+            PatKind::Range(box PatRange { lo, hi, end }) => {
+                use rustc_apfloat::Float;
                 let ty = lo.ty();
-                ctor = if let Some(int_range) = IntRange::from_range(
-                    cx.tcx,
-                    lo.eval_bits(cx.tcx, cx.param_env),
-                    hi.eval_bits(cx.tcx, cx.param_env),
-                    ty,
-                    &end,
-                ) {
-                    IntRange(int_range)
-                } else {
-                    FloatRange(lo, hi, end)
+                let lo = lo.try_eval_bits(cx.tcx, cx.param_env).unwrap();
+                let hi = hi.try_eval_bits(cx.tcx, cx.param_env).unwrap();
+                ctor = match ty.kind() {
+                    ty::Char | ty::Int(_) | ty::Uint(_) => {
+                        IntRange(IntRange::from_range(cx.tcx, lo, hi, ty, *end))
+                    }
+                    ty::Float(ty::FloatTy::F32) => {
+                        let lo = rustc_apfloat::ieee::Single::from_bits(lo);
+                        let hi = rustc_apfloat::ieee::Single::from_bits(hi);
+                        F32Range(lo, hi, *end)
+                    }
+                    ty::Float(ty::FloatTy::F64) => {
+                        let lo = rustc_apfloat::ieee::Double::from_bits(lo);
+                        let hi = rustc_apfloat::ieee::Double::from_bits(hi);
+                        F64Range(lo, hi, *end)
+                    }
+                    _ => bug!("invalid type for range pattern: {}", ty),
                 };
                 fields = Fields::empty();
             }
@@ -1491,14 +1491,13 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
                 }
             }
             &Str(value) => PatKind::Constant { value },
-            &FloatRange(lo, hi, end) => PatKind::Range(Box::new(PatRange { lo, hi, end })),
             IntRange(range) => return range.to_pat(cx.tcx, self.ty),
             Wildcard | NonExhaustive => PatKind::Wild,
             Missing { .. } => bug!(
                 "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
                 `Missing` should have been processed in `apply_constructors`"
             ),
-            Opaque | Or => {
+            F32Range(..) | F64Range(..) | Opaque | Or => {
                 bug!("can't convert to pattern: {:?}", self)
             }
         };
@@ -1673,11 +1672,8 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> {
                 }
                 write!(f, "]")
             }
-            &FloatRange(lo, hi, end) => {
-                write!(f, "{lo}")?;
-                write!(f, "{end}")?;
-                write!(f, "{hi}")
-            }
+            F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"),
+            F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"),
             IntRange(range) => write!(f, "{range:?}"), // Best-effort, will render e.g. `false` as `0..=0`
             Wildcard | Missing { .. } | NonExhaustive => write!(f, "_ : {:?}", self.ty),
             Or => {
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
index 7806e8f45d3..2a7f23ef6d2 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
@@ -57,6 +57,7 @@ impl<'tcx> Lift for PlaceElem<'tcx> {
                 ProjectionElem::ConstantIndex { offset, min_length, from_end }
             }
             ProjectionElem::Downcast(a, u) => ProjectionElem::Downcast(a, u),
+            ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(ty.lift()),
         }
     }
 }
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 9ced3a7f3cd..7a5b3585d59 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -227,10 +227,13 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                     }
                     _ => bug!("Unexpected type {place_ty:#?}"),
                 },
-                // `OpaqueCast` only transmutes the type, so no moves there and
-                // `Downcast` only changes information about a `Place` without moving
+                // `OpaqueCast`:Only transmutes the type, so no moves there.
+                // `Downcast`  :Only changes information about a `Place` without moving.
+                // `Subtype`   :Only transmutes the type, so moves.
                 // So it's safe to skip these.
-                ProjectionElem::OpaqueCast(_) | ProjectionElem::Downcast(_, _) => (),
+                ProjectionElem::OpaqueCast(_)
+                | ProjectionElem::Subtype(_)
+                | ProjectionElem::Downcast(_, _) => (),
             }
             if union_path.is_none() {
                 // inlined from add_move_path because of a borrowck conflict with the iterator
diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
new file mode 100644
index 00000000000..e5be7c0ca76
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
@@ -0,0 +1,70 @@
+use crate::MirPass;
+use rustc_index::IndexVec;
+use rustc_middle::mir::patch::MirPatch;
+use rustc_middle::mir::visit::MutVisitor;
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+
+pub struct Subtyper;
+
+pub struct SubTypeChecker<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    patcher: MirPatch<'tcx>,
+    local_decls: &'a IndexVec<Local, LocalDecl<'tcx>>,
+}
+
+impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn visit_assign(
+        &mut self,
+        place: &mut Place<'tcx>,
+        rvalue: &mut Rvalue<'tcx>,
+        location: Location,
+    ) {
+        // We don't need to do anything for deref temps as they are
+        // not part of the source code, but used for desugaring purposes.
+        if self.local_decls[place.local].is_deref_temp() {
+            return;
+        }
+        let mut place_ty = place.ty(self.local_decls, self.tcx).ty;
+        let mut rval_ty = rvalue.ty(self.local_decls, self.tcx);
+        // Not erasing this causes `Free Regions` errors in validator,
+        // when rval is `ReStatic`.
+        rval_ty = self.tcx.erase_regions_ty(rval_ty);
+        place_ty = self.tcx.erase_regions(place_ty);
+        if place_ty != rval_ty {
+            let temp = self
+                .patcher
+                .new_temp(rval_ty, self.local_decls[place.as_ref().local].source_info.span);
+            let new_place = Place::from(temp);
+            self.patcher.add_assign(location, new_place, rvalue.clone());
+            let subtyped = new_place.project_deeper(&[ProjectionElem::Subtype(place_ty)], self.tcx);
+            *rvalue = Rvalue::Use(Operand::Move(subtyped));
+        }
+    }
+}
+
+// Aim here is to do this kind of transformation:
+//
+// let place: place_ty = rval;
+// // gets transformed to
+// let temp: rval_ty = rval;
+// let place: place_ty = temp as place_ty;
+pub fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+    let patch = MirPatch::new(body);
+    let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls };
+
+    for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
+        checker.visit_basic_block_data(bb, data);
+    }
+    checker.patcher.apply(body);
+}
+
+impl<'tcx> MirPass<'tcx> for Subtyper {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        subtype_finder(tcx, body);
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index bacabc62ee4..c428007707e 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -179,7 +179,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
         // Check the base local: it might be an unsafe-to-access static. We only check derefs of the
         // temporary holding the static pointer to avoid duplicate errors
         // <https://github.com/rust-lang/rust/pull/78068#issuecomment-731753506>.
-        if decl.internal && place.projection.first() == Some(&ProjectionElem::Deref) {
+        if place.projection.first() == Some(&ProjectionElem::Deref) {
             // If the projection root is an artificial local that we introduced when
             // desugaring `static`, give a more specific error message
             // (avoid the general "raw pointer" clause below, that would only be confusing).
diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs
index d56d4ad4f1e..78845af0162 100644
--- a/compiler/rustc_mir_transform/src/coverage/counters.rs
+++ b/compiler/rustc_mir_transform/src/coverage/counters.rs
@@ -1,10 +1,8 @@
 use super::Error;
 
 use super::graph;
-use super::spans;
 
 use graph::{BasicCoverageBlock, BcbBranch, CoverageGraph, TraverseCoverageGraphWithLoops};
-use spans::CoverageSpan;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::graph::WithNumNodes;
@@ -93,14 +91,14 @@ impl CoverageCounters {
     }
 
     /// Makes [`BcbCounter`] `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or
-    /// indirectly associated with `CoverageSpans`, and accumulates additional `Expression`s
+    /// indirectly associated with coverage spans, and accumulates additional `Expression`s
     /// representing intermediate values.
     pub fn make_bcb_counters(
         &mut self,
         basic_coverage_blocks: &CoverageGraph,
-        coverage_spans: &[CoverageSpan],
+        bcb_has_coverage_spans: impl Fn(BasicCoverageBlock) -> bool,
     ) -> Result<(), Error> {
-        MakeBcbCounters::new(self, basic_coverage_blocks).make_bcb_counters(coverage_spans)
+        MakeBcbCounters::new(self, basic_coverage_blocks).make_bcb_counters(bcb_has_coverage_spans)
     }
 
     fn make_counter(&mut self) -> BcbCounter {
@@ -113,14 +111,10 @@ impl CoverageCounters {
         BcbCounter::Expression { id, lhs, op, rhs }
     }
 
-    pub fn make_identity_counter(&mut self, counter_operand: Operand) -> BcbCounter {
-        self.make_expression(counter_operand, Op::Add, Operand::Zero)
-    }
-
     /// Counter IDs start from one and go up.
     fn next_counter(&mut self) -> CounterId {
         let next = self.next_counter_id;
-        self.next_counter_id = next.next_id();
+        self.next_counter_id = self.next_counter_id + 1;
         next
     }
 
@@ -128,7 +122,7 @@ impl CoverageCounters {
     /// (Counter IDs and Expression IDs are distinguished by the `Operand` enum.)
     fn next_expression(&mut self) -> ExpressionId {
         let next = self.next_expression_id;
-        self.next_expression_id = next.next_id();
+        self.next_expression_id = self.next_expression_id + 1;
         next
     }
 
@@ -208,7 +202,7 @@ impl CoverageCounters {
 }
 
 /// Traverse the `CoverageGraph` and add either a `Counter` or `Expression` to every BCB, to be
-/// injected with `CoverageSpan`s. `Expressions` have no runtime overhead, so if a viable expression
+/// injected with coverage spans. `Expressions` have no runtime overhead, so if a viable expression
 /// (adding or subtracting two other counters or expressions) can compute the same result as an
 /// embedded counter, an `Expression` should be used.
 struct MakeBcbCounters<'a> {
@@ -234,17 +228,14 @@ impl<'a> MakeBcbCounters<'a> {
     /// Returns any non-code-span expressions created to represent intermediate values (such as to
     /// add two counters so the result can be subtracted from another counter), or an Error with
     /// message for subsequent debugging.
-    fn make_bcb_counters(&mut self, coverage_spans: &[CoverageSpan]) -> Result<(), Error> {
+    fn make_bcb_counters(
+        &mut self,
+        bcb_has_coverage_spans: impl Fn(BasicCoverageBlock) -> bool,
+    ) -> Result<(), Error> {
         debug!("make_bcb_counters(): adding a counter or expression to each BasicCoverageBlock");
-        let num_bcbs = self.basic_coverage_blocks.num_nodes();
-
-        let mut bcbs_with_coverage = BitSet::new_empty(num_bcbs);
-        for covspan in coverage_spans {
-            bcbs_with_coverage.insert(covspan.bcb);
-        }
 
         // Walk the `CoverageGraph`. For each `BasicCoverageBlock` node with an associated
-        // `CoverageSpan`, add a counter. If the `BasicCoverageBlock` branches, add a counter or
+        // coverage span, add a counter. If the `BasicCoverageBlock` branches, add a counter or
         // expression to each branch `BasicCoverageBlock` (if the branch BCB has only one incoming
         // edge) or edge from the branching BCB to the branch BCB (if the branch BCB has multiple
         // incoming edges).
@@ -255,8 +246,8 @@ impl<'a> MakeBcbCounters<'a> {
         // the current BCB is in one or more nested loops or not.
         let mut traversal = TraverseCoverageGraphWithLoops::new(&self.basic_coverage_blocks);
         while let Some(bcb) = traversal.next(self.basic_coverage_blocks) {
-            if bcbs_with_coverage.contains(bcb) {
-                debug!("{:?} has at least one `CoverageSpan`. Get or make its counter", bcb);
+            if bcb_has_coverage_spans(bcb) {
+                debug!("{:?} has at least one coverage span. Get or make its counter", bcb);
                 let branching_counter_operand = self.get_or_make_counter_operand(bcb)?;
 
                 if self.bcb_needs_branch_counters(bcb) {
@@ -264,7 +255,7 @@ impl<'a> MakeBcbCounters<'a> {
                 }
             } else {
                 debug!(
-                    "{:?} does not have any `CoverageSpan`s. A counter will only be added if \
+                    "{:?} does not have any coverage spans. A counter will only be added if \
                     and when a covered BCB has an expression dependency.",
                     bcb,
                 );
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index ff2254d6941..812633348e3 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -288,9 +288,9 @@ rustc_index::newtype_index! {
 ///     not relevant to coverage analysis. `FalseUnwind`, for example, can be treated the same as
 ///     a `Goto`, and merged with its successor into the same BCB.
 ///
-/// Each BCB with at least one computed `CoverageSpan` will have no more than one `Counter`.
+/// Each BCB with at least one computed coverage span will have no more than one `Counter`.
 /// In some cases, a BCB's execution count can be computed by `Expression`. Additional
-/// disjoint `CoverageSpan`s in a BCB can also be counted by `Expression` (by adding `ZERO`
+/// disjoint coverage spans in a BCB can also be counted by `Expression` (by adding `ZERO`
 /// to the BCB's primary counter or expression).
 ///
 /// The BCB CFG is critical to simplifying the coverage analysis by ensuring graph path-based
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index c75d33eeb31..abf13519e9e 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -9,13 +9,11 @@ mod tests;
 
 use self::counters::{BcbCounter, CoverageCounters};
 use self::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
-use self::spans::{CoverageSpan, CoverageSpans};
+use self::spans::CoverageSpans;
 
 use crate::MirPass;
 
-use rustc_data_structures::graph::WithNumNodes;
 use rustc_data_structures::sync::Lrc;
-use rustc_index::IndexVec;
 use rustc_middle::hir;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::coverage::*;
@@ -154,7 +152,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
         let body_span = self.body_span;
 
         ////////////////////////////////////////////////////
-        // Compute `CoverageSpan`s from the `CoverageGraph`.
+        // Compute coverage spans from the `CoverageGraph`.
         let coverage_spans = CoverageSpans::generate_coverage_spans(
             &self.mir_body,
             fn_sig_span,
@@ -164,32 +162,33 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
 
         ////////////////////////////////////////////////////
         // Create an optimized mix of `Counter`s and `Expression`s for the `CoverageGraph`. Ensure
-        // every `CoverageSpan` has a `Counter` or `Expression` assigned to its `BasicCoverageBlock`
+        // every coverage span has a `Counter` or `Expression` assigned to its `BasicCoverageBlock`
         // and all `Expression` dependencies (operands) are also generated, for any other
-        // `BasicCoverageBlock`s not already associated with a `CoverageSpan`.
+        // `BasicCoverageBlock`s not already associated with a coverage span.
         //
         // Intermediate expressions (used to compute other `Expression` values), which have no
         // direct association with any `BasicCoverageBlock`, are accumulated inside `coverage_counters`.
+        let bcb_has_coverage_spans = |bcb| coverage_spans.bcb_has_coverage_spans(bcb);
         let result = self
             .coverage_counters
-            .make_bcb_counters(&mut self.basic_coverage_blocks, &coverage_spans);
+            .make_bcb_counters(&mut self.basic_coverage_blocks, bcb_has_coverage_spans);
 
         if let Ok(()) = result {
             ////////////////////////////////////////////////////
-            // Remove the counter or edge counter from of each `CoverageSpan`s associated
+            // Remove the counter or edge counter from of each coverage cpan's associated
             // `BasicCoverageBlock`, and inject a `Coverage` statement into the MIR.
             //
-            // `Coverage` statements injected from `CoverageSpan`s will include the code regions
+            // `Coverage` statements injected from coverage spans will include the code regions
             // (source code start and end positions) to be counted by the associated counter.
             //
-            // These `CoverageSpan`-associated counters are removed from their associated
+            // These coverage-span-associated counters are removed from their associated
             // `BasicCoverageBlock`s so that the only remaining counters in the `CoverageGraph`
             // are indirect counters (to be injected next, without associated code regions).
-            self.inject_coverage_span_counters(coverage_spans);
+            self.inject_coverage_span_counters(&coverage_spans);
 
             ////////////////////////////////////////////////////
             // For any remaining `BasicCoverageBlock` counters (that were not associated with
-            // any `CoverageSpan`), inject `Coverage` statements (_without_ code region `Span`s)
+            // any coverage span), inject `Coverage` statements (_without_ code region spans)
             // to ensure `BasicCoverageBlock` counters that other `Expression`s may depend on
             // are in fact counted, even though they don't directly contribute to counting
             // their own independent code region's coverage.
@@ -214,47 +213,40 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
         }
     }
 
-    /// Inject a counter for each `CoverageSpan`. There can be multiple `CoverageSpan`s for a given
-    /// BCB, but only one actual counter needs to be incremented per BCB. `bb_counters` maps each
-    /// `bcb` to its `Counter`, when injected. Subsequent `CoverageSpan`s for a BCB that already has
-    /// a `Counter` will inject an `Expression` instead, and compute its value by adding `ZERO` to
-    /// the BCB `Counter` value.
-    fn inject_coverage_span_counters(&mut self, coverage_spans: Vec<CoverageSpan>) {
+    /// Injects a single [`StatementKind::Coverage`] for each BCB that has one
+    /// or more coverage spans.
+    fn inject_coverage_span_counters(&mut self, coverage_spans: &CoverageSpans) {
         let tcx = self.tcx;
         let source_map = tcx.sess.source_map();
         let body_span = self.body_span;
         let file_name = Symbol::intern(&self.source_file.name.prefer_remapped().to_string_lossy());
 
-        let mut bcb_counters = IndexVec::from_elem_n(None, self.basic_coverage_blocks.num_nodes());
-        for covspan in coverage_spans {
-            let bcb = covspan.bcb;
-            let span = covspan.span;
-            let counter_kind = if let Some(&counter_operand) = bcb_counters[bcb].as_ref() {
-                self.coverage_counters.make_identity_counter(counter_operand)
-            } else if let Some(counter_kind) = self.coverage_counters.take_bcb_counter(bcb) {
-                bcb_counters[bcb] = Some(counter_kind.as_operand());
-                counter_kind
-            } else {
+        for (bcb, spans) in coverage_spans.bcbs_with_coverage_spans() {
+            let counter_kind = self.coverage_counters.take_bcb_counter(bcb).unwrap_or_else(|| {
                 bug!("Every BasicCoverageBlock should have a Counter or Expression");
-            };
+            });
 
-            let code_region = make_code_region(source_map, file_name, span, body_span);
+            // Convert the coverage spans into a vector of code regions to be
+            // associated with this BCB's coverage statement.
+            let code_regions = spans
+                .iter()
+                .map(|&span| make_code_region(source_map, file_name, span, body_span))
+                .collect::<Vec<_>>();
 
             inject_statement(
                 self.mir_body,
                 self.make_mir_coverage_kind(&counter_kind),
                 self.bcb_leader_bb(bcb),
-                Some(code_region),
+                code_regions,
             );
         }
     }
 
-    /// `inject_coverage_span_counters()` looped through the `CoverageSpan`s and injected the
-    /// counter from the `CoverageSpan`s `BasicCoverageBlock`, removing it from the BCB in the
-    /// process (via `take_counter()`).
+    /// At this point, any BCB with coverage counters has already had its counter injected
+    /// into MIR, and had its counter removed from `coverage_counters` (via `take_counter()`).
     ///
     /// Any other counter associated with a `BasicCoverageBlock`, or its incoming edge, but not
-    /// associated with a `CoverageSpan`, should only exist if the counter is an `Expression`
+    /// associated with a coverage span, should only exist if the counter is an `Expression`
     /// dependency (one of the expression operands). Collect them, and inject the additional
     /// counters into the MIR, without a reportable coverage span.
     fn inject_indirect_counters(&mut self) {
@@ -303,7 +295,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
                         self.mir_body,
                         self.make_mir_coverage_kind(&counter_kind),
                         inject_to_bb,
-                        None,
+                        Vec::new(),
                     );
                 }
                 BcbCounter::Expression { .. } => inject_intermediate_expression(
@@ -368,20 +360,14 @@ fn inject_statement(
     mir_body: &mut mir::Body<'_>,
     counter_kind: CoverageKind,
     bb: BasicBlock,
-    some_code_region: Option<CodeRegion>,
+    code_regions: Vec<CodeRegion>,
 ) {
-    debug!(
-        "  injecting statement {:?} for {:?} at code region: {:?}",
-        counter_kind, bb, some_code_region
-    );
+    debug!("  injecting statement {counter_kind:?} for {bb:?} at code regions: {code_regions:?}");
     let data = &mut mir_body[bb];
     let source_info = data.terminator().source_info;
     let statement = Statement {
         source_info,
-        kind: StatementKind::Coverage(Box::new(Coverage {
-            kind: counter_kind,
-            code_region: some_code_region,
-        })),
+        kind: StatementKind::Coverage(Box::new(Coverage { kind: counter_kind, code_regions })),
     };
     data.statements.insert(0, statement);
 }
@@ -395,7 +381,10 @@ fn inject_intermediate_expression(mir_body: &mut mir::Body<'_>, expression: Cove
     let source_info = data.terminator().source_info;
     let statement = Statement {
         source_info,
-        kind: StatementKind::Coverage(Box::new(Coverage { kind: expression, code_region: None })),
+        kind: StatementKind::Coverage(Box::new(Coverage {
+            kind: expression,
+            code_regions: Vec::new(),
+        })),
     };
     data.statements.push(statement);
 }
diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs
index 56365c5d474..2c0164e765c 100644
--- a/compiler/rustc_mir_transform/src/coverage/query.rs
+++ b/compiler/rustc_mir_transform/src/coverage/query.rs
@@ -93,8 +93,8 @@ fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) ->
 fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> {
     let body = mir_body(tcx, def_id);
     all_coverage_in_mir_body(body)
-        // Not all coverage statements have an attached code region.
-        .filter_map(|coverage| coverage.code_region.as_ref())
+        // Coverage statements have a list of code regions (possibly empty).
+        .flat_map(|coverage| coverage.code_regions.as_slice())
         .collect()
 }
 
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index 767f8e9f4fa..dd87694f97c 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -1,6 +1,7 @@
 use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB};
 
 use rustc_data_structures::graph::WithNumNodes;
+use rustc_index::IndexVec;
 use rustc_middle::mir::{
     self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator,
     TerminatorKind,
@@ -10,6 +11,48 @@ use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol};
 
 use std::cell::OnceCell;
 
+pub(super) struct CoverageSpans {
+    /// Map from BCBs to their list of coverage spans.
+    bcb_to_spans: IndexVec<BasicCoverageBlock, Vec<Span>>,
+}
+
+impl CoverageSpans {
+    pub(super) fn generate_coverage_spans(
+        mir_body: &mir::Body<'_>,
+        fn_sig_span: Span,
+        body_span: Span,
+        basic_coverage_blocks: &CoverageGraph,
+    ) -> Self {
+        let coverage_spans = CoverageSpansGenerator::generate_coverage_spans(
+            mir_body,
+            fn_sig_span,
+            body_span,
+            basic_coverage_blocks,
+        );
+
+        // Group the coverage spans by BCB, with the BCBs in sorted order.
+        let mut bcb_to_spans = IndexVec::from_elem_n(Vec::new(), basic_coverage_blocks.num_nodes());
+        for CoverageSpan { bcb, span, .. } in coverage_spans {
+            bcb_to_spans[bcb].push(span);
+        }
+
+        Self { bcb_to_spans }
+    }
+
+    pub(super) fn bcb_has_coverage_spans(&self, bcb: BasicCoverageBlock) -> bool {
+        !self.bcb_to_spans[bcb].is_empty()
+    }
+
+    pub(super) fn bcbs_with_coverage_spans(
+        &self,
+    ) -> impl Iterator<Item = (BasicCoverageBlock, &[Span])> {
+        self.bcb_to_spans.iter_enumerated().filter_map(|(bcb, spans)| {
+            // Only yield BCBs that have at least one coverage span.
+            (!spans.is_empty()).then_some((bcb, spans.as_slice()))
+        })
+    }
+}
+
 #[derive(Debug, Copy, Clone)]
 pub(super) enum CoverageStatement {
     Statement(BasicBlock, Span, usize),
@@ -35,7 +78,7 @@ impl CoverageStatement {
 /// or is subsumed by the `Span` associated with this `CoverageSpan`, and it's `BasicBlock`
 /// `dominates()` the `BasicBlock`s in this `CoverageSpan`.
 #[derive(Debug, Clone)]
-pub(super) struct CoverageSpan {
+struct CoverageSpan {
     pub span: Span,
     pub expn_span: Span,
     pub current_macro_or_none: OnceCell<Option<Symbol>>,
@@ -162,7 +205,7 @@ impl CoverageSpan {
 ///  * Merge spans that represent continuous (both in source code and control flow), non-branching
 ///    execution
 ///  * Carve out (leave uncovered) any span that will be counted by another MIR (notably, closures)
-pub struct CoverageSpans<'a, 'tcx> {
+struct CoverageSpansGenerator<'a, 'tcx> {
     /// The MIR, used to look up `BasicBlockData`.
     mir_body: &'a mir::Body<'tcx>,
 
@@ -218,7 +261,7 @@ pub struct CoverageSpans<'a, 'tcx> {
     refined_spans: Vec<CoverageSpan>,
 }
 
-impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
+impl<'a, 'tcx> CoverageSpansGenerator<'a, 'tcx> {
     /// Generate a minimal set of `CoverageSpan`s, each representing a contiguous code region to be
     /// counted.
     ///
@@ -246,7 +289,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
         body_span: Span,
         basic_coverage_blocks: &'a CoverageGraph,
     ) -> Vec<CoverageSpan> {
-        let mut coverage_spans = CoverageSpans {
+        let mut coverage_spans = Self {
             mir_body,
             fn_sig_span,
             body_span,
@@ -734,7 +777,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
 
 /// If the MIR `Statement` has a span contributive to computing coverage spans,
 /// return it; otherwise return `None`.
-pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
+fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
     match statement.kind {
         // These statements have spans that are often outside the scope of the executed source code
         // for their parent `BasicBlock`.
@@ -781,7 +824,7 @@ pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span>
 
 /// If the MIR `Terminator` has a span contributive to computing coverage spans,
 /// return it; otherwise return `None`.
-pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
+fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
     match terminator.kind {
         // These terminators have spans that don't positively contribute to computing a reasonable
         // span of actually executed source code. (For example, SwitchInt terminators extracted from
@@ -828,7 +871,7 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Sp
 /// [^1]Expansions result from Rust syntax including macros, syntactic sugar,
 /// etc.).
 #[inline]
-pub(super) fn function_source_span(span: Span, body_span: Span) -> Span {
+fn function_source_span(span: Span, body_span: Span) -> Span {
     let original_span = original_sp(span, body_span).with_ctxt(body_span.ctxt());
     if body_span.contains(original_span) { original_span } else { body_span }
 }
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index 4a066ed3abd..7476d3ce927 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -25,8 +25,7 @@
 //! to: `rustc_span::create_default_session_globals_then(|| { test_here(); })`.
 
 use super::counters;
-use super::graph;
-use super::spans;
+use super::graph::{self, BasicCoverageBlock};
 
 use coverage_test_macros::let_bcb;
 
@@ -644,39 +643,18 @@ fn test_traverse_coverage_with_loops() {
     );
 }
 
-fn synthesize_body_span_from_terminators(mir_body: &Body<'_>) -> Span {
-    let mut some_span: Option<Span> = None;
-    for (_, data) in mir_body.basic_blocks.iter_enumerated() {
-        let term_span = data.terminator().source_info.span;
-        if let Some(span) = some_span.as_mut() {
-            *span = span.to(term_span);
-        } else {
-            some_span = Some(term_span)
-        }
-    }
-    some_span.expect("body must have at least one BasicBlock")
-}
-
 #[test]
 fn test_make_bcb_counters() {
     rustc_span::create_default_session_globals_then(|| {
         let mir_body = goto_switchint();
-        let body_span = synthesize_body_span_from_terminators(&mir_body);
         let mut basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body);
-        let mut coverage_spans = Vec::new();
-        for (bcb, data) in basic_coverage_blocks.iter_enumerated() {
-            if let Some(span) = spans::filtered_terminator_span(data.terminator(&mir_body)) {
-                coverage_spans.push(spans::CoverageSpan::for_terminator(
-                    spans::function_source_span(span, body_span),
-                    span,
-                    bcb,
-                    data.last_bb(),
-                ));
-            }
-        }
+        // Historically this test would use `spans` internals to set up fake
+        // coverage spans for BCBs 1 and 2. Now we skip that step and just tell
+        // BCB counter construction that those BCBs have spans.
+        let bcb_has_coverage_spans = |bcb: BasicCoverageBlock| (1..=2).contains(&bcb.as_usize());
         let mut coverage_counters = counters::CoverageCounters::new(&basic_coverage_blocks);
         coverage_counters
-            .make_bcb_counters(&mut basic_coverage_blocks, &coverage_spans)
+            .make_bcb_counters(&mut basic_coverage_blocks, bcb_has_coverage_spans)
             .expect("should be Ok");
         assert_eq!(coverage_counters.intermediate_expressions.len(), 0);
 
diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs
index 95898b5b73c..42be7457018 100644
--- a/compiler/rustc_mir_transform/src/deref_separator.rs
+++ b/compiler/rustc_mir_transform/src/deref_separator.rs
@@ -37,7 +37,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> {
             for (idx, (p_ref, p_elem)) in place.iter_projections().enumerate() {
                 if !p_ref.projection.is_empty() && p_elem == ProjectionElem::Deref {
                     let ty = p_ref.ty(self.local_decls, self.tcx).ty;
-                    let temp = self.patcher.new_internal_with_info(
+                    let temp = self.patcher.new_local_with_info(
                         ty,
                         self.local_decls[p_ref.local].source_info.span,
                         LocalInfo::DerefTemp,
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index e51f771e00d..1c917a85c03 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -69,7 +69,7 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> {
             let (unique_ty, nonnull_ty, ptr_ty) =
                 build_ptr_tys(tcx, base_ty.boxed_ty(), self.unique_did, self.nonnull_did);
 
-            let ptr_local = self.patch.new_internal(ptr_ty, source_info.span);
+            let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);
 
             self.patch.add_assign(
                 location,
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index b62d7da2a4c..d18fdaaf22f 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -271,7 +271,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
         let tcx = self.tcx;
         let patch = &mut self.patch;
         debug!("create_drop_flag({:?})", self.body.span);
-        self.drop_flags[index].get_or_insert_with(|| patch.new_internal(tcx.types.bool, span));
+        self.drop_flags[index].get_or_insert_with(|| patch.new_temp(tcx.types.bool, span));
     }
 
     fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 8a807d786a5..c16f07a453c 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -321,7 +321,7 @@ impl<'tcx> TransformVisitor<'tcx> {
 
     // Create a statement which reads the discriminant into a temporary
     fn get_discr(&self, body: &mut Body<'tcx>) -> (Statement<'tcx>, Place<'tcx>) {
-        let temp_decl = LocalDecl::new(self.discr_ty, body.span).internal();
+        let temp_decl = LocalDecl::new(self.discr_ty, body.span);
         let local_decls_len = body.local_decls.push(temp_decl);
         let temp = Place::from(local_decls_len);
 
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 449bade3322..56bdc5a171a 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -306,6 +306,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 }
                 ProjectionElem::Downcast(name, index) => ProjectionElem::Downcast(name, index),
                 ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty),
+                ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(ty),
             };
             value = self.insert(Value::Projection(value, proj));
         }
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index ebd61f8ad95..32dfb743905 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -218,7 +218,13 @@ impl<'tcx> Inliner<'tcx> {
         // Normally, this shouldn't be required, but trait normalization failure can create a
         // validation ICE.
         let output_type = callee_body.return_ty();
-        if !util::is_subtype(self.tcx, self.param_env, output_type, destination_ty) {
+        if !util::relate_types(
+            self.tcx,
+            self.param_env,
+            ty::Variance::Covariant,
+            output_type,
+            destination_ty,
+        ) {
             trace!(?output_type, ?destination_ty);
             return Err("failed to normalize return type");
         }
@@ -248,7 +254,13 @@ impl<'tcx> Inliner<'tcx> {
                 self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter())
             {
                 let input_type = callee_body.local_decls[input].ty;
-                if !util::is_subtype(self.tcx, self.param_env, input_type, arg_ty) {
+                if !util::relate_types(
+                    self.tcx,
+                    self.param_env,
+                    ty::Variance::Covariant,
+                    input_type,
+                    arg_ty,
+                ) {
                     trace!(?arg_ty, ?input_type);
                     return Err("failed to normalize tuple argument type");
                 }
@@ -257,7 +269,13 @@ impl<'tcx> Inliner<'tcx> {
             for (arg, input) in args.iter().zip(callee_body.args_iter()) {
                 let input_type = callee_body.local_decls[input].ty;
                 let arg_ty = arg.ty(&caller_body.local_decls, self.tcx);
-                if !util::is_subtype(self.tcx, self.param_env, input_type, arg_ty) {
+                if !util::relate_types(
+                    self.tcx,
+                    self.param_env,
+                    ty::Variance::Covariant,
+                    input_type,
+                    arg_ty,
+                ) {
                     trace!(?arg_ty, ?input_type);
                     return Err("failed to normalize argument type");
                 }
@@ -598,9 +616,7 @@ impl<'tcx> Inliner<'tcx> {
                 // If there are any locals without storage markers, give them storage only for the
                 // duration of the call.
                 for local in callee_body.vars_and_temps_iter() {
-                    if !callee_body.local_decls[local].internal
-                        && integrator.always_live_locals.contains(local)
-                    {
+                    if integrator.always_live_locals.contains(local) {
                         let new_local = integrator.map_local(local);
                         caller_body[callsite.block].statements.push(Statement {
                             source_info: callsite.source_info,
@@ -623,9 +639,7 @@ impl<'tcx> Inliner<'tcx> {
                         n += 1;
                     }
                     for local in callee_body.vars_and_temps_iter().rev() {
-                        if !callee_body.local_decls[local].internal
-                            && integrator.always_live_locals.contains(local)
-                        {
+                        if integrator.always_live_locals.contains(local) {
                             let new_local = integrator.map_local(local);
                             caller_body[block].statements.push(Statement {
                                 source_info: callsite.source_info,
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 754f2ee8376..c0a09b7a761 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -54,6 +54,7 @@ mod check_packed_ref;
 pub mod check_unsafety;
 mod remove_place_mention;
 // This pass is public to allow external drivers to perform MIR cleanup
+mod add_subtyping_projections;
 pub mod cleanup_post_borrowck;
 mod const_debuginfo;
 mod const_goto;
@@ -481,6 +482,7 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // These next passes must be executed together
         &add_call_guards::CriticalCallEdges,
         &reveal_all::RevealAll, // has to be done before drop elaboration, since we need to drop opaque types, too.
+        &add_subtyping_projections::Subtyper, // calling this after reveal_all ensures that we don't deal with opaque types
         &elaborate_drops::ElaborateDrops,
         // This will remove extraneous landing pads which are no longer
         // necessary as well as well as forcing any call in a non-unwinding
diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs
index 55f1eac6f84..1626cf3c035 100644
--- a/compiler/rustc_mir_transform/src/reveal_all.rs
+++ b/compiler/rustc_mir_transform/src/reveal_all.rs
@@ -46,16 +46,18 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
                 .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_)))
                 .collect::<Vec<_>>(),
         );
+        self.super_place(place, _context, _location);
     }
 
     #[inline]
-    fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, _: Location) {
+    fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) {
         // We have to use `try_normalize_erasing_regions` here, since it's
         // possible that we visit impossible-to-satisfy where clauses here,
         // see #91745
         if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.const_) {
             constant.const_ = c;
         }
+        self.super_constant(constant, location);
     }
 
     #[inline]
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 2795cf15702..73dae044355 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -441,21 +441,23 @@ fn save_unreachable_coverage(
         let dead_block = &basic_blocks[dead_block];
         for statement in &dead_block.statements {
             let StatementKind::Coverage(coverage) = &statement.kind else { continue };
-            let Some(code_region) = &coverage.code_region else { continue };
+            if coverage.code_regions.is_empty() {
+                continue;
+            };
             let instance = statement.source_info.scope.inlined_instance(source_scopes);
             if live.contains(&instance) {
-                retained_coverage.push((statement.source_info, code_region.clone()));
+                retained_coverage.push((statement.source_info, coverage.code_regions.clone()));
             }
         }
     }
 
     let start_block = &mut basic_blocks[START_BLOCK];
     start_block.statements.extend(retained_coverage.into_iter().map(
-        |(source_info, code_region)| Statement {
+        |(source_info, code_regions)| Statement {
             source_info,
             kind: StatementKind::Coverage(Box::new(Coverage {
                 kind: CoverageKind::Unreachable,
-                code_region: Some(code_region),
+                code_regions,
             })),
         },
     ));
diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl
index 2b7d9bd3413..cf23d79afaf 100644
--- a/compiler/rustc_monomorphize/messages.ftl
+++ b/compiler/rustc_monomorphize/messages.ftl
@@ -7,8 +7,6 @@ monomorphize_couldnt_dump_mono_stats =
 monomorphize_encountered_error_while_instantiating =
     the above error was encountered while instantiating `{$formatted_item}`
 
-monomorphize_fatal_error = {$error_message}
-
 monomorphize_large_assignments =
     moving {$size} bytes
     .label = value moved from here
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 05b6c406206..88a305e8214 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -59,7 +59,6 @@ parse_bare_cr = {$double_quotes ->
 
 parse_bare_cr_in_raw_string = bare CR not allowed in raw string
 
-parse_binary_float_literal_not_supported = binary float literal is not supported
 parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases
 
 parse_box_not_pat = expected pattern, found {$descr}
@@ -284,7 +283,6 @@ parse_generics_in_path = unexpected generic arguments in path
 
 parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
 parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
-parse_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
 parse_if_expression_missing_condition = missing condition for `if` expression
     .condition_label = expected condition here
     .block_label = if this block is the condition of the `if` expression, then it must be followed by another block
@@ -356,8 +354,6 @@ parse_inner_doc_comment_not_permitted = expected outer doc comment
     .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
     .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
 
-parse_int_literal_too_large = integer literal is too large
-
 parse_invalid_block_macro_segment = cannot use a `block` macro fragment here
     .label = the `block` fragment is within this context
     .suggestion = wrap this in another block
@@ -382,18 +378,8 @@ parse_invalid_dyn_keyword = invalid `dyn` keyword
     .suggestion = remove this keyword
 
 parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else`
-parse_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
-    .label = invalid suffix `{$suffix}`
-    .help = valid suffixes are `f32` and `f64`
-
-parse_invalid_float_literal_width = invalid width `{$width}` for float literal
-    .help = valid widths are 32 and 64
-
 parse_invalid_identifier_with_leading_number = identifiers cannot start with a number
 
-parse_invalid_int_literal_width = invalid width `{$width}` for integer literal
-    .help = valid widths are 8, 16, 32, 64 and 128
-
 parse_invalid_interpolated_expression = invalid interpolated expression
 
 parse_invalid_literal_suffix = suffixes on {$kind} literals are invalid
@@ -412,14 +398,6 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
 
 parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
 
-parse_invalid_num_literal_base_prefix = invalid base prefix for number literal
-    .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
-    .suggestion = try making the prefix lowercase
-
-parse_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
-    .label = invalid suffix `{$suffix}`
-    .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
-
 parse_invalid_unicode_escape = invalid unicode character escape
     .label = invalid escape
     .help = unicode escape must {$surrogate ->
@@ -603,13 +581,6 @@ parse_no_brace_unicode_escape = incorrect unicode escape sequence
 
 parse_no_digits_literal = no valid digits found for number
 
-parse_non_item_in_item_list = non-item in item list
-    .suggestion_use_const_not_let = consider using `const` instead of `let` for associated const
-    .label_list_start = item list starts here
-    .label_non_item = non-item starts here
-    .label_list_end = item list ends here
-    .suggestion_remove_semicolon = consider removing this semicolon
-
 parse_non_string_abi_literal = non-string ABI literal
     .suggestion = specify the ABI with a string literal
 
@@ -626,7 +597,6 @@ parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable
 
 parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||`
 
-parse_octal_float_literal_not_supported = octal float literal is not supported
 parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
 parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
 parse_out_of_range_hex_escape = out of range hex escape
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index aad4edaba90..cc54cc5bebb 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -813,7 +813,12 @@ impl<'a> Parser<'a> {
     fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemInfo> {
         let unsafety = self.parse_unsafety(Case::Sensitive);
         // Parse optional `auto` prefix.
-        let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No };
+        let is_auto = if self.eat_keyword(kw::Auto) {
+            self.sess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
+            IsAuto::Yes
+        } else {
+            IsAuto::No
+        };
 
         self.expect_keyword(kw::Trait)?;
         let ident = self.parse_ident()?;
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index a25b0f1f893..0a64b2f806a 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -247,7 +247,7 @@ impl<'a> Parser<'a> {
             )?;
             FnRetTy::Ty(ty)
         } else {
-            FnRetTy::Default(self.token.span.shrink_to_lo())
+            FnRetTy::Default(self.prev_token.span.shrink_to_hi())
         })
     }
 
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 493daf314ce..f853039f72c 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -1,6 +1,7 @@
-// This implements the dead-code warning pass. It follows middle::reachable
-// closely. The idea is that all reachable symbols are live, codes called
-// from live codes are live, and everything else is dead.
+// This implements the dead-code warning pass.
+// All reachable symbols are live, code called from live code is live, code with certain lint
+// expectations such as `#[expect(unused)]` and `#[expect(dead_code)]` is live, and everything else
+// is dead.
 
 use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
 use itertools::Itertools;
@@ -747,7 +748,7 @@ fn live_symbols_and_ignored_derived_traits(
     (symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits)
 }
 
-struct DeadVariant {
+struct DeadItem {
     def_id: LocalDefId,
     name: Symbol,
     level: lint::Level,
@@ -785,7 +786,13 @@ impl<'tcx> DeadVisitor<'tcx> {
         ShouldWarnAboutField::Yes(is_positional)
     }
 
-    fn warn_multiple_dead_codes(
+    // # Panics
+    // All `dead_codes` must have the same lint level, otherwise we will intentionally ICE.
+    // This is because we emit a multi-spanned lint using the lint level of the `dead_codes`'s
+    // first local def id.
+    // Prefer calling `Self.warn_dead_code` or `Self.warn_dead_code_grouped_by_lint_level`
+    // since those methods group by lint level before calling this method.
+    fn lint_at_single_level(
         &self,
         dead_codes: &[LocalDefId],
         participle: &str,
@@ -796,6 +803,15 @@ impl<'tcx> DeadVisitor<'tcx> {
             return;
         };
         let tcx = self.tcx;
+
+        let first_hir_id = tcx.hir().local_def_id_to_hir_id(first_id);
+        let first_lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, first_hir_id).0;
+        assert!(dead_codes.iter().skip(1).all(|id| {
+            let hir_id = tcx.hir().local_def_id_to_hir_id(*id);
+            let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
+            level == first_lint_level
+        }));
+
         let names: Vec<_> =
             dead_codes.iter().map(|&def_id| tcx.item_name(def_id.to_def_id())).collect();
         let spans: Vec<_> = dead_codes
@@ -876,31 +892,26 @@ impl<'tcx> DeadVisitor<'tcx> {
             }
         };
 
-        self.tcx.emit_spanned_lint(
-            lint,
-            tcx.hir().local_def_id_to_hir_id(first_id),
-            MultiSpan::from_spans(spans),
-            diag,
-        );
+        self.tcx.emit_spanned_lint(lint, first_hir_id, MultiSpan::from_spans(spans), diag);
     }
 
-    fn warn_dead_fields_and_variants(
+    fn warn_multiple(
         &self,
         def_id: LocalDefId,
         participle: &str,
-        dead_codes: Vec<DeadVariant>,
+        dead_codes: Vec<DeadItem>,
         is_positional: bool,
     ) {
         let mut dead_codes = dead_codes
             .iter()
             .filter(|v| !v.name.as_str().starts_with('_'))
-            .collect::<Vec<&DeadVariant>>();
+            .collect::<Vec<&DeadItem>>();
         if dead_codes.is_empty() {
             return;
         }
         dead_codes.sort_by_key(|v| v.level);
         for (_, group) in &dead_codes.into_iter().group_by(|v| v.level) {
-            self.warn_multiple_dead_codes(
+            self.lint_at_single_level(
                 &group.map(|v| v.def_id).collect::<Vec<_>>(),
                 participle,
                 Some(def_id),
@@ -910,7 +921,7 @@ impl<'tcx> DeadVisitor<'tcx> {
     }
 
     fn warn_dead_code(&mut self, id: LocalDefId, participle: &str) {
-        self.warn_multiple_dead_codes(&[id], participle, None, false);
+        self.lint_at_single_level(&[id], participle, None, false);
     }
 
     fn check_definition(&mut self, def_id: LocalDefId) {
@@ -954,17 +965,16 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
         if let hir::ItemKind::Impl(impl_item) = tcx.hir().item(item).kind {
             let mut dead_items = Vec::new();
             for item in impl_item.items {
-                let did = item.id.owner_id.def_id;
-                if !visitor.is_live_code(did) {
-                    dead_items.push(did)
+                let def_id = item.id.owner_id.def_id;
+                if !visitor.is_live_code(def_id) {
+                    let name = tcx.item_name(def_id.to_def_id());
+                    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+                    let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
+
+                    dead_items.push(DeadItem { def_id, name, level })
                 }
             }
-            visitor.warn_multiple_dead_codes(
-                &dead_items,
-                "used",
-                Some(item.owner_id.def_id),
-                false,
-            );
+            visitor.warn_multiple(item.owner_id.def_id, "used", dead_items, false);
         }
 
         if !live_symbols.contains(&item.owner_id.def_id) {
@@ -988,7 +998,7 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
                     // Record to group diagnostics.
                     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
                     let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
-                    dead_variants.push(DeadVariant { def_id, name: variant.name, level });
+                    dead_variants.push(DeadItem { def_id, name: variant.name, level });
                     continue;
                 }
 
@@ -1013,21 +1023,16 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
                                     hir_id,
                                 )
                                 .0;
-                            Some(DeadVariant { def_id, name: field.name, level })
+                            Some(DeadItem { def_id, name: field.name, level })
                         } else {
                             None
                         }
                     })
                     .collect();
-                visitor.warn_dead_fields_and_variants(def_id, "read", dead_fields, is_positional)
+                visitor.warn_multiple(def_id, "read", dead_fields, is_positional);
             }
 
-            visitor.warn_dead_fields_and_variants(
-                item.owner_id.def_id,
-                "constructed",
-                dead_variants,
-                false,
-            );
+            visitor.warn_multiple(item.owner_id.def_id, "constructed", dead_variants, false);
         }
     }
 
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 4f71704b885..c92d0b878ea 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -52,31 +52,6 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
     configure_main(tcx, &ctxt)
 }
 
-// Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs`
-// (with `ast::Item`), so make sure to keep them in sync.
-// A small optimization was added so that hir::Item is fetched only when needed.
-// An equivalent optimization was not applied to the duplicated code in test_harness.rs.
-fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> EntryPointType {
-    let attrs = ctxt.tcx.hir().attrs(id.hir_id());
-    if attr::contains_name(attrs, sym::start) {
-        EntryPointType::Start
-    } else if attr::contains_name(attrs, sym::rustc_main) {
-        EntryPointType::RustcMainAttr
-    } else {
-        if let Some(name) = ctxt.tcx.opt_item_name(id.owner_id.to_def_id())
-            && name == sym::main {
-            if at_root {
-                // This is a top-level function so can be `main`.
-                EntryPointType::MainNamed
-            } else {
-                EntryPointType::OtherMain
-            }
-        } else {
-            EntryPointType::None
-        }
-    }
-}
-
 fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Option<Span> {
     let attrs = ctxt.tcx.hir().attrs(id.hir_id());
     attr::find_by_name(attrs, sym).map(|attr| attr.span)
@@ -85,7 +60,13 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti
 fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
     let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID);
 
-    match entry_point_type(ctxt, id, at_root) {
+    let attrs = ctxt.tcx.hir().attrs(id.hir_id());
+    let entry_point_type = rustc_ast::entry::entry_point_type(
+        attrs,
+        at_root,
+        ctxt.tcx.opt_item_name(id.owner_id.to_def_id()),
+    );
+    match entry_point_type {
         EntryPointType::None => {
             if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
                 ctxt.tcx.sess.emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
diff --git a/compiler/rustc_query_system/messages.ftl b/compiler/rustc_query_system/messages.ftl
index d5fed8fe179..d7ab7557511 100644
--- a/compiler/rustc_query_system/messages.ftl
+++ b/compiler/rustc_query_system/messages.ftl
@@ -15,8 +15,6 @@ query_system_cycle_stack_single = ...which immediately requires {$stack_bottom}
 
 query_system_cycle_usage = cycle used when {$usage}
 
-query_system_cycle_which_requires = ...which requires {$desc}...
-
 query_system_increment_compilation = internal compiler error: encountered incremental compilation error with {$dep_node}
     .help = This is a known issue with the compiler. Run {$run_cmd} to allow your project to compile
 
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 9a970f5db39..272483d4a98 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -130,9 +130,6 @@ resolve_generic_params_from_outer_item_ty_param = type parameter from outer item
 resolve_glob_import_doesnt_reexport =
     glob import doesn't reexport anything because no candidate is public enough
 
-resolve_help_try_using_local_generic_param =
-    try using a local generic parameter instead
-
 resolve_ident_bound_more_than_once_in_parameter_list =
     identifier `{$identifier}` is bound more than once in this parameter list
     .label = used as parameter more than once
@@ -249,9 +246,6 @@ resolve_self_in_generic_param_default =
     generic parameters cannot use `Self` in their defaults
     .label = `Self` in generic parameter default
 
-resolve_self_type_implicitly_declared_by_impl =
-    `Self` type implicitly declared here, by this `impl`
-
 resolve_tool_module_imported =
     cannot use a tool module through an import
     .note = the tool module imported here
@@ -267,12 +261,6 @@ resolve_trait_impl_mismatch =
     .label = does not match trait
     .label_trait_item = item in trait
 
-resolve_try_adding_local_generic_param_on_method =
-    try adding a local generic parameter in this method instead
-
-resolve_try_using_local_generic_parameter =
-    try using a local generic parameter instead
-
 resolve_try_using_similarly_named_label =
     try using similarly named label
 
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 907a6b1c46c..110286255c5 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1169,6 +1169,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     return;
                 }
 
+                if ident.name == kw::Underscore {
+                    return;
+                }
+
                 let child_accessible =
                     accessible && this.is_accessible_from(name_binding.vis, parent_scope.module);
 
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 15ec727e4c9..ece8b7f6ec9 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -41,9 +41,6 @@ type Res = def::Res<NodeId>;
 
 type IdentMap<T> = FxHashMap<Ident, T>;
 
-/// Map from the name in a pattern to its binding mode.
-type BindingMap = IdentMap<BindingInfo>;
-
 use diagnostics::{
     ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime, MissingLifetimeKind,
 };
@@ -3164,8 +3161,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
     /// this is done hygienically. This could arise for a macro
     /// that expands into an or-pattern where one 'x' was from the
     /// user and one 'x' came from the macro.
-    fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
-        let mut binding_map = FxHashMap::default();
+    fn binding_mode_map(&mut self, pat: &Pat) -> FxIndexMap<Ident, BindingInfo> {
+        let mut binding_map = FxIndexMap::default();
 
         pat.walk(&mut |pat| {
             match pat.kind {
@@ -3200,22 +3197,28 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
 
     /// Checks that all of the arms in an or-pattern have exactly the
     /// same set of bindings, with the same binding modes for each.
-    fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) -> Vec<BindingMap> {
-        let mut missing_vars = FxHashMap::default();
-        let mut inconsistent_vars = FxHashMap::default();
+    fn check_consistent_bindings(
+        &mut self,
+        pats: &[P<Pat>],
+    ) -> Vec<FxIndexMap<Ident, BindingInfo>> {
+        // pats is consistent.
+        let mut missing_vars = FxIndexMap::default();
+        let mut inconsistent_vars = FxIndexMap::default();
 
         // 1) Compute the binding maps of all arms.
         let maps = pats.iter().map(|pat| self.binding_mode_map(pat)).collect::<Vec<_>>();
 
         // 2) Record any missing bindings or binding mode inconsistencies.
-        for (map_outer, pat_outer) in pats.iter().enumerate().map(|(idx, pat)| (&maps[idx], pat)) {
+        for (map_outer, pat_outer) in maps.iter().zip(pats.iter()) {
             // Check against all arms except for the same pattern which is always self-consistent.
-            let inners = pats
+            let inners = maps
                 .iter()
-                .enumerate()
+                .zip(pats.iter())
                 .filter(|(_, pat)| pat.id != pat_outer.id)
-                .flat_map(|(idx, _)| maps[idx].iter())
-                .map(|(key, binding)| (key.name, map_outer.get(&key), binding));
+                .flat_map(|(map, _)| map)
+                .map(|(key, binding)| (key.name, map_outer.get(key), binding));
+
+            let inners = inners.collect::<Vec<_>>();
 
             for (name, info, &binding_inner) in inners {
                 match info {
@@ -3244,10 +3247,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         }
 
         // 3) Report all missing variables we found.
-        let mut missing_vars = missing_vars.into_iter().collect::<Vec<_>>();
-        missing_vars.sort_by_key(|&(sym, ref _err)| sym);
-
-        for (name, mut v) in missing_vars.into_iter() {
+        for (name, mut v) in missing_vars {
             if inconsistent_vars.contains_key(&name) {
                 v.could_be_path = false;
             }
@@ -3258,10 +3258,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         }
 
         // 4) Report all inconsistencies in binding modes we found.
-        let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>();
-        inconsistent_vars.sort();
         for (name, v) in inconsistent_vars {
-            self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1));
+            self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1));
         }
 
         // 5) Finally bubble up all the binding maps.
diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl
index e06b6380944..b356b503aa5 100644
--- a/compiler/rustc_session/messages.ftl
+++ b/compiler/rustc_session/messages.ftl
@@ -25,8 +25,6 @@ session_feature_diagnostic_for_issue =
 session_feature_diagnostic_help =
     add `#![feature({$feature})]` to the crate attributes to enable
 
-session_feature_gate_error = {$explain}
-
 session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions
 
 session_file_write_fail = failed to write `{$path}` due to error `{$err}`
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index c6c97ce35e8..7d1122c2fd2 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -15,7 +15,7 @@ use rustc_middle::mir::interpret::{alloc_range, AllocId};
 use rustc_middle::ty::{self, Ty, TyCtxt, Variance};
 use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_target::abi::FieldIdx;
-use stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx};
+use stable_mir::mir::{CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx};
 use stable_mir::ty::{FloatTy, GenericParamDef, IntTy, Movability, RigidTy, Span, TyKind, UintTy};
 use stable_mir::{self, opaque, Context};
 use tracing::debug;
@@ -106,7 +106,14 @@ impl<'tcx> Context for Tables<'tcx> {
                         .collect(),
                 })
                 .collect(),
-            locals: mir.local_decls.iter().map(|decl| self.intern_ty(decl.ty)).collect(),
+            locals: mir
+                .local_decls
+                .iter()
+                .map(|decl| stable_mir::mir::LocalDecl {
+                    ty: self.intern_ty(decl.ty),
+                    span: decl.source_info.span.stable(self),
+                })
+                .collect(),
         }
     }
 
@@ -223,41 +230,64 @@ pub(crate) trait Stable<'tcx> {
 impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
     type T = stable_mir::mir::Statement;
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
-        use rustc_middle::mir::StatementKind::*;
-        match &self.kind {
-            Assign(assign) => {
-                stable_mir::mir::Statement::Assign(assign.0.stable(tables), assign.1.stable(tables))
-            }
-            FakeRead(fake_read_place) => stable_mir::mir::Statement::FakeRead(
-                fake_read_place.0.stable(tables),
-                fake_read_place.1.stable(tables),
+        Statement { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> {
+    type T = stable_mir::mir::StatementKind;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        match self {
+            mir::StatementKind::Assign(assign) => stable_mir::mir::StatementKind::Assign(
+                assign.0.stable(tables),
+                assign.1.stable(tables),
             ),
-            SetDiscriminant { place: plc, variant_index: idx } => {
-                stable_mir::mir::Statement::SetDiscriminant {
-                    place: plc.as_ref().stable(tables),
-                    variant_index: idx.stable(tables),
+            mir::StatementKind::FakeRead(fake_read_place) => {
+                stable_mir::mir::StatementKind::FakeRead(
+                    fake_read_place.0.stable(tables),
+                    fake_read_place.1.stable(tables),
+                )
+            }
+            mir::StatementKind::SetDiscriminant { place, variant_index } => {
+                stable_mir::mir::StatementKind::SetDiscriminant {
+                    place: place.as_ref().stable(tables),
+                    variant_index: variant_index.stable(tables),
                 }
             }
-            Deinit(place) => stable_mir::mir::Statement::Deinit(place.stable(tables)),
-            StorageLive(place) => stable_mir::mir::Statement::StorageLive(place.stable(tables)),
-            StorageDead(place) => stable_mir::mir::Statement::StorageDead(place.stable(tables)),
-            Retag(retag, place) => {
-                stable_mir::mir::Statement::Retag(retag.stable(tables), place.stable(tables))
+            mir::StatementKind::Deinit(place) => {
+                stable_mir::mir::StatementKind::Deinit(place.stable(tables))
+            }
+
+            mir::StatementKind::StorageLive(place) => {
+                stable_mir::mir::StatementKind::StorageLive(place.stable(tables))
+            }
+
+            mir::StatementKind::StorageDead(place) => {
+                stable_mir::mir::StatementKind::StorageDead(place.stable(tables))
+            }
+            mir::StatementKind::Retag(retag, place) => {
+                stable_mir::mir::StatementKind::Retag(retag.stable(tables), place.stable(tables))
+            }
+            mir::StatementKind::PlaceMention(place) => {
+                stable_mir::mir::StatementKind::PlaceMention(place.stable(tables))
             }
-            PlaceMention(place) => stable_mir::mir::Statement::PlaceMention(place.stable(tables)),
-            AscribeUserType(place_projection, variance) => {
-                stable_mir::mir::Statement::AscribeUserType {
+            mir::StatementKind::AscribeUserType(place_projection, variance) => {
+                stable_mir::mir::StatementKind::AscribeUserType {
                     place: place_projection.as_ref().0.stable(tables),
                     projections: place_projection.as_ref().1.stable(tables),
                     variance: variance.stable(tables),
                 }
             }
-            Coverage(coverage) => stable_mir::mir::Statement::Coverage(opaque(coverage)),
-            Intrinsic(intrinstic) => {
-                stable_mir::mir::Statement::Intrinsic(intrinstic.stable(tables))
+            mir::StatementKind::Coverage(coverage) => {
+                stable_mir::mir::StatementKind::Coverage(opaque(coverage))
+            }
+            mir::StatementKind::Intrinsic(intrinstic) => {
+                stable_mir::mir::StatementKind::Intrinsic(intrinstic.stable(tables))
+            }
+            mir::StatementKind::ConstEvalCounter => {
+                stable_mir::mir::StatementKind::ConstEvalCounter
             }
-            ConstEvalCounter => stable_mir::mir::Statement::ConstEvalCounter,
-            Nop => stable_mir::mir::Statement::Nop,
+            mir::StatementKind::Nop => stable_mir::mir::StatementKind::Nop,
         }
     }
 }
@@ -806,11 +836,20 @@ impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
 impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
     type T = stable_mir::mir::Terminator;
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
-        use rustc_middle::mir::TerminatorKind::*;
         use stable_mir::mir::Terminator;
-        match &self.kind {
-            Goto { target } => Terminator::Goto { target: target.as_usize() },
-            SwitchInt { discr, targets } => Terminator::SwitchInt {
+        Terminator { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
+    type T = stable_mir::mir::TerminatorKind;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::mir::TerminatorKind;
+        match self {
+            mir::TerminatorKind::Goto { target } => {
+                TerminatorKind::Goto { target: target.as_usize() }
+            }
+            mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt {
                 discr: discr.stable(tables),
                 targets: targets
                     .iter()
@@ -821,42 +860,60 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
                     .collect(),
                 otherwise: targets.otherwise().as_usize(),
             },
-            UnwindResume => Terminator::Resume,
-            UnwindTerminate(_) => Terminator::Abort,
-            Return => Terminator::Return,
-            Unreachable => Terminator::Unreachable,
-            Drop { place, target, unwind, replace: _ } => Terminator::Drop {
-                place: place.stable(tables),
-                target: target.as_usize(),
-                unwind: unwind.stable(tables),
-            },
-            Call { func, args, destination, target, unwind, call_source: _, fn_span: _ } => {
-                Terminator::Call {
-                    func: func.stable(tables),
-                    args: args.iter().map(|arg| arg.stable(tables)).collect(),
-                    destination: destination.stable(tables),
-                    target: target.map(|t| t.as_usize()),
+            mir::TerminatorKind::UnwindResume => TerminatorKind::Resume,
+            mir::TerminatorKind::UnwindTerminate(_) => TerminatorKind::Abort,
+            mir::TerminatorKind::Return => TerminatorKind::Return,
+            mir::TerminatorKind::Unreachable => TerminatorKind::Unreachable,
+            mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => {
+                TerminatorKind::Drop {
+                    place: place.stable(tables),
+                    target: target.as_usize(),
                     unwind: unwind.stable(tables),
                 }
             }
-            Assert { cond, expected, msg, target, unwind } => Terminator::Assert {
-                cond: cond.stable(tables),
-                expected: *expected,
-                msg: msg.stable(tables),
-                target: target.as_usize(),
+            mir::TerminatorKind::Call {
+                func,
+                args,
+                destination,
+                target,
+                unwind,
+                call_source: _,
+                fn_span: _,
+            } => TerminatorKind::Call {
+                func: func.stable(tables),
+                args: args.iter().map(|arg| arg.stable(tables)).collect(),
+                destination: destination.stable(tables),
+                target: target.map(|t| t.as_usize()),
                 unwind: unwind.stable(tables),
             },
-            InlineAsm { template, operands, options, line_spans, destination, unwind } => {
-                Terminator::InlineAsm {
-                    template: format!("{template:?}"),
-                    operands: operands.iter().map(|operand| operand.stable(tables)).collect(),
-                    options: format!("{options:?}"),
-                    line_spans: format!("{line_spans:?}"),
-                    destination: destination.map(|d| d.as_usize()),
+            mir::TerminatorKind::Assert { cond, expected, msg, target, unwind } => {
+                TerminatorKind::Assert {
+                    cond: cond.stable(tables),
+                    expected: *expected,
+                    msg: msg.stable(tables),
+                    target: target.as_usize(),
                     unwind: unwind.stable(tables),
                 }
             }
-            Yield { .. } | GeneratorDrop | FalseEdge { .. } | FalseUnwind { .. } => unreachable!(),
+            mir::TerminatorKind::InlineAsm {
+                template,
+                operands,
+                options,
+                line_spans,
+                destination,
+                unwind,
+            } => TerminatorKind::InlineAsm {
+                template: format!("{template:?}"),
+                operands: operands.iter().map(|operand| operand.stable(tables)).collect(),
+                options: format!("{options:?}"),
+                line_spans: format!("{line_spans:?}"),
+                destination: destination.map(|d| d.as_usize()),
+                unwind: unwind.stable(tables),
+            },
+            mir::TerminatorKind::Yield { .. }
+            | mir::TerminatorKind::GeneratorDrop
+            | mir::TerminatorKind::FalseEdge { .. }
+            | mir::TerminatorKind::FalseUnwind { .. } => unreachable!(),
         }
     }
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 4f46256626f..a62fa246ac4 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -129,9 +129,11 @@ symbols! {
         Alignment,
         Any,
         Arc,
+        ArcWeak,
         Argument,
         ArgumentMethods,
         Arguments,
+        ArrayIntoIter,
         AsMut,
         AsRef,
         AssertParamIsClone,
@@ -164,6 +166,7 @@ symbols! {
         Capture,
         Center,
         Clone,
+        Command,
         ConstParamTy,
         Context,
         Continue,
@@ -171,6 +174,7 @@ symbols! {
         Count,
         Cow,
         Debug,
+        DebugStruct,
         Decodable,
         Decoder,
         DecorateLint,
@@ -194,6 +198,8 @@ symbols! {
         From,
         FromIterator,
         FromResidual,
+        FsOpenOptions,
+        FsPermissions,
         Future,
         FutureOutput,
         FxHashMap,
@@ -207,16 +213,22 @@ symbols! {
         Implied,
         IndexOutput,
         Input,
+        Instant,
         Into,
         IntoDiagnostic,
         IntoFuture,
         IntoIterator,
+        IoLines,
         IoRead,
+        IoSeek,
         IoWrite,
         IpAddr,
         IrTyKind,
         Is,
         ItemContext,
+        IterEmpty,
+        IterOnce,
+        IterPeekable,
         Iterator,
         IteratorItem,
         Layout,
@@ -227,6 +239,7 @@ symbols! {
         Mutex,
         MutexGuard,
         N,
+        NonNull,
         NonZeroI128,
         NonZeroI16,
         NonZeroI32,
@@ -259,15 +272,19 @@ symbols! {
         ProcMacro,
         ProceduralMasqueradeDummyType,
         Range,
+        RangeBounds,
         RangeFrom,
         RangeFull,
         RangeInclusive,
         RangeTo,
         RangeToInclusive,
         Rc,
+        RcWeak,
         Ready,
         Receiver,
         RefCell,
+        RefCellRef,
+        RefCellRefMut,
         Relaxed,
         Release,
         Result,
@@ -284,6 +301,7 @@ symbols! {
         Send,
         SeqCst,
         SliceIndex,
+        SliceIter,
         Some,
         String,
         StructuralEq,
@@ -561,6 +579,7 @@ symbols! {
         constant,
         constructor,
         context,
+        convert_identity,
         copy,
         copy_closures,
         copy_nonoverlapping,
@@ -616,6 +635,7 @@ symbols! {
         declare_lint_pass,
         decode,
         default_alloc_error_handler,
+        default_fn,
         default_lib_allocator,
         default_method_body_is_const,
         default_type_parameter_fallback,
@@ -628,6 +648,7 @@ symbols! {
         deref,
         deref_method,
         deref_mut,
+        deref_mut_method,
         deref_target,
         derive,
         derive_const,
@@ -777,11 +798,14 @@ symbols! {
         from_desugaring,
         from_fn,
         from_iter,
+        from_iter_fn,
         from_output,
         from_residual,
         from_size_align_unchecked,
+        from_str_method,
         from_usize,
         from_yeet,
+        fs_create_dir,
         fsub_fast,
         fundamental,
         future,
@@ -868,6 +892,10 @@ symbols! {
         into_iter,
         intra_doc_pointers,
         intrinsics,
+        intrinsics_unaligned_volatile_load,
+        intrinsics_unaligned_volatile_store,
+        io_stderr,
+        io_stdout,
         irrefutable_let_patterns,
         isa_attribute,
         isize,
@@ -962,6 +990,7 @@ symbols! {
         mem_replace,
         mem_size_of,
         mem_size_of_val,
+        mem_swap,
         mem_uninitialized,
         mem_variant_count,
         mem_zeroed,
@@ -1091,6 +1120,7 @@ symbols! {
         options,
         or,
         or_patterns,
+        ord_cmp_method,
         other,
         out,
         overflow_checks,
@@ -1104,7 +1134,6 @@ symbols! {
         panic_abort,
         panic_bounds_check,
         panic_cannot_unwind,
-        panic_display,
         panic_fmt,
         panic_handler,
         panic_impl,
@@ -1172,6 +1201,7 @@ symbols! {
         proc_macro_mod,
         proc_macro_non_items,
         proc_macro_path_invoc,
+        process_exit,
         profiler_builtins,
         profiler_runtime,
         ptr,
@@ -1179,6 +1209,10 @@ symbols! {
         ptr_cast_const,
         ptr_cast_mut,
         ptr_const_is_null,
+        ptr_copy,
+        ptr_copy_nonoverlapping,
+        ptr_drop_in_place,
+        ptr_eq,
         ptr_from_ref,
         ptr_guaranteed_cmp,
         ptr_is_null,
@@ -1187,8 +1221,17 @@ symbols! {
         ptr_null_mut,
         ptr_offset_from,
         ptr_offset_from_unsigned,
+        ptr_read,
+        ptr_read_unaligned,
+        ptr_read_volatile,
+        ptr_replace,
+        ptr_slice_from_raw_parts,
+        ptr_slice_from_raw_parts_mut,
+        ptr_swap,
+        ptr_swap_nonoverlapping,
         ptr_unique,
         ptr_write,
+        ptr_write_bytes,
         ptr_write_unaligned,
         ptr_write_volatile,
         pub_macro_rules,
@@ -1299,6 +1342,7 @@ symbols! {
         rustc_coherence_is_core,
         rustc_coinductive,
         rustc_confusables,
+        rustc_const_panic_str,
         rustc_const_stable,
         rustc_const_unstable,
         rustc_conversion_suggestion,
@@ -1478,6 +1522,8 @@ symbols! {
         sized,
         skip,
         slice,
+        slice_from_raw_parts,
+        slice_from_raw_parts_mut,
         slice_len_fn,
         slice_patterns,
         slicing_syntax,
@@ -1565,7 +1611,9 @@ symbols! {
         thumb2,
         thumb_mode: "thumb-mode",
         tmm_reg,
+        to_owned_method,
         to_string,
+        to_string_method,
         to_vec,
         todo_macro,
         tool_attributes,
@@ -1588,6 +1636,7 @@ symbols! {
         try_blocks,
         try_capture,
         try_from,
+        try_from_fn,
         try_into,
         try_trait_v2,
         tt,
diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml
index 393e59e8b00..a91eb41b18a 100644
--- a/compiler/rustc_target/Cargo.toml
+++ b/compiler/rustc_target/Cargo.toml
@@ -14,6 +14,7 @@ rustc_feature = { path = "../rustc_feature" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
+rustc_index = { path = "../rustc_index" }
 
 [dependencies.object]
 version = "0.32.0"
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 74fe98920c4..f6f8b53d130 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -1,3 +1,4 @@
+use rustc_data_structures::intern::Interned;
 pub use Integer::*;
 pub use Primitive::*;
 
@@ -18,6 +19,111 @@ impl ToJson for Endian {
     }
 }
 
+rustc_index::newtype_index! {
+    /// The *source-order* index of a field in a variant.
+    ///
+    /// This is how most code after type checking refers to fields, rather than
+    /// using names (as names have hygiene complications and more complex lookup).
+    ///
+    /// Particularly for `repr(Rust)` types, this may not be the same as *layout* order.
+    /// (It is for `repr(C)` `struct`s, however.)
+    ///
+    /// For example, in the following types,
+    /// ```rust
+    /// # enum Never {}
+    /// # #[repr(u16)]
+    /// enum Demo1 {
+    ///    Variant0 { a: Never, b: i32 } = 100,
+    ///    Variant1 { c: u8, d: u64 } = 10,
+    /// }
+    /// struct Demo2 { e: u8, f: u16, g: u8 }
+    /// ```
+    /// `b` is `FieldIdx(1)` in `VariantIdx(0)`,
+    /// `d` is `FieldIdx(1)` in `VariantIdx(1)`, and
+    /// `f` is `FieldIdx(1)` in `VariantIdx(0)`.
+    #[derive(HashStable_Generic)]
+    pub struct FieldIdx {}
+}
+
+rustc_index::newtype_index! {
+    /// The *source-order* index of a variant in a type.
+    ///
+    /// For enums, these are always `0..variant_count`, regardless of any
+    /// custom discriminants that may have been defined, and including any
+    /// variants that may end up uninhabited due to field types.  (Some of the
+    /// variants may not be present in a monomorphized ABI [`Variants`], but
+    /// those skipped variants are always counted when determining the *index*.)
+    ///
+    /// `struct`s, `tuples`, and `unions`s are considered to have a single variant
+    /// with variant index zero, aka [`FIRST_VARIANT`].
+    #[derive(HashStable_Generic)]
+    pub struct VariantIdx {
+        /// Equivalent to `VariantIdx(0)`.
+        const FIRST_VARIANT = 0;
+    }
+}
+#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
+#[rustc_pass_by_value]
+pub struct Layout<'a>(pub Interned<'a, LayoutS<FieldIdx, VariantIdx>>);
+
+impl<'a> fmt::Debug for Layout<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // See comment on `<LayoutS as Debug>::fmt` above.
+        self.0.0.fmt(f)
+    }
+}
+
+impl<'a> Deref for Layout<'a> {
+    type Target = &'a LayoutS<FieldIdx, VariantIdx>;
+    fn deref(&self) -> &&'a LayoutS<FieldIdx, VariantIdx> {
+        &self.0.0
+    }
+}
+
+impl<'a> Layout<'a> {
+    pub fn fields(self) -> &'a FieldsShape<FieldIdx> {
+        &self.0.0.fields
+    }
+
+    pub fn variants(self) -> &'a Variants<FieldIdx, VariantIdx> {
+        &self.0.0.variants
+    }
+
+    pub fn abi(self) -> Abi {
+        self.0.0.abi
+    }
+
+    pub fn largest_niche(self) -> Option<Niche> {
+        self.0.0.largest_niche
+    }
+
+    pub fn align(self) -> AbiAndPrefAlign {
+        self.0.0.align
+    }
+
+    pub fn size(self) -> Size {
+        self.0.0.size
+    }
+
+    pub fn max_repr_align(self) -> Option<Align> {
+        self.0.0.max_repr_align
+    }
+
+    pub fn unadjusted_abi_align(self) -> Align {
+        self.0.0.unadjusted_abi_align
+    }
+
+    /// Whether the layout is from a type that implements [`std::marker::PointerLike`].
+    ///
+    /// Currently, that means that the type is pointer-sized, pointer-aligned,
+    /// and has a scalar ABI.
+    pub fn is_pointer_like(self, data_layout: &TargetDataLayout) -> bool {
+        self.size() == data_layout.pointer_size
+            && self.align().abi == data_layout.pointer_align.abi
+            && matches!(self.abi(), Abi::Scalar(..))
+    }
+}
+
 /// The layout of a type, alongside the type itself.
 /// Provides various type traversal APIs (e.g., recursing into fields).
 ///
@@ -42,8 +148,8 @@ impl<'a, Ty: fmt::Display> fmt::Debug for TyAndLayout<'a, Ty> {
 }
 
 impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
-    type Target = &'a LayoutS;
-    fn deref(&self) -> &&'a LayoutS {
+    type Target = &'a LayoutS<FieldIdx, VariantIdx>;
+    fn deref(&self) -> &&'a LayoutS<FieldIdx, VariantIdx> {
         &self.layout.0.0
     }
 }
diff --git a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
index 8d80fcd5fe5..624837a22d6 100644
--- a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
@@ -3,7 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions};
 // This target if is for the Android v7a ABI in thumb mode with
 // NEON unconditionally enabled and, therefore, with 32 FPU registers
 // enabled as well. See section A2.6.2 on page A2-56 in
-// https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf
+// https://web.archive.org/web/20210307234416/https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf
 
 // See https://developer.android.com/ndk/guides/abis.html#v7a
 // for target ABI requirements.
diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs
index 28c81340ad8..b500c50de98 100644
--- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs
@@ -4,7 +4,7 @@ use crate::spec::{Target, TargetOptions};
 // (for consistency with Android and Debian-based distributions)
 // and with NEON unconditionally enabled and, therefore, with 32 FPU
 // registers enabled as well. See section A2.6.2 on page A2-56 in
-// https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf
+// https://web.archive.org/web/20210307234416/https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf
 
 pub fn target() -> Target {
     Target {
diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs
index 2c375ab22d7..dce0cbcef02 100644
--- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs
@@ -4,7 +4,7 @@ use crate::spec::{Target, TargetOptions};
 // (for consistency with Android and Debian-based distributions)
 // and with NEON unconditionally enabled and, therefore, with 32 FPU
 // registers enabled as well. See section A2.6.2 on page A2-56 in
-// https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf
+// https://web.archive.org/web/20210307234416/https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf
 
 pub fn target() -> Target {
     Target {
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 0f9d36342ad..339a3e73846 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -346,14 +346,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
             ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output])
         });
 
-        let pred = ty::Clause::from_projection_clause(
-            tcx,
-            tupled_inputs_and_output.map_bound(|(inputs, output)| ty::ProjectionPredicate {
+        let pred = tupled_inputs_and_output
+            .map_bound(|(inputs, output)| ty::ProjectionPredicate {
                 projection_ty: tcx
                     .mk_alias_ty(goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]),
                 term: output.into(),
-            }),
-        );
+            })
+            .to_predicate(tcx);
 
         // A built-in `Fn` impl only holds if the output is sized.
         // (FIXME: technically we only need to check this if the type is a fn ptr...)
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 820973dc090..015e38b2ac0 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -23,6 +23,7 @@ use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::TypeFoldable;
+use rustc_middle::ty::Variance;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::config::TraitSolver;
 
@@ -156,6 +157,20 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
             .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
     }
 
+    pub fn relate<T: ToTrace<'tcx>>(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        variance: Variance,
+        expected: T,
+        actual: T,
+    ) -> Result<(), TypeError<'tcx>> {
+        self.infcx
+            .at(cause, param_env)
+            .relate(DefineOpaqueTypes::Yes, expected, variance, actual)
+            .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
+    }
+
     /// Checks whether `expected` is a supertype of `actual`: `expected :> actual`.
     pub fn sup<T: ToTrace<'tcx>>(
         &self,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 2a586f810d6..9a728b1060f 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-filelength :(
+
 mod ambiguity;
 pub mod on_unimplemented;
 pub mod suggestions;
@@ -67,6 +69,7 @@ pub enum CandidateSimilarity {
 pub struct ImplCandidate<'tcx> {
     pub trait_ref: ty::TraitRef<'tcx>,
     pub similarity: CandidateSimilarity,
+    impl_def_id: DefId,
 }
 
 enum GetSafeTransmuteErrorAndReason {
@@ -1331,6 +1334,7 @@ trait InferCtxtPrivExt<'tcx> {
         body_def_id: LocalDefId,
         err: &mut Diagnostic,
         other: bool,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> bool;
 
     fn report_similar_impl_candidates_for_root_obligation(
@@ -1918,8 +1922,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
                 let imp = self.tcx.impl_trait_ref(def_id).unwrap().skip_binder();
 
-                self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false)
-                    .map(|similarity| ImplCandidate { trait_ref: imp, similarity })
+                self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map(
+                    |similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id },
+                )
             })
             .collect();
         if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) {
@@ -1938,7 +1943,82 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         body_def_id: LocalDefId,
         err: &mut Diagnostic,
         other: bool,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> bool {
+        // If we have a single implementation, try to unify it with the trait ref
+        // that failed. This should uncover a better hint for what *is* implemented.
+        if let [single] = &impl_candidates {
+            if self.probe(|_| {
+                let ocx = ObligationCtxt::new(self);
+                let obligation_trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
+                let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id);
+                let impl_trait_ref = ocx.normalize(
+                    &ObligationCause::dummy(),
+                    param_env,
+                    ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args),
+                );
+
+                ocx.register_obligations(
+                    self.tcx
+                        .predicates_of(single.impl_def_id)
+                        .instantiate(self.tcx, impl_args)
+                        .into_iter()
+                        .map(|(clause, _)| {
+                            Obligation::new(self.tcx, ObligationCause::dummy(), param_env, clause)
+                        }),
+                );
+                if !ocx.select_where_possible().is_empty() {
+                    return false;
+                }
+
+                let mut terrs = vec![];
+                for (obligation_arg, impl_arg) in
+                    std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args)
+                {
+                    if let Err(terr) =
+                        ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg)
+                    {
+                        terrs.push(terr);
+                    }
+                    if !ocx.select_where_possible().is_empty() {
+                        return false;
+                    }
+                }
+
+                // Literally nothing unified, just give up.
+                if terrs.len() == impl_trait_ref.args.len() {
+                    return false;
+                }
+
+                let cand =
+                    self.resolve_vars_if_possible(impl_trait_ref).fold_with(&mut BottomUpFolder {
+                        tcx: self.tcx,
+                        ty_op: |ty| ty,
+                        lt_op: |lt| lt,
+                        ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()),
+                    });
+                err.highlighted_help(vec![
+                    (format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle),
+                    ("is".to_string(), Style::Highlight),
+                    (" implemented for `".to_string(), Style::NoStyle),
+                    (cand.self_ty().to_string(), Style::Highlight),
+                    ("`".to_string(), Style::NoStyle),
+                ]);
+
+                if let [TypeError::Sorts(exp_found)] = &terrs[..] {
+                    let exp_found = self.resolve_vars_if_possible(*exp_found);
+                    err.help(format!(
+                        "for that trait implementation, expected `{}`, found `{}`",
+                        exp_found.expected, exp_found.found
+                    ));
+                }
+
+                true
+            }) {
+                return true;
+            }
+        }
+
         let other = if other { "other " } else { "" };
         let report = |candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
             if candidates.is_empty() {
@@ -2062,9 +2142,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             })
             .collect();
         impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref));
+        let mut impl_candidates: Vec<_> =
+            impl_candidates.into_iter().map(|cand| cand.trait_ref).collect();
         impl_candidates.dedup();
 
-        report(impl_candidates.into_iter().map(|cand| cand.trait_ref).collect(), err)
+        report(impl_candidates, err)
     }
 
     fn report_similar_impl_candidates_for_root_obligation(
@@ -2108,6 +2190,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 body_def_id,
                 err,
                 true,
+                obligation.param_env,
             );
         }
     }
@@ -2316,6 +2399,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             obligation.cause.body_id,
                             &mut err,
                             false,
+                            obligation.param_env,
                         );
                     }
                 }
@@ -3051,6 +3135,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 body_def_id,
                 err,
                 true,
+                obligation.param_env,
             ) {
                 self.report_similar_impl_candidates_for_root_obligation(
                     &obligation,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 15f2ba809a4..b7c73501280 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -4000,14 +4000,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         // ... whose signature is `async` (i.e. this is an AFIT)
         let (sig, body) = item.expect_fn();
-        let hir::IsAsync::Async(async_span) = sig.header.asyncness else {
-            return;
-        };
-        let Ok(async_span) =
-            self.tcx.sess.source_map().span_extend_while(async_span, |c| c.is_whitespace())
-        else {
-            return;
-        };
         let hir::FnRetTy::Return(hir::Ty { kind: hir::TyKind::OpaqueDef(def, ..), .. }) =
             sig.decl.output
         else {
@@ -4021,55 +4013,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             return;
         }
 
-        let future = self.tcx.hir().item(*def).expect_opaque_ty();
-        let Some(hir::GenericBound::LangItemTrait(_, _, _, generics)) = future.bounds.get(0) else {
-            // `async fn` should always lower to a lang item bound... but don't ICE.
-            return;
-        };
-        let Some(hir::TypeBindingKind::Equality { term: hir::Term::Ty(future_output_ty) }) =
-            generics.bindings.get(0).map(|binding| binding.kind)
-        else {
-            // Also should never happen.
+        let Some(sugg) = suggest_desugaring_async_fn_to_impl_future_in_trait(
+            self.tcx,
+            *sig,
+            *body,
+            opaque_def_id.expect_local(),
+            &format!(" + {auto_trait}"),
+        ) else {
             return;
         };
 
         let function_name = self.tcx.def_path_str(fn_def_id);
-
-        let mut sugg = if future_output_ty.span.is_empty() {
-            vec![
-                (async_span, String::new()),
-                (
-                    future_output_ty.span,
-                    format!(" -> impl std::future::Future<Output = ()> + {auto_trait}"),
-                ),
-            ]
-        } else {
-            vec![
-                (
-                    future_output_ty.span.shrink_to_lo(),
-                    "impl std::future::Future<Output = ".to_owned(),
-                ),
-                (future_output_ty.span.shrink_to_hi(), format!("> + {auto_trait}")),
-                (async_span, String::new()),
-            ]
-        };
-
-        // If there's a body, we also need to wrap it in `async {}`
-        if let hir::TraitFn::Provided(body) = body {
-            let body = self.tcx.hir().body(*body);
-            let body_span = body.value.span;
-            let body_span_without_braces =
-                body_span.with_lo(body_span.lo() + BytePos(1)).with_hi(body_span.hi() - BytePos(1));
-            if body_span_without_braces.is_empty() {
-                sugg.push((body_span_without_braces, " async {} ".to_owned()));
-            } else {
-                sugg.extend([
-                    (body_span_without_braces.shrink_to_lo(), "async {".to_owned()),
-                    (body_span_without_braces.shrink_to_hi(), "} ".to_owned()),
-                ]);
-            }
-        }
-
         err.multipart_suggestion(
             format!(
                 "`{auto_trait}` can be made part of the associated future's \
@@ -4321,3 +4275,65 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceImplTraitFolder<'tcx> {
         self.tcx
     }
 }
+
+pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    sig: hir::FnSig<'tcx>,
+    body: hir::TraitFn<'tcx>,
+    opaque_def_id: LocalDefId,
+    add_bounds: &str,
+) -> Option<Vec<(Span, String)>> {
+    let hir::IsAsync::Async(async_span) = sig.header.asyncness else {
+        return None;
+    };
+    let Ok(async_span) = tcx.sess.source_map().span_extend_while(async_span, |c| c.is_whitespace())
+    else {
+        return None;
+    };
+
+    let future = tcx.hir().get_by_def_id(opaque_def_id).expect_item().expect_opaque_ty();
+    let Some(hir::GenericBound::LangItemTrait(_, _, _, generics)) = future.bounds.get(0) else {
+        // `async fn` should always lower to a lang item bound... but don't ICE.
+        return None;
+    };
+    let Some(hir::TypeBindingKind::Equality { term: hir::Term::Ty(future_output_ty) }) =
+        generics.bindings.get(0).map(|binding| binding.kind)
+    else {
+        // Also should never happen.
+        return None;
+    };
+
+    let mut sugg = if future_output_ty.span.is_empty() {
+        vec![
+            (async_span, String::new()),
+            (
+                future_output_ty.span,
+                format!(" -> impl std::future::Future<Output = ()>{add_bounds}"),
+            ),
+        ]
+    } else {
+        vec![
+            (future_output_ty.span.shrink_to_lo(), "impl std::future::Future<Output = ".to_owned()),
+            (future_output_ty.span.shrink_to_hi(), format!(">{add_bounds}")),
+            (async_span, String::new()),
+        ]
+    };
+
+    // If there's a body, we also need to wrap it in `async {}`
+    if let hir::TraitFn::Provided(body) = body {
+        let body = tcx.hir().body(body);
+        let body_span = body.value.span;
+        let body_span_without_braces =
+            body_span.with_lo(body_span.lo() + BytePos(1)).with_hi(body_span.hi() - BytePos(1));
+        if body_span_without_braces.is_empty() {
+            sugg.push((body_span_without_braces, " async {} ".to_owned()));
+        } else {
+            sugg.extend([
+                (body_span_without_braces.shrink_to_lo(), "async {".to_owned()),
+                (body_span_without_braces.shrink_to_hi(), "} ".to_owned()),
+            ]);
+        }
+    }
+
+    Some(sugg)
+}
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 154cc7a7141..73c2ff3c536 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1644,7 +1644,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
     let env_predicates = data
         .projection_bounds()
         .filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
-        .map(|p| ty::Clause::from_projection_clause(tcx, p.with_self_ty(tcx, object_ty)));
+        .map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx));
 
     assemble_candidates_from_predicates(
         selcx,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index bc9ba85fc9f..8871de194a6 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -39,6 +39,7 @@ use rustc_middle::dep_graph::dep_kinds;
 use rustc_middle::dep_graph::DepNodeIndex;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::traits::DefiningAnchor;
+use rustc_middle::ty::_match::MatchAgainstFreshVars;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::relate::TypeRelation;
@@ -2642,7 +2643,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         current: ty::PolyTraitPredicate<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> bool {
-        let mut matcher = ty::_match::Match::new(self.tcx(), param_env);
+        let mut matcher = MatchAgainstFreshVars::new(self.tcx(), param_env);
         matcher.relate(previous, current).is_ok()
     }
 
@@ -3115,9 +3116,6 @@ fn bind_generator_hidden_types_above<'tcx>(
             bty.instantiate(tcx, args)
         })
         .collect();
-    if considering_regions {
-        debug_assert!(!hidden_types.has_erased_regions());
-    }
     let bound_vars =
         tcx.mk_bound_variable_kinds_from_iter(bound_vars.iter().chain(
             (num_bound_variables..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon)),
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index e41073937be..f23c100a686 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -316,7 +316,7 @@ fn vtable_entries<'tcx>(
         dump_vtable_entries(tcx, sp, trait_ref, &entries);
     }
 
-    tcx.arena.alloc_from_iter(entries.into_iter())
+    tcx.arena.alloc_from_iter(entries)
 }
 
 /// Find slot base for trait methods within vtable entries of another trait
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index b04008d9ee5..060df772613 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -105,13 +105,13 @@ pub fn unnormalized_obligations<'tcx>(
 
 /// Returns the obligations that make this trait reference
 /// well-formed. For example, if there is a trait `Set` defined like
-/// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
+/// `trait Set<K: Eq>`, then the trait bound `Foo: Set<Bar>` is WF
 /// if `Bar: Eq`.
 pub fn trait_obligations<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     body_id: LocalDefId,
-    trait_pred: &ty::TraitPredicate<'tcx>,
+    trait_pred: ty::TraitPredicate<'tcx>,
     span: Span,
     item: &'tcx hir::Item<'tcx>,
 ) -> Vec<traits::PredicateObligation<'tcx>> {
@@ -129,12 +129,17 @@ pub fn trait_obligations<'tcx>(
     wf.normalize(infcx)
 }
 
+/// Returns the requirements for `clause` to be well-formed.
+///
+/// For example, if there is a trait `Set` defined like
+/// `trait Set<K: Eq>`, then the trait bound `Foo: Set<Bar>` is WF
+/// if `Bar: Eq`.
 #[instrument(skip(infcx), ret)]
-pub fn predicate_obligations<'tcx>(
+pub fn clause_obligations<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     body_id: LocalDefId,
-    predicate: ty::Predicate<'tcx>,
+    clause: ty::Clause<'tcx>,
     span: Span,
 ) -> Vec<traits::PredicateObligation<'tcx>> {
     let mut wf = WfPredicates {
@@ -148,45 +153,32 @@ pub fn predicate_obligations<'tcx>(
     };
 
     // It's ok to skip the binder here because wf code is prepared for it
-    match predicate.kind().skip_binder() {
-        ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => {
-            wf.compute_trait_pred(&t, Elaborate::None);
+    match clause.kind().skip_binder() {
+        ty::ClauseKind::Trait(t) => {
+            wf.compute_trait_pred(t, Elaborate::None);
         }
-        ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {}
-        ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
-            ty,
-            _reg,
-        ))) => {
+        ty::ClauseKind::RegionOutlives(..) => {}
+        ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
             wf.compute(ty.into());
         }
-        ty::PredicateKind::Clause(ty::ClauseKind::Projection(t)) => {
+        ty::ClauseKind::Projection(t) => {
             wf.compute_projection(t.projection_ty);
             wf.compute(match t.term.unpack() {
                 ty::TermKind::Ty(ty) => ty.into(),
                 ty::TermKind::Const(c) => c.into(),
             })
         }
-        ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
+        ty::ClauseKind::ConstArgHasType(ct, ty) => {
             wf.compute(ct.into());
             wf.compute(ty.into());
         }
-        ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
+        ty::ClauseKind::WellFormed(arg) => {
             wf.compute(arg);
         }
 
-        ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
+        ty::ClauseKind::ConstEvaluatable(ct) => {
             wf.compute(ct.into());
         }
-
-        ty::PredicateKind::ObjectSafe(_)
-        | ty::PredicateKind::ClosureKind(..)
-        | ty::PredicateKind::Subtype(..)
-        | ty::PredicateKind::Coerce(..)
-        | ty::PredicateKind::ConstEquate(..)
-        | ty::PredicateKind::Ambiguous
-        | ty::PredicateKind::AliasRelate(..) => {
-            bug!("We should only wf check where clauses, unexpected predicate: {predicate:?}")
-        }
     }
 
     wf.normalize(infcx)
@@ -233,7 +225,7 @@ enum Elaborate {
 
 fn extend_cause_with_original_assoc_item_obligation<'tcx>(
     tcx: TyCtxt<'tcx>,
-    trait_ref: &ty::TraitRef<'tcx>,
+    trait_ref: ty::TraitRef<'tcx>,
     item: Option<&hir::Item<'tcx>>,
     cause: &mut traits::ObligationCause<'tcx>,
     pred: ty::Predicate<'tcx>,
@@ -336,9 +328,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
     }
 
     /// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
-    fn compute_trait_pred(&mut self, trait_pred: &ty::TraitPredicate<'tcx>, elaborate: Elaborate) {
+    fn compute_trait_pred(&mut self, trait_pred: ty::TraitPredicate<'tcx>, elaborate: Elaborate) {
         let tcx = self.tcx();
-        let trait_ref = &trait_pred.trait_ref;
+        let trait_ref = trait_pred.trait_ref;
 
         // Negative trait predicates don't require supertraits to hold, just
         // that their args are WF.
@@ -411,7 +403,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
     // Compute the obligations that are required for `trait_ref` to be WF,
     // given that it is a *negative* trait predicate.
-    fn compute_negative_trait_pred(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
+    fn compute_negative_trait_pred(&mut self, trait_ref: ty::TraitRef<'tcx>) {
         for arg in trait_ref.args {
             self.compute(arg);
         }
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 16183403d67..b118ddaab2b 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -528,7 +528,7 @@ fn fn_abi_adjust_for_abi<'tcx>(
                 arg.make_indirect();
             } else {
                 // We want to pass small aggregates as immediates, but using
-                // a LLVM aggregate type for this leads to bad optimizations,
+                // an LLVM aggregate type for this leads to bad optimizations,
                 // so we pick an appropriately sized integer type instead.
                 arg.cast_to(Reg { kind: RegKind::Integer, size });
             }
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 383cc996b9e..35487d3b698 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -71,7 +71,7 @@ pub(crate) fn destructure_const<'tcx>(
         _ => bug!("cannot destructure constant {:?}", const_),
     };
 
-    let fields = tcx.arena.alloc_from_iter(fields.into_iter());
+    let fields = tcx.arena.alloc_from_iter(fields);
 
     ty::DestructuredConst { variant, fields }
 }
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 5bd68d7ccaa..8132742d1df 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -85,7 +85,7 @@ fn univariant_uninterned<'tcx>(
     fields: &IndexSlice<FieldIdx, Layout<'_>>,
     repr: &ReprOptions,
     kind: StructKind,
-) -> Result<LayoutS, &'tcx LayoutError<'tcx>> {
+) -> Result<LayoutS<FieldIdx, VariantIdx>, &'tcx LayoutError<'tcx>> {
     let dl = cx.data_layout();
     let pack = repr.pack;
     if pack.is_some() && repr.align.is_some() {
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 4234e69e854..c22c67bd907 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -3,9 +3,8 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{
-    self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
-};
+use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt, TypeVisitor};
+use rustc_middle::ty::{ToPredicate, TypeSuperVisitable, TypeVisitable};
 use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
 use rustc_span::DUMMY_SP;
 use rustc_trait_selection::traits;
@@ -214,10 +213,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
             // strategy, then just reinterpret the associated type like an opaque :^)
             let default_ty = self.tcx.type_of(shifted_alias_ty.def_id).instantiate(self.tcx, shifted_alias_ty.args);
 
-            self.predicates.push(ty::Clause::from_projection_clause(self.tcx, ty::Binder::bind_with_vars(
+            self.predicates.push(ty::Binder::bind_with_vars(
                 ty::ProjectionPredicate { projection_ty: shifted_alias_ty, term: default_ty.into() },
                 self.bound_vars,
-            )));
+            ).to_predicate(self.tcx));
 
             // We walk the *un-shifted* alias ty, because we're tracking the de bruijn
             // binder depth, and if we were to walk `shifted_alias_ty` instead, we'd
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index 6f8f7b06fa3..72f026ee8de 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -5,7 +5,13 @@ use crate::{ty::Ty, Span};
 #[derive(Clone, Debug)]
 pub struct Body {
     pub blocks: Vec<BasicBlock>,
-    pub locals: Vec<Ty>,
+    pub locals: Vec<LocalDecl>,
+}
+
+#[derive(Clone, Debug)]
+pub struct LocalDecl {
+    pub ty: Ty,
+    pub span: Span,
 }
 
 #[derive(Clone, Debug)]
@@ -15,7 +21,13 @@ pub struct BasicBlock {
 }
 
 #[derive(Clone, Debug)]
-pub enum Terminator {
+pub struct Terminator {
+    pub kind: TerminatorKind,
+    pub span: Span,
+}
+
+#[derive(Clone, Debug)]
+pub enum TerminatorKind {
     Goto {
         target: usize,
     },
@@ -179,7 +191,13 @@ pub enum NonDivergingIntrinsic {
 }
 
 #[derive(Clone, Debug)]
-pub enum Statement {
+pub struct Statement {
+    pub kind: StatementKind,
+    pub span: Span,
+}
+
+#[derive(Clone, Debug)]
+pub enum StatementKind {
     Assign(Place, Rvalue),
     FakeRead(FakeReadCause, Place),
     SetDiscriminant { place: Place, variant_index: VariantIdx },
diff --git a/config.example.toml b/config.example.toml
index f3c2366d674..4f44121410e 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -19,11 +19,18 @@
 # Note that this has no default value (x.py uses the defaults in `config.example.toml`).
 #profile = <none>
 
-# Keeps track of the last version of `x.py` used.
-# If `changelog-seen` does not match the version that is currently running,
-# `x.py` will prompt you to update it and to read the changelog.
-# See `src/bootstrap/CHANGELOG.md` for more information.
-changelog-seen = 2
+# Keeps track of major changes made to this configuration.
+#
+# This value also represents ID of the PR that caused major changes. Meaning,
+# you can visit github.com/rust-lang/rust/pull/{change-id} to check for more details.
+#
+# A 'major change' includes any of the following
+#  - A new option
+#  - A change in the default values
+#
+# If `change-id` does not match the version that is currently running,
+# `x.py` will prompt you to update it and check the related PR for more details.
+change-id = 115898
 
 # =============================================================================
 # Tweaking how LLVM is compiled
diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs
index 84331eba2d4..b6b6246baa6 100644
--- a/library/alloc/src/borrow.rs
+++ b/library/alloc/src/borrow.rs
@@ -55,6 +55,7 @@ pub trait ToOwned {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "cloning is often expensive and is not expected to have side effects"]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "to_owned_method")]
     fn to_owned(&self) -> Self::Owned;
 
     /// Uses borrowed data to replace owned data, usually by cloning.
diff --git a/library/alloc/src/collections/btree/dedup_sorted_iter.rs b/library/alloc/src/collections/btree/dedup_sorted_iter.rs
index 17ee78045a9..cd6a88f3291 100644
--- a/library/alloc/src/collections/btree/dedup_sorted_iter.rs
+++ b/library/alloc/src/collections/btree/dedup_sorted_iter.rs
@@ -1,6 +1,6 @@
 use core::iter::Peekable;
 
-/// A iterator for deduping the key of a sorted iterator.
+/// An iterator for deduping the key of a sorted iterator.
 /// When encountering the duplicated key, only the last key-value pair is yielded.
 ///
 /// Used by [`BTreeMap::bulk_build_from_sorted_iter`][1].
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index f435f503fc1..cd3648214a4 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -140,6 +140,7 @@
 #![feature(maybe_uninit_uninit_array_transpose)]
 #![feature(pattern)]
 #![feature(pointer_byte_offsets)]
+#![feature(ptr_addr_eq)]
 #![feature(ptr_internals)]
 #![feature(ptr_metadata)]
 #![feature(ptr_sub_ptr)]
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 8dbaca223aa..73cb746c41d 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -1649,7 +1649,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
     /// assert!(!Rc::ptr_eq(&five, &other_five));
     /// ```
     pub fn ptr_eq(this: &Self, other: &Self) -> bool {
-        this.ptr.as_ptr() as *const () == other.ptr.as_ptr() as *const ()
+        ptr::addr_eq(this.ptr.as_ptr(), other.ptr.as_ptr())
     }
 }
 
@@ -2701,6 +2701,7 @@ impl<T, I: iter::TrustedLen<Item = T>> ToRcSlice<T> for I {
 ///
 /// [`upgrade`]: Weak::upgrade
 #[stable(feature = "rc_weak", since = "1.4.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "RcWeak")]
 pub struct Weak<
     T: ?Sized,
     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
@@ -3146,7 +3147,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
     #[must_use]
     #[stable(feature = "weak_ptr_eq", since = "1.39.0")]
     pub fn ptr_eq(&self, other: &Self) -> bool {
-        ptr::eq(self.ptr.as_ptr() as *const (), other.ptr.as_ptr() as *const ())
+        ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr())
     }
 }
 
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index ed43244ebda..e42bed7d264 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2435,6 +2435,7 @@ pub trait ToString {
     /// ```
     #[rustc_conversion_suggestion]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "to_string_method")]
     fn to_string(&self) -> String;
 }
 
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 61f4bfc54b0..0c6f3ef9b73 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -311,6 +311,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
 ///
 /// [`upgrade`]: Weak::upgrade
 #[stable(feature = "arc_weak", since = "1.4.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "ArcWeak")]
 pub struct Weak<
     T: ?Sized,
     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
@@ -1778,7 +1779,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
     #[must_use]
     #[stable(feature = "ptr_eq", since = "1.17.0")]
     pub fn ptr_eq(this: &Self, other: &Self) -> bool {
-        this.ptr.as_ptr() as *const () == other.ptr.as_ptr() as *const ()
+        ptr::addr_eq(this.ptr.as_ptr(), other.ptr.as_ptr())
     }
 }
 
@@ -2900,7 +2901,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
     #[must_use]
     #[stable(feature = "weak_ptr_eq", since = "1.39.0")]
     pub fn ptr_eq(&self, other: &Self) -> bool {
-        ptr::eq(self.ptr.as_ptr() as *const (), other.ptr.as_ptr() as *const ())
+        ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr())
     }
 }
 
diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs
index 587877dff55..8815cb21fc4 100644
--- a/library/core/src/array/iter.rs
+++ b/library/core/src/array/iter.rs
@@ -13,6 +13,7 @@ use crate::{
 /// A by-value [array] iterator.
 #[stable(feature = "array_value_iter", since = "1.51.0")]
 #[rustc_insignificant_dtor]
+#[rustc_diagnostic_item = "ArrayIntoIter"]
 pub struct IntoIter<T, const N: usize> {
     /// This is the array we are iterating over.
     ///
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 3b4d99221f2..db07ef7e3c9 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1423,6 +1423,7 @@ impl Clone for BorrowRef<'_> {
 /// See the [module-level documentation](self) for more.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[must_not_suspend = "holding a Ref across suspend points can cause BorrowErrors"]
+#[rustc_diagnostic_item = "RefCellRef"]
 pub struct Ref<'b, T: ?Sized + 'b> {
     // NB: we use a pointer instead of `&'b T` to avoid `noalias` violations, because a
     // `Ref` argument doesn't hold immutability for its whole scope, only until it drops.
@@ -1804,6 +1805,7 @@ impl<'b> BorrowRefMut<'b> {
 /// See the [module-level documentation](self) for more.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[must_not_suspend = "holding a RefMut across suspend points can cause BorrowErrors"]
+#[rustc_diagnostic_item = "RefCellRefMut"]
 pub struct RefMut<'b, T: ?Sized + 'b> {
     // NB: we use a pointer instead of `&'b mut T` to avoid `noalias` violations, because a
     // `RefMut` argument doesn't hold exclusivity for its whole scope, only until it drops.
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 36080616767..ca4e6be71ef 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -3,14 +3,17 @@
 //! This module contains various tools for comparing and ordering values. In
 //! summary:
 //!
-//! * [`Eq`] and [`PartialEq`] are traits that allow you to define total and
-//!   partial equality between values, respectively. Implementing them overloads
-//!   the `==` and `!=` operators.
+//! * [`PartialEq<Rhs>`] overloads the `==` and `!=` operators. In cases where
+//!   `Rhs` (the right hand side's type) is `Self`, this trait corresponds to a
+//!   partial equivalence relation.
+//! * [`Eq`] indicates that the overloaded `==` operator corresponds to an
+//!   equivalence relation.
 //! * [`Ord`] and [`PartialOrd`] are traits that allow you to define total and
 //!   partial orderings between values, respectively. Implementing them overloads
 //!   the `<`, `<=`, `>`, and `>=` operators.
 //! * [`Ordering`] is an enum returned by the main functions of [`Ord`] and
-//!   [`PartialOrd`], and describes an ordering.
+//!   [`PartialOrd`], and describes an ordering of two values (less, equal, or
+//!   greater).
 //! * [`Reverse`] is a struct that allows you to easily reverse an ordering.
 //! * [`max`] and [`min`] are functions that build off of [`Ord`] and allow you
 //!   to find the maximum or minimum of two values.
@@ -27,16 +30,21 @@ pub(crate) use bytewise::BytewiseEq;
 
 use self::Ordering::*;
 
-/// Trait for equality comparisons.
+/// Trait for comparisons using the equality operator.
+///
+/// Implementing this trait for types provides the `==` and `!=` operators for
+/// those types.
 ///
 /// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`.
 /// We use the easier-to-read infix notation in the remainder of this documentation.
 ///
-/// This trait allows for partial equality, for types that do not have a full
-/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
-/// so floating point types implement `PartialEq` but not [`trait@Eq`].
-/// Formally speaking, when `Rhs == Self`, this trait corresponds to a [partial equivalence
-/// relation](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
+/// This trait allows for comparisons using the equality operator, for types
+/// that do not have a full equivalence relation. For example, in floating point
+/// numbers `NaN != NaN`, so floating point types implement `PartialEq` but not
+/// [`trait@Eq`]. Formally speaking, when `Rhs == Self`, this trait corresponds
+/// to a [partial equivalence relation].
+///
+/// [partial equivalence relation]: https://en.wikipedia.org/wiki/Partial_equivalence_relation
 ///
 /// Implementations must ensure that `eq` and `ne` are consistent with each other:
 ///
@@ -242,15 +250,15 @@ pub macro PartialEq($item:item) {
     /* compiler built-in */
 }
 
-/// Trait for equality comparisons which are [equivalence relations](
+/// Trait for comparisons corresponding to [equivalence relations](
 /// https://en.wikipedia.org/wiki/Equivalence_relation).
 ///
-/// This means, that in addition to `a == b` and `a != b` being strict inverses, the equality must
-/// be (for all `a`, `b` and `c`):
+/// This means, that in addition to `a == b` and `a != b` being strict inverses,
+/// the relation must be (for all `a`, `b` and `c`):
 ///
 /// - reflexive: `a == a`;
-/// - symmetric: `a == b` implies `b == a`; and
-/// - transitive: `a == b` and `b == c` implies `a == c`.
+/// - symmetric: `a == b` implies `b == a` (required by `PartialEq` as well); and
+/// - transitive: `a == b` and `b == c` implies `a == c` (required by `PartialEq` as well).
 ///
 /// This property cannot be checked by the compiler, and therefore `Eq` implies
 /// [`PartialEq`], and has no extra methods.
@@ -260,6 +268,10 @@ pub macro PartialEq($item:item) {
 /// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
 /// methods.
 ///
+/// Implement `Eq` in addition to `PartialEq` if it's guaranteed that
+/// `PartialEq::eq(a, a)` always returns `true` (reflexivity), in addition to
+/// the symmetric and transitive properties already required by `PartialEq`.
+///
 /// ## Derivable
 ///
 /// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has
@@ -676,12 +688,19 @@ impl<T: Clone> Clone for Reverse<T> {
 ///
 /// ## Corollaries
 ///
-/// From the above and the requirements of `PartialOrd`, it follows that `<` defines a strict total order.
-/// This means that for all `a`, `b` and `c`:
+/// From the above and the requirements of `PartialOrd`, it follows that for
+/// all `a`, `b` and `c`:
 ///
 /// - exactly one of `a < b`, `a == b` or `a > b` is true; and
 /// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
 ///
+/// Mathematically speaking, the `<` operator defines a strict [weak order]. In
+/// cases where `==` conforms to mathematical equality, it also defines a
+/// strict [total order].
+///
+/// [weak order]: https://en.wikipedia.org/wiki/Weak_ordering
+/// [total order]: https://en.wikipedia.org/wiki/Total_order
+///
 /// ## Derivable
 ///
 /// This trait can be used with `#[derive]`.
@@ -790,6 +809,7 @@ pub trait Ord: Eq + PartialOrd<Self> {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_diagnostic_item = "ord_cmp_method"]
     fn cmp(&self, other: &Self) -> Ordering;
 
     /// Compares and returns the maximum of two values.
@@ -920,6 +940,20 @@ pub macro Ord($item:item) {
 /// - transitivity of `>`: if `a > b` and `b > c` then `a > c`
 /// - duality of `partial_cmp`: `partial_cmp(a, b) == partial_cmp(b, a).map(Ordering::reverse)`
 ///
+/// ## Strict and non-strict partial orders
+///
+/// The `<` and `>` operators behave according to a *strict* partial order.
+/// However, `<=` and `>=` do **not** behave according to a *non-strict*
+/// partial order.
+/// That is because mathematically, a non-strict partial order would require
+/// reflexivity, i.e. `a <= a` would need to be true for every `a`. This isn't
+/// always the case for types that implement `PartialOrd`, for example:
+///
+/// ```
+/// let a = f64::sqrt(-1.0);
+/// assert_eq!(a <= a, false);
+/// ```
+///
 /// ## Derivable
 ///
 /// This trait can be used with `#[derive]`.
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index ff5a4c913b7..9e4fdcda06e 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -100,6 +100,7 @@ pub use num::FloatToInt;
 #[stable(feature = "convert_id", since = "1.33.0")]
 #[rustc_const_stable(feature = "const_identity", since = "1.33.0")]
 #[inline(always)]
+#[rustc_diagnostic_item = "convert_identity"]
 pub const fn identity<T>(x: T) -> T {
     x
 }
@@ -642,6 +643,7 @@ pub trait TryFrom<T>: Sized {
 
     /// Performs the conversion.
     #[stable(feature = "try_from", since = "1.34.0")]
+    #[rustc_diagnostic_item = "try_from_fn"]
     fn try_from(value: T) -> Result<Self, Self::Error>;
 }
 
diff --git a/library/core/src/default.rs b/library/core/src/default.rs
index 5242e97eb9a..16618b38769 100644
--- a/library/core/src/default.rs
+++ b/library/core/src/default.rs
@@ -130,6 +130,7 @@ pub trait Default: Sized {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_diagnostic_item = "default_fn"]
     fn default() -> Self;
 }
 
diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs
index 9227248041e..47db53ac6f3 100644
--- a/library/core/src/fmt/builders.rs
+++ b/library/core/src/fmt/builders.rs
@@ -84,6 +84,7 @@ impl fmt::Write for PadAdapter<'_, '_> {
 #[must_use = "must eventually call `finish()` on Debug builders"]
 #[allow(missing_debug_implementations)]
 #[stable(feature = "debug_builders", since = "1.2.0")]
+#[rustc_diagnostic_item = "DebugStruct"]
 pub struct DebugStruct<'a, 'b: 'a> {
     fmt: &'a mut fmt::Formatter<'b>,
     result: fmt::Result,
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index fc91d1afc43..c45ab094a20 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -239,6 +239,7 @@ impl<W: Write + ?Sized> Write for &mut W {
 /// documentation of the methods defined on `Formatter` below.
 #[allow(missing_debug_implementations)]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "Formatter"]
 pub struct Formatter<'a> {
     flags: u32,
     fill: char,
@@ -791,8 +792,10 @@ pub trait Octal {
 /// assert_eq!(format!("l as binary is: {l:b}"), "l as binary is: 1101011");
 ///
 /// assert_eq!(
-///     format!("l as binary is: {l:#032b}"),
-///     "l as binary is: 0b000000000000000000000001101011"
+///     // Note that the `0b` prefix added by `#` is included in the total width, so we
+///     // need to add two to correctly display all 32 bits.
+///     format!("l as binary is: {l:#034b}"),
+///     "l as binary is: 0b00000000000000000000000001101011"
 /// );
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index d37888c27bd..5bf221b429f 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -133,6 +133,10 @@ impl<'a> Argument<'a> {
         Self::new(x, USIZE_MARKER)
     }
 
+    // FIXME: Transmuting formatter in new and indirectly branching to/calling
+    // it here is an explicit CFI violation.
+    #[allow(inline_no_sanitize)]
+    #[no_sanitize(cfi, kcfi)]
     #[inline(always)]
     pub(super) fn fmt(&self, f: &mut Formatter<'_>) -> Result {
         (self.formatter)(self.value, f)
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 4bf3da07354..ff177c70d39 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -277,7 +277,7 @@ pub fn spin_loop() {
 /// - Treats the call to `contains` and its result as volatile: the body of `benchmark` cannot
 ///   optimize this away
 ///
-/// This makes our benchmark much more realistic to how the function would be used in situ, where
+/// This makes our benchmark much more realistic to how the function would actually be used, where
 /// arguments are usually not known at compile time and the result is used in some way.
 #[inline]
 #[stable(feature = "bench_black_box", since = "1.66.0")]
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 4c76662ac09..e4d6c2c2928 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1509,12 +1509,14 @@ extern "rust-intrinsic" {
     ///
     /// This intrinsic does not have a stable counterpart.
     #[rustc_nounwind]
+    #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_load"]
     pub fn unaligned_volatile_load<T>(src: *const T) -> T;
     /// Performs a volatile store to the `dst` pointer.
     /// The pointer is not required to be aligned.
     ///
     /// This intrinsic does not have a stable counterpart.
     #[rustc_nounwind]
+    #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_store"]
     pub fn unaligned_volatile_store<T>(dst: *mut T, val: T);
 
     /// Returns the square root of an `f32`
@@ -2666,6 +2668,7 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
 #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
 #[inline(always)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_copy_nonoverlapping"]
 pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
     extern "rust-intrinsic" {
         #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
@@ -2761,6 +2764,7 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
 #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
 #[inline(always)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_copy"]
 pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
     extern "rust-intrinsic" {
         #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
@@ -2834,6 +2838,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
 #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
 #[inline(always)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_write_bytes"]
 pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
     extern "rust-intrinsic" {
         #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs
index 20aca323bab..65ba42920c9 100644
--- a/library/core/src/iter/adapters/peekable.rs
+++ b/library/core/src/iter/adapters/peekable.rs
@@ -12,6 +12,7 @@ use crate::ops::{ControlFlow, Try};
 #[derive(Clone, Debug)]
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "IterPeekable"]
 pub struct Peekable<I: Iterator> {
     iter: I,
     /// Remember a peeked value, even if it was None.
diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs
index 243df015f9a..438e046a4df 100644
--- a/library/core/src/iter/sources/empty.rs
+++ b/library/core/src/iter/sources/empty.rs
@@ -27,6 +27,7 @@ pub const fn empty<T>() -> Empty<T> {
 /// This `struct` is created by the [`empty()`] function. See its documentation for more.
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "iter_empty", since = "1.2.0")]
+#[rustc_diagnostic_item = "IterEmpty"]
 pub struct Empty<T>(marker::PhantomData<fn() -> T>);
 
 #[stable(feature = "core_impl_debug", since = "1.9.0")]
diff --git a/library/core/src/iter/sources/once.rs b/library/core/src/iter/sources/once.rs
index 6e9ed0d3c52..21be4377da1 100644
--- a/library/core/src/iter/sources/once.rs
+++ b/library/core/src/iter/sources/once.rs
@@ -61,6 +61,7 @@ pub fn once<T>(value: T) -> Once<T> {
 /// This `struct` is created by the [`once()`] function. See its documentation for more.
 #[derive(Clone, Debug)]
 #[stable(feature = "iter_once", since = "1.2.0")]
+#[rustc_diagnostic_item = "IterOnce"]
 pub struct Once<T> {
     inner: crate::option::IntoIter<T>,
 }
diff --git a/library/core/src/iter/sources/successors.rs b/library/core/src/iter/sources/successors.rs
index 6a6cbe905e4..7f7b2c77566 100644
--- a/library/core/src/iter/sources/successors.rs
+++ b/library/core/src/iter/sources/successors.rs
@@ -17,7 +17,7 @@ where
     F: FnMut(&T) -> Option<T>,
 {
     // If this function returned `impl Iterator<Item=T>`
-    // it could be based on `unfold` and not need a dedicated type.
+    // it could be based on `from_fn` and not need a dedicated type.
     // However having a named `Successors<T, F>` type allows it to be `Clone` when `T` and `F` are.
     Successors { next: first, succ }
 }
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index e0ef5071c40..0d1cf7941fb 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -146,6 +146,7 @@ pub trait FromIterator<A>: Sized {
     /// assert_eq!(v, vec![5, 5, 5, 5, 5]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_diagnostic_item = "from_iter_fn"]
     fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self;
 }
 
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index be734a9ba52..7fa7e83a744 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -238,6 +238,7 @@
 #![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(no_core)]
+#![feature(no_sanitize)]
 #![feature(platform_intrinsics)]
 #![feature(prelude_import)]
 #![feature(repr_simd)]
@@ -418,6 +419,7 @@ pub mod primitive;
 // FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is
 // merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet.
 #[allow(clashing_extern_declarations)]
+#[cfg_attr(bootstrap, allow(deprecated_in_future))]
 #[unstable(feature = "stdsimd", issue = "48556")]
 mod core_arch;
 
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index c27be8d2ffd..c367b53b720 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -719,7 +719,8 @@ macro_rules! unreachable {
 /// The difference between `unimplemented!` and [`todo!`] is that while `todo!`
 /// conveys an intent of implementing the functionality later and the message is "not yet
 /// implemented", `unimplemented!` makes no such claims. Its message is "not implemented".
-/// Also some IDEs will mark `todo!`s.
+///
+/// Also, some IDEs will mark `todo!`s.
 ///
 /// # Panics
 ///
@@ -805,11 +806,15 @@ macro_rules! unimplemented {
 /// The difference between [`unimplemented!`] and `todo!` is that while `todo!` conveys
 /// an intent of implementing the functionality later and the message is "not yet
 /// implemented", `unimplemented!` makes no such claims. Its message is "not implemented".
-/// Also some IDEs will mark `todo!`s.
+///
+/// Also, some IDEs will mark `todo!`s.
 ///
 /// # Panics
 ///
-/// This will always [`panic!`].
+/// This will always [`panic!`] because `todo!` is just a shorthand for `panic!` with a
+/// fixed, specific message.
+///
+/// Like `panic!`, this macro has a second form for displaying custom values.
 ///
 /// # Examples
 ///
@@ -817,38 +822,47 @@ macro_rules! unimplemented {
 ///
 /// ```
 /// trait Foo {
-///     fn bar(&self);
+///     fn bar(&self) -> u8;
 ///     fn baz(&self);
+///     fn qux(&self) -> Result<u64, ()>;
 /// }
 /// ```
 ///
 /// We want to implement `Foo` on one of our types, but we also want to work on
 /// just `bar()` first. In order for our code to compile, we need to implement
-/// `baz()`, so we can use `todo!`:
+/// `baz()` and `qux()`, so we can use `todo!`:
 ///
 /// ```
 /// # trait Foo {
-/// #     fn bar(&self);
+/// #     fn bar(&self) -> u8;
 /// #     fn baz(&self);
+/// #     fn qux(&self) -> Result<u64, ()>;
 /// # }
 /// struct MyStruct;
 ///
 /// impl Foo for MyStruct {
-///     fn bar(&self) {
-///         // implementation goes here
+///     fn bar(&self) -> u8 {
+///         1 + 1
 ///     }
 ///
 ///     fn baz(&self) {
-///         // let's not worry about implementing baz() for now
+///         // Let's not worry about implementing baz() for now
 ///         todo!();
 ///     }
+///
+///     fn qux(&self) -> Result<u64, ()> {
+///         // We can add a message to todo! to display our omission.
+///         // This will display:
+///         // "thread 'main' panicked at 'not yet implemented: MyStruct is not yet quxable'".
+///         todo!("MyStruct is not yet quxable");
+///     }
 /// }
 ///
 /// fn main() {
 ///     let s = MyStruct;
 ///     s.bar();
 ///
-///     // we aren't even using baz(), so this is fine.
+///     // We aren't even using baz() or qux(), so this is fine.
 /// }
 /// ```
 #[macro_export]
diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs
index 5f3d66e3773..98cff3493a7 100644
--- a/library/core/src/mem/manually_drop.rs
+++ b/library/core/src/mem/manually_drop.rs
@@ -4,12 +4,12 @@ use crate::ptr;
 /// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
 /// This wrapper is 0-cost.
 ///
-/// `ManuallyDrop<T>` is guaranteed to have the same layout as `T`, and is subject
-/// to the same layout optimizations as `T`. As a consequence, it has *no effect*
-/// on the assumptions that the compiler makes about its contents. For example,
-/// initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined
-/// behavior. If you need to handle uninitialized data, use [`MaybeUninit<T>`]
-/// instead.
+/// `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as
+/// `T`, and is subject to the same layout optimizations as `T`. As a consequence,
+/// it has *no effect* on the assumptions that the compiler makes about its
+/// contents. For example, initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`]
+/// is undefined behavior. If you need to handle uninitialized data, use
+/// [`MaybeUninit<T>`] instead.
 ///
 /// Note that accessing the value inside a `ManuallyDrop<T>` is safe.
 /// This means that a `ManuallyDrop<T>` whose content has been dropped must not
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index d7abc9a0e23..d1b1eb7624b 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -723,15 +723,12 @@ pub unsafe fn uninitialized<T>() -> T {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+#[rustc_diagnostic_item = "mem_swap"]
 pub const fn swap<T>(x: &mut T, y: &mut T) {
     // NOTE(eddyb) SPIR-V's Logical addressing model doesn't allow for arbitrary
     // reinterpretation of values as (chunkable) byte arrays, and the loop in the
     // block optimization in `swap_slice` is hard to rewrite back
     // into the (unoptimized) direct swapping implementation, so we disable it.
-    // FIXME(eddyb) the block optimization also prevents MIR optimizations from
-    // understanding `mem::replace`, `Option::take`, etc. - a better overall
-    // solution might be to make `ptr::swap_nonoverlapping` into an intrinsic, which
-    // a backend can choose to implement using the block optimization, or not.
     #[cfg(not(any(target_arch = "spirv")))]
     {
         // For types that are larger multiples of their alignment, the simple way
@@ -768,11 +765,14 @@ pub(crate) const fn swap_simple<T>(x: &mut T, y: &mut T) {
     // And LLVM actually optimizes it to 3×memcpy if called with
     // a type larger than it's willing to keep in a register.
     // Having typed reads and writes in MIR here is also good as
-    // it lets MIRI and CTFE understand them better, including things
+    // it lets Miri and CTFE understand them better, including things
     // like enforcing type validity for them.
     // Importantly, read+copy_nonoverlapping+write introduces confusing
     // asymmetry to the behaviour where one value went through read+write
     // whereas the other was copied over by the intrinsic (see #94371).
+    // Furthermore, using only read+write here benefits limited backends
+    // such as SPIR-V that work on an underlying *typed* view of memory,
+    // and thus have trouble with Rust's untyped memory operations.
 
     // SAFETY: exclusive references are always valid to read/write,
     // including being aligned, and nothing here panics so it's drop-safe.
@@ -930,7 +930,7 @@ pub const fn replace<T>(dest: &mut T, src: T) -> T {
 /// This function is not magic; it is literally defined as
 ///
 /// ```
-/// pub fn drop<T>(_x: T) { }
+/// pub fn drop<T>(_x: T) {}
 /// ```
 ///
 /// Because `_x` is moved into the function, it is automatically dropped before
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 290f649f9ac..f60626b00dc 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -377,6 +377,13 @@ impl f32 {
     pub const MANTISSA_DIGITS: u32 = 24;
 
     /// Approximate number of significant digits in base 10.
+    ///
+    /// This is the maximum <i>x</i> such that any decimal number with <i>x</i>
+    /// significant digits can be converted to `f32` and back without loss.
+    ///
+    /// Equal to floor(log<sub>10</sub>&nbsp;2<sup>[`MANTISSA_DIGITS`]&nbsp;&minus;&nbsp;1</sup>).
+    ///
+    /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const DIGITS: u32 = 6;
 
@@ -384,31 +391,62 @@ impl f32 {
     ///
     /// This is the difference between `1.0` and the next larger representable number.
     ///
+    /// Equal to 2<sup>1&nbsp;&minus;&nbsp;[`MANTISSA_DIGITS`]</sup>.
+    ///
     /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
+    /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const EPSILON: f32 = 1.19209290e-07_f32;
 
     /// Smallest finite `f32` value.
+    ///
+    /// Equal to &minus;[`MAX`].
+    ///
+    /// [`MAX`]: f32::MAX
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN: f32 = -3.40282347e+38_f32;
     /// Smallest positive normal `f32` value.
+    ///
+    /// Equal to 2<sup>[`MIN_EXP`]&nbsp;&minus;&nbsp;1</sup>.
+    ///
+    /// [`MIN_EXP`]: f32::MIN_EXP
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_POSITIVE: f32 = 1.17549435e-38_f32;
     /// Largest finite `f32` value.
+    ///
+    /// Equal to
+    /// (1&nbsp;&minus;&nbsp;2<sup>&minus;[`MANTISSA_DIGITS`]</sup>)&nbsp;2<sup>[`MAX_EXP`]</sup>.
+    ///
+    /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS
+    /// [`MAX_EXP`]: f32::MAX_EXP
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX: f32 = 3.40282347e+38_f32;
 
     /// One greater than the minimum possible normal power of 2 exponent.
+    ///
+    /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
+    /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_EXP: i32 = -125;
     /// Maximum possible power of 2 exponent.
+    ///
+    /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
+    /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX_EXP: i32 = 128;
 
-    /// Minimum possible normal power of 10 exponent.
+    /// Minimum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
+    ///
+    /// Equal to ceil(log<sub>10</sub>&nbsp;[`MIN_POSITIVE`]).
+    ///
+    /// [`MIN_POSITIVE`]: f32::MIN_POSITIVE
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_10_EXP: i32 = -37;
-    /// Maximum possible power of 10 exponent.
+    /// Maximum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
+    ///
+    /// Equal to floor(log<sub>10</sub>&nbsp;[`MAX`]).
+    ///
+    /// [`MAX`]: f32::MAX
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX_10_EXP: i32 = 38;
 
@@ -820,7 +858,7 @@ impl f32 {
     /// let angle = std::f32::consts::PI;
     ///
     /// let abs_difference = (angle.to_degrees() - 180.0).abs();
-    ///
+    /// # #[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))]
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
     #[must_use = "this returns the result of the operation, \
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 7569d2cd6ca..0a87021d8c1 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -376,6 +376,13 @@ impl f64 {
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MANTISSA_DIGITS: u32 = 53;
     /// Approximate number of significant digits in base 10.
+    ///
+    /// This is the maximum <i>x</i> such that any decimal number with <i>x</i>
+    /// significant digits can be converted to `f64` and back without loss.
+    ///
+    /// Equal to floor(log<sub>10</sub>&nbsp;2<sup>[`MANTISSA_DIGITS`]&nbsp;&minus;&nbsp;1</sup>).
+    ///
+    /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const DIGITS: u32 = 15;
 
@@ -383,31 +390,62 @@ impl f64 {
     ///
     /// This is the difference between `1.0` and the next larger representable number.
     ///
+    /// Equal to 2<sup>1&nbsp;&minus;&nbsp;[`MANTISSA_DIGITS`]</sup>.
+    ///
     /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
+    /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
 
     /// Smallest finite `f64` value.
+    ///
+    /// Equal to &minus;[`MAX`].
+    ///
+    /// [`MAX`]: f64::MAX
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN: f64 = -1.7976931348623157e+308_f64;
     /// Smallest positive normal `f64` value.
+    ///
+    /// Equal to 2<sup>[`MIN_EXP`]&nbsp;&minus;&nbsp;1</sup>.
+    ///
+    /// [`MIN_EXP`]: f64::MIN_EXP
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_POSITIVE: f64 = 2.2250738585072014e-308_f64;
     /// Largest finite `f64` value.
+    ///
+    /// Equal to
+    /// (1&nbsp;&minus;&nbsp;2<sup>&minus;[`MANTISSA_DIGITS`]</sup>)&nbsp;2<sup>[`MAX_EXP`]</sup>.
+    ///
+    /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS
+    /// [`MAX_EXP`]: f64::MAX_EXP
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX: f64 = 1.7976931348623157e+308_f64;
 
     /// One greater than the minimum possible normal power of 2 exponent.
+    ///
+    /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
+    /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_EXP: i32 = -1021;
     /// Maximum possible power of 2 exponent.
+    ///
+    /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
+    /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX_EXP: i32 = 1024;
 
-    /// Minimum possible normal power of 10 exponent.
+    /// Minimum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
+    ///
+    /// Equal to ceil(log<sub>10</sub>&nbsp;[`MIN_POSITIVE`]).
+    ///
+    /// [`MIN_POSITIVE`]: f64::MIN_POSITIVE
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MIN_10_EXP: i32 = -307;
-    /// Maximum possible power of 10 exponent.
+    /// Maximum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
+    ///
+    /// Equal to floor(log<sub>10</sub>&nbsp;[`MAX`]).
+    ///
+    /// [`MAX`]: f64::MAX
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const MAX_10_EXP: i32 = 308;
 
diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs
index 911761c6edd..d6f2f5ca366 100644
--- a/library/core/src/ops/deref.rs
+++ b/library/core/src/ops/deref.rs
@@ -180,6 +180,7 @@ impl<T: ?Sized> Deref for &mut T {
 pub trait DerefMut: Deref {
     /// Mutably dereferences the value.
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_diagnostic_item = "deref_mut_method"]
     fn deref_mut(&mut self) -> &mut Self::Target;
 }
 
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index cc596293ca3..b4160095887 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -758,6 +758,7 @@ impl<T: Clone> Bound<&T> {
 /// `RangeBounds` is implemented by Rust's built-in range types, produced
 /// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
 #[stable(feature = "collections_range", since = "1.28.0")]
+#[rustc_diagnostic_item = "RangeBounds"]
 pub trait RangeBounds<T: ?Sized> {
     /// Start index bound.
     ///
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index f2909a81d49..9899014e85a 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -743,8 +743,6 @@ impl<T> Option<T> {
     /// # Examples
     ///
     /// ```rust
-    /// #![feature(option_as_slice)]
-    ///
     /// assert_eq!(
     ///     [Some(1234).as_slice(), None.as_slice()],
     ///     [&[1234][..], &[][..]],
@@ -755,15 +753,13 @@ impl<T> Option<T> {
     /// borrowing) [`[_]::first`](slice::first):
     ///
     /// ```rust
-    /// #![feature(option_as_slice)]
-    ///
     /// for i in [Some(1234_u16), None] {
     ///     assert_eq!(i.as_ref(), i.as_slice().first());
     /// }
     /// ```
     #[inline]
     #[must_use]
-    #[unstable(feature = "option_as_slice", issue = "108545")]
+    #[stable(feature = "option_as_slice", since = "CURRENT_RUSTC_VERSION")]
     pub fn as_slice(&self) -> &[T] {
         // SAFETY: When the `Option` is `Some`, we're using the actual pointer
         // to the payload, with a length of 1, so this is equivalent to
@@ -794,8 +790,6 @@ impl<T> Option<T> {
     /// # Examples
     ///
     /// ```rust
-    /// #![feature(option_as_slice)]
-    ///
     /// assert_eq!(
     ///     [Some(1234).as_mut_slice(), None.as_mut_slice()],
     ///     [&mut [1234][..], &mut [][..]],
@@ -806,8 +800,6 @@ impl<T> Option<T> {
     /// our original `Option`:
     ///
     /// ```rust
-    /// #![feature(option_as_slice)]
-    ///
     /// let mut x = Some(1234);
     /// x.as_mut_slice()[0] += 1;
     /// assert_eq!(x, Some(1235));
@@ -817,13 +809,11 @@ impl<T> Option<T> {
     /// is [`[_]::first_mut`](slice::first_mut):
     ///
     /// ```rust
-    /// #![feature(option_as_slice)]
-    ///
     /// assert_eq!(Some(123).as_mut_slice().first_mut(), Some(&mut 123))
     /// ```
     #[inline]
     #[must_use]
-    #[unstable(feature = "option_as_slice", issue = "108545")]
+    #[stable(feature = "option_as_slice", since = "CURRENT_RUSTC_VERSION")]
     pub fn as_mut_slice(&mut self) -> &mut [T] {
         // SAFETY: When the `Option` is `Some`, we're using the actual pointer
         // to the payload, with a length of 1, so this is equivalent to
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index 386f5fcbd6a..a00fd322b3c 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -47,6 +47,7 @@ pub macro panic_2015 {
 #[allow_internal_unstable(core_panic, const_format_args)]
 #[rustc_diagnostic_item = "core_panic_2021_macro"]
 #[rustc_macro_transparency = "semitransparent"]
+#[cfg(any(bootstrap, feature = "panic_immediate_abort"))]
 pub macro panic_2021 {
     () => (
         $crate::panicking::panic("explicit panic")
@@ -63,6 +64,50 @@ pub macro panic_2021 {
 }
 
 #[doc(hidden)]
+#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
+#[allow_internal_unstable(
+    core_panic,
+    core_intrinsics,
+    const_dispatch,
+    const_eval_select,
+    const_format_args,
+    rustc_attrs
+)]
+#[rustc_diagnostic_item = "core_panic_2021_macro"]
+#[rustc_macro_transparency = "semitransparent"]
+#[cfg(not(any(bootstrap, feature = "panic_immediate_abort")))]
+pub macro panic_2021 {
+    () => ({
+        // Create a function so that the argument for `track_caller`
+        // can be moved inside if possible.
+        #[cold]
+        #[track_caller]
+        #[inline(never)]
+        const fn panic_cold_explicit() -> ! {
+            $crate::panicking::panic_explicit()
+        }
+        panic_cold_explicit();
+    }),
+    // Special-case the single-argument case for const_panic.
+    ("{}", $arg:expr $(,)?) => ({
+        #[cold]
+        #[track_caller]
+        #[inline(never)]
+        #[rustc_const_panic_str] // enforce a &&str argument in const-check and hook this by const-eval
+        #[rustc_do_not_const_check] // hooked by const-eval
+        const fn panic_cold_display<T: $crate::fmt::Display>(arg: &T) -> ! {
+            $crate::panicking::panic_display(arg)
+        }
+        panic_cold_display(&$arg);
+    }),
+    ($($t:tt)+) => ({
+        // Semicolon to prevent temporaries inside the formatting machinery from
+        // being considered alive in the caller after the panic_fmt call.
+        $crate::panicking::panic_fmt($crate::const_format_args!($($t)+));
+    }),
+}
+
+#[doc(hidden)]
 #[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")]
 #[allow_internal_unstable(core_panic)]
 #[rustc_diagnostic_item = "unreachable_2015_macro"]
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index e6cdffd96af..1a32cf92ffb 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -152,6 +152,14 @@ pub const fn panic_str(expr: &str) -> ! {
     panic_display(&expr);
 }
 
+#[track_caller]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[rustc_const_unstable(feature = "core_panic", issue = "none")]
+pub const fn panic_explicit() -> ! {
+    panic_display(&"explicit panic");
+}
+
 #[inline]
 #[track_caller]
 #[rustc_diagnostic_item = "unreachable_display"] // needed for `non-fmt-panics` lint
@@ -161,8 +169,10 @@ pub fn unreachable_display<T: fmt::Display>(x: &T) -> ! {
 
 #[inline]
 #[track_caller]
-#[lang = "panic_display"] // needed for const-evaluated panics
 #[rustc_do_not_const_check] // hooked by const-eval
+#[cfg_attr(bootstrap, lang = "panic_display")]
+// enforce a &&str argument in const-check and hook this by const-eval
+#[cfg_attr(not(bootstrap), rustc_const_panic_str)]
 #[rustc_const_unstable(feature = "core_panic", issue = "none")]
 pub const fn panic_display<T: fmt::Display>(x: &T) -> ! {
     panic_fmt(format_args!("{}", *x));
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index fd5fe5a04f4..380a21b376b 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1142,10 +1142,9 @@ impl<T: Copy> Copy for (T,) {
 ///     surprising results upon inspecting the bit patterns,
 ///     as the same calculations might produce NaNs with different bit patterns.
 ///
-/// When the number resulting from a primitive operation (addition,
-/// subtraction, multiplication, or division) on this type is not exactly
-/// representable as `f32`, it is rounded according to the roundTiesToEven
-/// direction defined in IEEE 754-2008. That means:
+/// When a primitive operation (addition, subtraction, multiplication, or
+/// division) is performed on this type, the result is rounded according to the
+/// roundTiesToEven direction defined in IEEE 754-2008. That means:
 ///
 /// - The result is the representable value closest to the true value, if there
 ///   is a unique closest representable value.
@@ -1154,6 +1153,9 @@ impl<T: Copy> Copy for (T,) {
 /// - If the true value's magnitude is ≥ `f32::MAX` + 2<sup>(`f32::MAX_EXP` −
 ///   `f32::MANTISSA_DIGITS` − 1)</sup>, the result is ∞ or −∞ (preserving the
 ///   true value's sign).
+/// - If the result of a sum exactly equals zero, the outcome is +0.0 unless
+///   both arguments were negative, then it is -0.0. Subtraction `a - b` is
+///   regarded as a sum `a + (-b)`.
 ///
 /// For more information on floating point numbers, see [Wikipedia][wikipedia].
 ///
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index d1286a1dea7..5039ff53d03 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -494,6 +494,7 @@ mod mut_ptr;
 #[stable(feature = "drop_in_place", since = "1.8.0")]
 #[lang = "drop_in_place"]
 #[allow(unconditional_recursion)]
+#[rustc_diagnostic_item = "ptr_drop_in_place"]
 pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     // Code here does not matter - this is replaced by the
     // real drop glue by the compiler.
@@ -740,6 +741,7 @@ pub const fn from_mut<T: ?Sized>(r: &mut T) -> *mut T {
 #[stable(feature = "slice_from_raw_parts", since = "1.42.0")]
 #[rustc_const_stable(feature = "const_slice_from_raw_parts", since = "1.64.0")]
 #[rustc_allow_const_fn_unstable(ptr_metadata)]
+#[rustc_diagnostic_item = "ptr_slice_from_raw_parts"]
 pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
     from_raw_parts(data.cast(), len)
 }
@@ -772,6 +774,7 @@ pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
 #[inline]
 #[stable(feature = "slice_from_raw_parts", since = "1.42.0")]
 #[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")]
+#[rustc_diagnostic_item = "ptr_slice_from_raw_parts_mut"]
 pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
     from_raw_parts_mut(data.cast(), len)
 }
@@ -850,6 +853,7 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+#[rustc_diagnostic_item = "ptr_swap"]
 pub const unsafe fn swap<T>(x: *mut T, y: *mut T) {
     // Give ourselves some scratch space to work with.
     // We do not have to worry about drops: `MaybeUninit` does nothing when dropped.
@@ -911,6 +915,7 @@ pub const unsafe fn swap<T>(x: *mut T, y: *mut T) {
 #[inline]
 #[stable(feature = "swap_nonoverlapping", since = "1.27.0")]
 #[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+#[rustc_diagnostic_item = "ptr_swap_nonoverlapping"]
 pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
     #[allow(unused)]
     macro_rules! attempt_swap_as_chunks {
@@ -1022,6 +1027,7 @@ const unsafe fn swap_nonoverlapping_simple_untyped<T>(x: *mut T, y: *mut T, coun
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_replace", issue = "83164")]
+#[rustc_diagnostic_item = "ptr_replace"]
 pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
     // SAFETY: the caller must guarantee that `dst` is valid to be
     // cast to a mutable reference (valid for writes, aligned, initialized),
@@ -1147,6 +1153,7 @@ pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
 #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
 #[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_read"]
 pub const unsafe fn read<T>(src: *const T) -> T {
     // It would be semantically correct to implement this via `copy_nonoverlapping`
     // and `MaybeUninit`, as was done before PR #109035. Calling `assume_init`
@@ -1264,6 +1271,7 @@ pub const unsafe fn read<T>(src: *const T) -> T {
 #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
 #[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_read_unaligned"]
 pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
     let mut tmp = MaybeUninit::<T>::uninit();
     // SAFETY: the caller must guarantee that `src` is valid for reads.
@@ -1539,6 +1547,7 @@ pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
 #[inline]
 #[stable(feature = "volatile", since = "1.9.0")]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_read_volatile"]
 pub unsafe fn read_volatile<T>(src: *const T) -> T {
     // SAFETY: the caller must uphold the safety contract for `volatile_load`.
     unsafe {
@@ -1864,10 +1873,35 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz
 /// ```
 #[stable(feature = "ptr_eq", since = "1.17.0")]
 #[inline(always)]
+#[must_use = "pointer comparison produces a value"]
+#[rustc_diagnostic_item = "ptr_eq"]
 pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
     a == b
 }
 
+/// Compares the *addresses* of the two pointers for equality,
+/// ignoring any metadata in fat pointers.
+///
+/// If the arguments are thin pointers of the same type,
+/// then this is the same as [`eq`].
+///
+/// # Examples
+///
+/// ```
+/// #![feature(ptr_addr_eq)]
+///
+/// let whole: &[i32; 3] = &[1, 2, 3];
+/// let first: &i32 = &whole[0];
+/// assert!(std::ptr::addr_eq(whole, first));
+/// assert!(!std::ptr::eq::<dyn std::fmt::Debug>(whole, first));
+/// ```
+#[unstable(feature = "ptr_addr_eq", issue = "116324")]
+#[inline(always)]
+#[must_use = "pointer comparison produces a value"]
+pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool {
+    (p as *const ()) == (q as *const ())
+}
+
 /// Hash a raw pointer.
 ///
 /// This can be used to hash a `&T` reference (which coerces to `*const T` implicitly)
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index d5bd54fd59a..5f5a10bbdf3 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -68,6 +68,7 @@ use crate::slice::{self, SliceIndex};
 #[repr(transparent)]
 #[rustc_layout_scalar_valid_range_start(1)]
 #[rustc_nonnull_optimization_guaranteed]
+#[rustc_diagnostic_item = "NonNull"]
 pub struct NonNull<T: ?Sized> {
     pointer: *const T,
 }
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 6981abc9be1..50127b27f8b 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1422,6 +1422,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(Err("foo").unwrap_or_else(count), 3);
     /// ```
     #[inline]
+    #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap_or_else<F: FnOnce(E) -> T>(self, op: F) -> T {
         match self {
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index cc931355318..5e229bf5244 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -59,6 +59,7 @@ impl<'a, T> IntoIterator for &'a mut [T] {
 /// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
 #[must_use = "iterators are lazy and do nothing unless consumed"]
+#[rustc_diagnostic_item = "SliceIter"]
 pub struct Iter<'a, T: 'a> {
     /// The pointer to the next element to return, or the past-the-end location
     /// if the iterator is empty.
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
index 48a6eb03b5e..9cdf9b68afb 100644
--- a/library/core/src/slice/raw.rs
+++ b/library/core/src/slice/raw.rs
@@ -90,6 +90,7 @@ use crate::ptr;
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "const_slice_from_raw_parts", since = "1.64.0")]
 #[must_use]
+#[rustc_diagnostic_item = "slice_from_raw_parts"]
 pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
     // SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
     unsafe {
@@ -136,6 +137,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")]
 #[must_use]
+#[rustc_diagnostic_item = "slice_from_raw_parts_mut"]
 pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
     // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
     unsafe {
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index eb0c424e2d2..899d572f0e3 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -808,7 +808,7 @@ impl str {
     /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆')
     /// assert_eq!(Some((1, '\u{0306}')), char_indices.next());
     ///
-    /// // note the 3 here - the last character took up two bytes
+    /// // note the 3 here - the previous character took up two bytes
     /// assert_eq!(Some((3, 'e')), char_indices.next());
     /// assert_eq!(Some((4, 's')), char_indices.next());
     ///
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index 2b37af66bd6..16fb1dad723 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -624,6 +624,7 @@ pub trait FromStr: Sized {
     /// assert_eq!(5, x);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_diagnostic_item = "from_str_method"]
     fn from_str(s: &str) -> Result<Self, Self::Err>;
 }
 
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 1e8d28979e6..6ef35d8414b 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -910,6 +910,7 @@ impl Duration {
 impl Add for Duration {
     type Output = Duration;
 
+    #[inline]
     fn add(self, rhs: Duration) -> Duration {
         self.checked_add(rhs).expect("overflow when adding durations")
     }
@@ -917,6 +918,7 @@ impl Add for Duration {
 
 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
 impl AddAssign for Duration {
+    #[inline]
     fn add_assign(&mut self, rhs: Duration) {
         *self = *self + rhs;
     }
@@ -926,6 +928,7 @@ impl AddAssign for Duration {
 impl Sub for Duration {
     type Output = Duration;
 
+    #[inline]
     fn sub(self, rhs: Duration) -> Duration {
         self.checked_sub(rhs).expect("overflow when subtracting durations")
     }
@@ -933,6 +936,7 @@ impl Sub for Duration {
 
 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
 impl SubAssign for Duration {
+    #[inline]
     fn sub_assign(&mut self, rhs: Duration) {
         *self = *self - rhs;
     }
@@ -942,6 +946,7 @@ impl SubAssign for Duration {
 impl Mul<u32> for Duration {
     type Output = Duration;
 
+    #[inline]
     fn mul(self, rhs: u32) -> Duration {
         self.checked_mul(rhs).expect("overflow when multiplying duration by scalar")
     }
@@ -951,6 +956,7 @@ impl Mul<u32> for Duration {
 impl Mul<Duration> for u32 {
     type Output = Duration;
 
+    #[inline]
     fn mul(self, rhs: Duration) -> Duration {
         rhs * self
     }
@@ -958,6 +964,7 @@ impl Mul<Duration> for u32 {
 
 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
 impl MulAssign<u32> for Duration {
+    #[inline]
     fn mul_assign(&mut self, rhs: u32) {
         *self = *self * rhs;
     }
@@ -967,6 +974,7 @@ impl MulAssign<u32> for Duration {
 impl Div<u32> for Duration {
     type Output = Duration;
 
+    #[inline]
     fn div(self, rhs: u32) -> Duration {
         self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar")
     }
@@ -974,6 +982,7 @@ impl Div<u32> for Duration {
 
 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
 impl DivAssign<u32> for Duration {
+    #[inline]
     fn div_assign(&mut self, rhs: u32) {
         *self = *self / rhs;
     }
diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
index 982d7853f69..81da75d32a1 100644
--- a/library/core/tests/array.rs
+++ b/library/core/tests/array.rs
@@ -663,7 +663,7 @@ fn array_mixed_equality_nans() {
 
 #[test]
 fn array_into_iter_fold() {
-    // Strings to help MIRI catch if we double-free or something
+    // Strings to help Miri catch if we double-free or something
     let a = ["Aa".to_string(), "Bb".to_string(), "Cc".to_string()];
     let mut s = "s".to_string();
     a.into_iter().for_each(|b| s += &b);
@@ -679,7 +679,7 @@ fn array_into_iter_fold() {
 
 #[test]
 fn array_into_iter_rfold() {
-    // Strings to help MIRI catch if we double-free or something
+    // Strings to help Miri catch if we double-free or something
     let a = ["Aa".to_string(), "Bb".to_string(), "Cc".to_string()];
     let mut s = "s".to_string();
     a.into_iter().rev().for_each(|b| s += &b);
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 73cce35ac59..c44223a2f32 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -184,6 +184,7 @@ pub struct DirEntry(fs_imp::DirEntry);
 /// ```
 #[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "FsOpenOptions")]
 pub struct OpenOptions(fs_imp::OpenOptions);
 
 /// Representation of the various timestamps on a file.
@@ -201,6 +202,7 @@ pub struct FileTimes(fs_imp::FileTimes);
 /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt
 #[derive(Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "FsPermissions")]
 pub struct Permissions(fs_imp::FilePermissions);
 
 /// A structure representing a type of file with accessors for each file type.
@@ -2241,6 +2243,7 @@ pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
 /// ```
 #[doc(alias = "mkdir")]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "fs_create_dir")]
 pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
     DirBuilder::new().create(path.as_ref())
 }
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 604b795cd52..c93bf020252 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1830,6 +1830,7 @@ pub trait Write {
 /// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "IoSeek")]
 pub trait Seek {
     /// Seek to an offset, in bytes, in a stream.
     ///
@@ -2893,6 +2894,7 @@ impl<B: BufRead> Iterator for Split<B> {
 /// [`lines`]: BufRead::lines
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "IoLines")]
 pub struct Lines<B> {
     buf: B,
 }
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 9098d36ee53..05b21eeb40f 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -611,6 +611,7 @@ static STDOUT: OnceLock<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = OnceLo
 /// ```
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "io_stdout")]
 pub fn stdout() -> Stdout {
     Stdout {
         inner: STDOUT
@@ -847,6 +848,7 @@ pub struct StderrLock<'a> {
 /// ```
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "io_stderr")]
 pub fn stderr() -> Stderr {
     // Note that unlike `stdout()` we don't use `at_exit` here to register a
     // destructor. Stderr is not buffered, so there's no need to run a
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index f1f0f8b1653..02f4d5bc7ae 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -259,7 +259,7 @@
     all(target_vendor = "fortanix", target_env = "sgx"),
     feature(slice_index_methods, coerce_unsized, sgx_platform)
 )]
-#![cfg_attr(windows, feature(round_char_boundary))]
+#![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))]
 #![cfg_attr(target_os = "xous", feature(slice_ptr_len))]
 //
 // Language features:
@@ -270,6 +270,7 @@
 #![feature(allow_internal_unstable)]
 #![feature(c_unwind)]
 #![feature(cfg_target_thread_local)]
+#![feature(cfi_encoding)]
 #![feature(concat_idents)]
 #![feature(const_mut_refs)]
 #![feature(const_trait_impl)]
@@ -292,6 +293,7 @@
 #![feature(needs_panic_runtime)]
 #![feature(negative_impls)]
 #![feature(never_type)]
+#![feature(no_sanitize)]
 #![feature(platform_intrinsics)]
 #![feature(prelude_import)]
 #![feature(rustc_attrs)]
diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs
index 227e418b709..60347a11da9 100644
--- a/library/std/src/net/udp.rs
+++ b/library/std/src/net/udp.rs
@@ -99,6 +99,16 @@ impl UdpSocket {
     ///
     /// let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
     /// ```
+    ///
+    /// Note that `bind` declares the scope of your network connection.
+    /// You can only receive datagrams from and send datagrams to
+    /// participants in that view of the network.
+    /// For instance, binding to a loopback address as in the example
+    /// above will prevent you from sending datagrams to another device
+    /// in your local network.
+    ///
+    /// In order to limit your view of the network the least, `bind` to
+    /// [`Ipv4Addr::UNSPECIFIED`] or [`Ipv6Addr::UNSPECIFIED`].
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
         super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket)
@@ -157,7 +167,9 @@ impl UdpSocket {
     }
 
     /// Sends data on the socket to the given address. On success, returns the
-    /// number of bytes written.
+    /// number of bytes written. Note that the operating system may refuse
+    /// buffers larger than 65507. However, partial writes are not possible
+    /// until buffer sizes above `i32::MAX`.
     ///
     /// Address type can be any implementor of [`ToSocketAddrs`] trait. See its
     /// documentation for concrete examples.
@@ -652,12 +664,19 @@ impl UdpSocket {
     /// function of a UDP socket is not a useful thing to do: The OS will be
     /// unable to determine whether something is listening on the remote
     /// address without the application sending data.
+    ///
+    /// If your first `connect` is to a loopback address, subsequent
+    /// `connect`s to non-loopback addresses might fail, depending
+    /// on the platform.
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
         super::each_addr(addr, |addr| self.0.connect(addr))
     }
 
     /// Sends data on the socket to the remote address to which it is connected.
+    /// On success, returns the number of bytes written. Note that the operating
+    /// system may refuse buffers larger than 65507. However, partial writes are
+    /// not possible until buffer sizes above `i32::MAX`.
     ///
     /// [`UdpSocket::connect`] will connect this socket to a remote address. This
     /// method will fail if the socket is not connected.
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 6cf3bd619b2..e148635f581 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -526,6 +526,7 @@ impl fmt::Debug for ChildStderr {
 /// list_dir.status().expect("process failed to execute");
 /// ```
 #[stable(feature = "process", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Command")]
 pub struct Command {
     inner: imp::Command,
 }
@@ -607,7 +608,7 @@ impl Command {
     ///
     /// Note that the argument is not passed through a shell, but given
     /// literally to the program. This means that shell syntax like quotes,
-    /// escaped characters, word splitting, glob patterns, substitution, etc.
+    /// escaped characters, word splitting, glob patterns, variable substitution, etc.
     /// have no effect.
     ///
     /// # Examples
@@ -637,7 +638,7 @@ impl Command {
     ///
     /// Note that the arguments are not passed through a shell, but given
     /// literally to the program. This means that shell syntax like quotes,
-    /// escaped characters, word splitting, glob patterns, substitution, etc.
+    /// escaped characters, word splitting, glob patterns, variable substitution, etc.
     /// have no effect.
     ///
     /// # Examples
@@ -2196,6 +2197,7 @@ impl Child {
 /// process::exit(0x0100);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "process_exit")]
 pub fn exit(code: i32) -> ! {
     crate::rt::cleanup();
     crate::sys::os::exit(code)
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs
index 26aaa2414c9..ac7c800ff6f 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/rwlock.rs
@@ -380,7 +380,7 @@ impl<T: ?Sized> RwLock<T> {
     ///
     /// If the lock is poisoned, it will remain poisoned until this function is called. This allows
     /// recovering from a poisoned state and marking that it has recovered. For example, if the
-    /// value is overwritten by a known-good value, then the mutex can be marked as un-poisoned. Or
+    /// value is overwritten by a known-good value, then the lock can be marked as un-poisoned. Or
     /// possibly, the value could be inspected to determine if it is in a consistent state, and if
     /// so the poison is removed.
     ///
@@ -397,7 +397,7 @@ impl<T: ?Sized> RwLock<T> {
     ///
     /// let _ = thread::spawn(move || {
     ///     let _lock = c_lock.write().unwrap();
-    ///     panic!(); // the mutex gets poisoned
+    ///     panic!(); // the lock gets poisoned
     /// }).join();
     ///
     /// assert_eq!(lock.is_poisoned(), true);
diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs
index e477a0cd7ab..559d2c7db47 100644
--- a/library/std/src/sys/personality/gcc.rs
+++ b/library/std/src/sys/personality/gcc.rs
@@ -95,7 +95,7 @@ const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1
 cfg_if::cfg_if! {
     if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "tvos"), not(target_os = "watchos"), not(target_os = "netbsd")))] {
         // ARM EHABI personality routine.
-        // https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
+        // https://web.archive.org/web/20190728160938/https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
         //
         // iOS uses the default routine instead since it uses SjLj unwinding.
         #[lang = "eh_personality"]
diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs
index 01505e94487..817c33b6603 100644
--- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs
+++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs
@@ -3,6 +3,8 @@
 use crate::arch::asm;
 use crate::cell::UnsafeCell;
 use crate::cmp;
+use crate::convert::TryInto;
+use crate::intrinsics;
 use crate::mem;
 use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut};
 use crate::ptr::{self, NonNull};
@@ -306,20 +308,35 @@ where
     }
 }
 
-// Split a memory region ptr..ptr + len into three parts:
-//   +--------+
-//   | small0 | Chunk smaller than 8 bytes
-//   +--------+
-//   |   big  | Chunk 8-byte aligned, and size a multiple of 8 bytes
-//   +--------+
-//   | small1 | Chunk smaller than 8 bytes
-//   +--------+
-fn region_as_aligned_chunks(ptr: *const u8, len: usize) -> (usize, usize, usize) {
-    let small0_size = if ptr.is_aligned_to(8) { 0 } else { 8 - ptr.addr() % 8 };
-    let small1_size = (len - small0_size) % 8;
-    let big_size = len - small0_size - small1_size;
-
-    (small0_size, big_size, small1_size)
+/// Divide the slice `(ptr, len)` into three parts, where the middle part is
+/// aligned to `u64`.
+///
+/// The return values `(prefix_len, mid_len, suffix_len)` add back up to `len`.
+/// The return values are such that the memory region `(ptr + prefix_len,
+/// mid_len)` is the largest possible region where `ptr + prefix_len` is aligned
+/// to `u64` and `mid_len` is a multiple of the byte size of `u64`. This means
+/// that `prefix_len` and `suffix_len` are guaranteed to be less than the byte
+/// size of `u64`, and that `(ptr, prefix_len)` and `(ptr + prefix_len +
+/// mid_len, suffix_len)` don't straddle an alignment boundary.
+// Standard Rust functions such as `<[u8]>::align_to::<u64>` and
+// `<*const u8>::align_offset` aren't _guaranteed_ to compute the largest
+// possible middle region, and as such can't be used.
+fn u64_align_to_guaranteed(ptr: *const u8, mut len: usize) -> (usize, usize, usize) {
+    const QWORD_SIZE: usize = mem::size_of::<u64>();
+
+    let offset = ptr as usize % QWORD_SIZE;
+
+    let prefix_len = if intrinsics::unlikely(offset > 0) { QWORD_SIZE - offset } else { 0 };
+
+    len = match len.checked_sub(prefix_len) {
+        Some(remaining_len) => remaining_len,
+        None => return (len, 0, 0),
+    };
+
+    let suffix_len = len % QWORD_SIZE;
+    len -= suffix_len;
+
+    (prefix_len, len, suffix_len)
 }
 
 unsafe fn copy_quadwords(src: *const u8, dst: *mut u8, len: usize) {
@@ -352,7 +369,13 @@ unsafe fn copy_quadwords(src: *const u8, dst: *mut u8, len: usize) {
 ///  - https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00615.html
 ///  - https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/processor-mmio-stale-data-vulnerabilities.html#inpage-nav-3-2-2
 pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) {
-    unsafe fn copy_bytewise_to_userspace(src: *const u8, dst: *mut u8, len: usize) {
+    /// Like `ptr::copy(src, dst, len)`, except it uses the Intel-recommended
+    /// instruction sequence for unaligned writes.
+    unsafe fn write_bytewise_to_userspace(src: *const u8, dst: *mut u8, len: usize) {
+        if intrinsics::likely(len == 0) {
+            return;
+        }
+
         unsafe {
             let mut seg_sel: u16 = 0;
             for off in 0..len {
@@ -380,41 +403,15 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
     assert!(!src.addr().overflowing_add(len).1);
     assert!(!dst.addr().overflowing_add(len).1);
 
-    if len < 8 {
-        // Can't align on 8 byte boundary: copy safely byte per byte
-        unsafe {
-            copy_bytewise_to_userspace(src, dst, len);
-        }
-    } else if len % 8 == 0 && dst.is_aligned_to(8) {
-        // Copying 8-byte aligned quadwords: copy quad word per quad word
-        unsafe {
-            copy_quadwords(src, dst, len);
-        }
-    } else {
-        // Split copies into three parts:
-        //   +--------+
-        //   | small0 | Chunk smaller than 8 bytes
-        //   +--------+
-        //   |   big  | Chunk 8-byte aligned, and size a multiple of 8 bytes
-        //   +--------+
-        //   | small1 | Chunk smaller than 8 bytes
-        //   +--------+
-        let (small0_size, big_size, small1_size) = region_as_aligned_chunks(dst, len);
+    unsafe {
+        let (len1, len2, len3) = u64_align_to_guaranteed(dst, len);
+        let (src1, dst1) = (src, dst);
+        let (src2, dst2) = (src1.add(len1), dst1.add(len1));
+        let (src3, dst3) = (src2.add(len2), dst2.add(len2));
 
-        unsafe {
-            // Copy small0
-            copy_bytewise_to_userspace(src, dst, small0_size);
-
-            // Copy big
-            let big_src = src.add(small0_size);
-            let big_dst = dst.add(small0_size);
-            copy_quadwords(big_src, big_dst, big_size);
-
-            // Copy small1
-            let small1_src = src.add(big_size + small0_size);
-            let small1_dst = dst.add(big_size + small0_size);
-            copy_bytewise_to_userspace(small1_src, small1_dst, small1_size);
-        }
+        write_bytewise_to_userspace(src1, dst1, len1);
+        copy_quadwords(src2, dst2, len2);
+        write_bytewise_to_userspace(src3, dst3, len3);
     }
 }
 
@@ -434,45 +431,33 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
 ///  - https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00657.html
 ///  - https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/stale-data-read-from-xapic.html
 pub(crate) unsafe fn copy_from_userspace(src: *const u8, dst: *mut u8, len: usize) {
-    // Copies memory region `src..src + len` to the enclave at `dst`. The source memory region
-    // is:
-    //  - strictly less than 8 bytes in size and may be
-    //  - located at a misaligned memory location
-    fn copy_misaligned_chunk_to_enclave(src: *const u8, dst: *mut u8, len: usize) {
-        let mut tmp_buff = [0u8; 16];
+    /// Like `ptr::copy(src, dst, len)`, except it uses only u64-aligned reads.
+    ///
+    /// # Safety
+    /// The source memory region must not straddle an alignment boundary.
+    unsafe fn read_misaligned_from_userspace(src: *const u8, dst: *mut u8, len: usize) {
+        if intrinsics::likely(len == 0) {
+            return;
+        }
 
         unsafe {
-            // Compute an aligned memory region to read from
-            // +--------+ <-- aligned_src + aligned_len (8B-aligned)
-            // |  pad1  |
-            // +--------+ <-- src + len (misaligned)
-            // |        |
-            // |        |
-            // |        |
-            // +--------+ <-- src (misaligned)
-            // |  pad0  |
-            // +--------+ <-- aligned_src (8B-aligned)
-            let pad0_size = src as usize % 8;
-            let aligned_src = src.sub(pad0_size);
-
-            let pad1_size = 8 - (src.add(len) as usize % 8);
-            let aligned_len = pad0_size + len + pad1_size;
-
-            debug_assert!(len < 8);
-            debug_assert_eq!(aligned_src as usize % 8, 0);
-            debug_assert_eq!(aligned_len % 8, 0);
-            debug_assert!(aligned_len <= 16);
-
-            // Copy the aligned buffer to a temporary buffer
-            // Note: copying from a slightly different memory location is a bit odd. In this case it
-            // can't lead to page faults or inadvertent copying from the enclave as we only ensured
-            // that the `src` pointer is aligned at an 8 byte boundary. As pages are 4096 bytes
-            // aligned, `aligned_src` must be on the same page as `src`. A similar argument can be made
-            // for `src + len`
-            copy_quadwords(aligned_src as _, tmp_buff.as_mut_ptr(), aligned_len);
-
-            // Copy the correct parts of the temporary buffer to the destination
-            ptr::copy(tmp_buff.as_ptr().add(pad0_size), dst, len);
+            let offset: usize;
+            let data: u64;
+            // doing a memory read that's potentially out of bounds for `src`,
+            // this isn't supported by Rust, so have to use assembly
+            asm!("
+                movl {src:e}, {offset:e}
+                andl $7, {offset:e}
+                andq $-8, {src}
+                movq ({src}), {dst}
+                ",
+                src = inout(reg) src => _,
+                offset = out(reg) offset,
+                dst = out(reg) data,
+                options(nostack, att_syntax, readonly, pure)
+            );
+            let data = data.to_le_bytes();
+            ptr::copy_nonoverlapping(data.as_ptr().add(offset), dst, len);
         }
     }
 
@@ -480,41 +465,19 @@ pub(crate) unsafe fn copy_from_userspace(src: *const u8, dst: *mut u8, len: usiz
     assert!(!dst.is_null());
     assert!(is_user_range(src, len));
     assert!(is_enclave_range(dst, len));
-    assert!(!(src as usize).overflowing_add(len + 8).1);
-    assert!(!(dst as usize).overflowing_add(len + 8).1);
+    assert!(len < isize::MAX as usize);
+    assert!(!(src as usize).overflowing_add(len).1);
+    assert!(!(dst as usize).overflowing_add(len).1);
 
-    if len < 8 {
-        copy_misaligned_chunk_to_enclave(src, dst, len);
-    } else if len % 8 == 0 && src as usize % 8 == 0 {
-        // Copying 8-byte aligned quadwords: copy quad word per quad word
-        unsafe {
-            copy_quadwords(src, dst, len);
-        }
-    } else {
-        // Split copies into three parts:
-        //   +--------+
-        //   | small0 | Chunk smaller than 8 bytes
-        //   +--------+
-        //   |   big  | Chunk 8-byte aligned, and size a multiple of 8 bytes
-        //   +--------+
-        //   | small1 | Chunk smaller than 8 bytes
-        //   +--------+
-        let (small0_size, big_size, small1_size) = region_as_aligned_chunks(dst, len);
+    unsafe {
+        let (len1, len2, len3) = u64_align_to_guaranteed(src, len);
+        let (src1, dst1) = (src, dst);
+        let (src2, dst2) = (src1.add(len1), dst1.add(len1));
+        let (src3, dst3) = (src2.add(len2), dst2.add(len2));
 
-        unsafe {
-            // Copy small0
-            copy_misaligned_chunk_to_enclave(src, dst, small0_size);
-
-            // Copy big
-            let big_src = src.add(small0_size);
-            let big_dst = dst.add(small0_size);
-            copy_quadwords(big_src, big_dst, big_size);
-
-            // Copy small1
-            let small1_src = src.add(big_size + small0_size);
-            let small1_dst = dst.add(big_size + small0_size);
-            copy_misaligned_chunk_to_enclave(small1_src, small1_dst, small1_size);
-        }
+        read_misaligned_from_userspace(src1, dst1, len1);
+        copy_quadwords(src2, dst2, len2);
+        read_misaligned_from_userspace(src3, dst3, len3);
     }
 }
 
@@ -609,9 +572,9 @@ where
     /// Copies the value from user memory into enclave memory.
     pub fn to_enclave(&self) -> T {
         unsafe {
-            let mut data: T = mem::MaybeUninit::uninit().assume_init();
-            copy_from_userspace(self.0.get() as _, &mut data as *mut T as _, mem::size_of::<T>());
-            data
+            let mut data = mem::MaybeUninit::uninit();
+            copy_from_userspace(self.0.get() as _, data.as_mut_ptr() as _, mem::size_of::<T>());
+            data.assume_init()
         }
     }
 }
diff --git a/library/std/src/sys/sgx/waitqueue/mod.rs b/library/std/src/sys/sgx/waitqueue/mod.rs
index 5e1d859ee99..25eca61d67b 100644
--- a/library/std/src/sys/sgx/waitqueue/mod.rs
+++ b/library/std/src/sys/sgx/waitqueue/mod.rs
@@ -18,6 +18,7 @@ mod unsafe_list;
 
 use crate::num::NonZeroUsize;
 use crate::ops::{Deref, DerefMut};
+use crate::panic::{self, AssertUnwindSafe};
 use crate::time::Duration;
 
 use super::abi::thread;
@@ -147,7 +148,8 @@ impl WaitQueue {
     /// Adds the calling thread to the `WaitVariable`'s wait queue, then wait
     /// until a wakeup event.
     ///
-    /// This function does not return until this thread has been awoken.
+    /// This function does not return until this thread has been awoken. When `before_wait` panics,
+    /// this function will abort.
     pub fn wait<T, F: FnOnce()>(mut guard: SpinMutexGuard<'_, WaitVariable<T>>, before_wait: F) {
         // very unsafe: check requirements of UnsafeList::push
         unsafe {
@@ -157,8 +159,13 @@ impl WaitQueue {
             }));
             let entry = guard.queue.inner.push(&mut entry);
             drop(guard);
-            before_wait();
+            if let Err(_e) = panic::catch_unwind(AssertUnwindSafe(|| before_wait())) {
+                rtabort!("Panic before wait on wakeup event")
+            }
             while !entry.lock().wake {
+                // `entry.wake` is only set in `notify_one` and `notify_all` functions. Both ensure
+                // the entry is removed from the queue _before_ setting this bool. There are no
+                // other references to `entry`.
                 // don't panic, this would invalidate `entry` during unwinding
                 let eventset = rtunwrap!(Ok, usercalls::wait(EV_UNPARK, WAIT_INDEFINITE));
                 rtassert!(eventset & EV_UNPARK == EV_UNPARK);
@@ -169,6 +176,7 @@ impl WaitQueue {
     /// Adds the calling thread to the `WaitVariable`'s wait queue, then wait
     /// until a wakeup event or timeout. If event was observed, returns true.
     /// If not, it will remove the calling thread from the wait queue.
+    /// When `before_wait` panics, this function will abort.
     pub fn wait_timeout<T, F: FnOnce()>(
         lock: &SpinMutex<WaitVariable<T>>,
         timeout: Duration,
@@ -181,9 +189,13 @@ impl WaitQueue {
                 wake: false,
             }));
             let entry_lock = lock.lock().queue.inner.push(&mut entry);
-            before_wait();
+            if let Err(_e) = panic::catch_unwind(AssertUnwindSafe(|| before_wait())) {
+                rtabort!("Panic before wait on wakeup event or timeout")
+            }
             usercalls::wait_timeout(EV_UNPARK, timeout, || entry_lock.lock().wake);
-            // acquire the wait queue's lock first to avoid deadlock.
+            // acquire the wait queue's lock first to avoid deadlock
+            // and ensure no other function can simultaneously access the list
+            // (e.g., `notify_one` or `notify_all`)
             let mut guard = lock.lock();
             let success = entry_lock.lock().wake;
             if !success {
@@ -204,8 +216,8 @@ impl WaitQueue {
     ) -> Result<WaitGuard<'_, T>, SpinMutexGuard<'_, WaitVariable<T>>> {
         // SAFETY: lifetime of the pop() return value is limited to the map
         // closure (The closure return value is 'static). The underlying
-        // stack frame won't be freed until after the WaitGuard created below
-        // is dropped.
+        // stack frame won't be freed until after the lock on the queue is released
+        // (i.e., `guard` is dropped).
         unsafe {
             let tcs = guard.queue.inner.pop().map(|entry| -> Tcs {
                 let mut entry_guard = entry.lock();
@@ -231,7 +243,7 @@ impl WaitQueue {
     ) -> Result<WaitGuard<'_, T>, SpinMutexGuard<'_, WaitVariable<T>>> {
         // SAFETY: lifetime of the pop() return values are limited to the
         // while loop body. The underlying stack frames won't be freed until
-        // after the WaitGuard created below is dropped.
+        // after the lock on the queue is released (i.e., `guard` is dropped).
         unsafe {
             let mut count = 0;
             while let Some(entry) = guard.queue.inner.pop() {
diff --git a/library/std/src/sys/uefi/mod.rs b/library/std/src/sys/uefi/mod.rs
index 9a10395af8e..097396ae993 100644
--- a/library/std/src/sys/uefi/mod.rs
+++ b/library/std/src/sys/uefi/mod.rs
@@ -36,7 +36,6 @@ pub mod path;
 pub mod pipe;
 #[path = "../unsupported/process.rs"]
 pub mod process;
-#[path = "../unsupported/stdio.rs"]
 pub mod stdio;
 #[path = "../unsupported/thread.rs"]
 pub mod thread;
diff --git a/library/std/src/sys/uefi/stdio.rs b/library/std/src/sys/uefi/stdio.rs
new file mode 100644
index 00000000000..a533d8a0575
--- /dev/null
+++ b/library/std/src/sys/uefi/stdio.rs
@@ -0,0 +1,162 @@
+use crate::io;
+use crate::iter::Iterator;
+use crate::mem::MaybeUninit;
+use crate::os::uefi;
+use crate::ptr::NonNull;
+
+const MAX_BUFFER_SIZE: usize = 8192;
+
+pub struct Stdin;
+pub struct Stdout;
+pub struct Stderr;
+
+impl Stdin {
+    pub const fn new() -> Stdin {
+        Stdin
+    }
+}
+
+impl io::Read for Stdin {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        let st: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table().cast();
+        let stdin = unsafe { (*st.as_ptr()).con_in };
+
+        // Try reading any pending data
+        let inp = match read_key_stroke(stdin) {
+            Ok(x) => x,
+            Err(e) if e == r_efi::efi::Status::NOT_READY => {
+                // Wait for keypress for new data
+                wait_stdin(stdin)?;
+                read_key_stroke(stdin).map_err(|x| io::Error::from_raw_os_error(x.as_usize()))?
+            }
+            Err(e) => {
+                return Err(io::Error::from_raw_os_error(e.as_usize()));
+            }
+        };
+
+        // Check if the key is printiable character
+        if inp.scan_code != 0x00 {
+            return Err(io::const_io_error!(io::ErrorKind::Interrupted, "Special Key Press"));
+        }
+
+        // SAFETY: Iterator will have only 1 character since we are reading only 1 Key
+        // SAFETY: This character will always be UCS-2 and thus no surrogates.
+        let ch: char = char::decode_utf16([inp.unicode_char]).next().unwrap().unwrap();
+        if ch.len_utf8() > buf.len() {
+            return Ok(0);
+        }
+
+        ch.encode_utf8(buf);
+
+        Ok(ch.len_utf8())
+    }
+}
+
+impl Stdout {
+    pub const fn new() -> Stdout {
+        Stdout
+    }
+}
+
+impl io::Write for Stdout {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        let st: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table().cast();
+        let stdout = unsafe { (*st.as_ptr()).con_out };
+
+        write(stdout, buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+impl Stderr {
+    pub const fn new() -> Stderr {
+        Stderr
+    }
+}
+
+impl io::Write for Stderr {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        let st: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table().cast();
+        let stderr = unsafe { (*st.as_ptr()).std_err };
+
+        write(stderr, buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+// UCS-2 character should occupy 3 bytes at most in UTF-8
+pub const STDIN_BUF_SIZE: usize = 3;
+
+pub fn is_ebadf(_err: &io::Error) -> bool {
+    true
+}
+
+pub fn panic_output() -> Option<impl io::Write> {
+    uefi::env::try_system_table().map(|_| Stderr::new())
+}
+
+fn write(
+    protocol: *mut r_efi::protocols::simple_text_output::Protocol,
+    buf: &[u8],
+) -> io::Result<usize> {
+    let mut utf16 = [0; MAX_BUFFER_SIZE / 2];
+
+    // Get valid UTF-8 buffer
+    let utf8 = match crate::str::from_utf8(buf) {
+        Ok(x) => x,
+        Err(e) => unsafe { crate::str::from_utf8_unchecked(&buf[..e.valid_up_to()]) },
+    };
+    // Clip UTF-8 buffer to max UTF-16 buffer we support
+    let utf8 = &utf8[..utf8.floor_char_boundary(utf16.len() - 1)];
+
+    for (i, ch) in utf8.encode_utf16().enumerate() {
+        utf16[i] = ch;
+    }
+
+    unsafe { simple_text_output(protocol, &mut utf16) }?;
+
+    Ok(utf8.len())
+}
+
+unsafe fn simple_text_output(
+    protocol: *mut r_efi::protocols::simple_text_output::Protocol,
+    buf: &mut [u16],
+) -> io::Result<()> {
+    let res = unsafe { ((*protocol).output_string)(protocol, buf.as_mut_ptr()) };
+    if res.is_error() { Err(io::Error::from_raw_os_error(res.as_usize())) } else { Ok(()) }
+}
+
+fn wait_stdin(stdin: *mut r_efi::protocols::simple_text_input::Protocol) -> io::Result<()> {
+    let boot_services: NonNull<r_efi::efi::BootServices> =
+        uefi::env::boot_services().unwrap().cast();
+    let wait_for_event = unsafe { (*boot_services.as_ptr()).wait_for_event };
+    let wait_for_key_event = unsafe { (*stdin).wait_for_key };
+
+    let r = {
+        let mut x: usize = 0;
+        (wait_for_event)(1, [wait_for_key_event].as_mut_ptr(), &mut x)
+    };
+    if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
+}
+
+fn read_key_stroke(
+    stdin: *mut r_efi::protocols::simple_text_input::Protocol,
+) -> Result<r_efi::protocols::simple_text_input::InputKey, r_efi::efi::Status> {
+    let mut input_key: MaybeUninit<r_efi::protocols::simple_text_input::InputKey> =
+        MaybeUninit::uninit();
+
+    let r = unsafe { ((*stdin).read_key_stroke)(stdin, input_key.as_mut_ptr()) };
+
+    if r.is_error() {
+        Err(r)
+    } else {
+        let input_key = unsafe { input_key.assume_init() };
+        Ok(input_key)
+    }
+}
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 764e1f25790..5ed2bdd7fe3 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -1391,6 +1391,7 @@ impl FromInner<FileDesc> for File {
 }
 
 impl AsFd for File {
+    #[inline]
     fn as_fd(&self) -> BorrowedFd<'_> {
         self.0.as_fd()
     }
diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs
index fba2a676f28..e9d19766592 100644
--- a/library/std/src/sys/unix/thread_local_dtor.rs
+++ b/library/std/src/sys/unix/thread_local_dtor.rs
@@ -11,28 +11,47 @@
 // Note, however, that we run on lots older linuxes, as well as cross
 // compiling from a newer linux to an older linux, so we also have a
 // fallback implementation to use as well.
+#[allow(unexpected_cfgs)]
 #[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "redox", target_os = "hurd"))]
+// FIXME: The Rust compiler currently omits weakly function definitions (i.e.,
+// __cxa_thread_atexit_impl) and its metadata from LLVM IR.
+#[no_sanitize(cfi, kcfi)]
 pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
     use crate::mem;
     use crate::sys_common::thread_local_dtor::register_dtor_fallback;
 
+    /// This is necessary because the __cxa_thread_atexit_impl implementation
+    /// std links to by default may be a C or C++ implementation that was not
+    /// compiled using the Clang integer normalization option.
+    #[cfg(not(sanitizer_cfi_normalize_integers))]
+    #[cfi_encoding = "i"]
+    #[repr(transparent)]
+    pub struct c_int(pub libc::c_int);
+
     extern "C" {
         #[linkage = "extern_weak"]
         static __dso_handle: *mut u8;
         #[linkage = "extern_weak"]
-        static __cxa_thread_atexit_impl: *const libc::c_void;
+        static __cxa_thread_atexit_impl: Option<
+            extern "C" fn(
+                unsafe extern "C" fn(*mut libc::c_void),
+                *mut libc::c_void,
+                *mut libc::c_void,
+            ) -> c_int,
+        >;
     }
-    if !__cxa_thread_atexit_impl.is_null() {
-        type F = unsafe extern "C" fn(
-            dtor: unsafe extern "C" fn(*mut u8),
-            arg: *mut u8,
-            dso_handle: *mut u8,
-        ) -> libc::c_int;
-        mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl)(
-            dtor,
-            t,
-            &__dso_handle as *const _ as *mut _,
-        );
+
+    if let Some(f) = __cxa_thread_atexit_impl {
+        unsafe {
+            f(
+                mem::transmute::<
+                    unsafe extern "C" fn(*mut u8),
+                    unsafe extern "C" fn(*mut libc::c_void),
+                >(dtor),
+                t.cast(),
+                &__dso_handle as *const _ as *mut _,
+            );
+        }
         return;
     }
     register_dtor_fallback(t, dtor);
diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs
index 5cbb5cb65ba..5919cc506d9 100644
--- a/library/std/src/sys/wasi/mod.rs
+++ b/library/std/src/sys/wasi/mod.rs
@@ -82,31 +82,99 @@ pub fn is_interrupted(errno: i32) -> bool {
 }
 
 pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
-    use std_io::ErrorKind::*;
-    if errno > u16::MAX as i32 || errno < 0 {
-        return Uncategorized;
+    use std_io::ErrorKind;
+
+    let Ok(errno) = u16::try_from(errno) else {
+        return ErrorKind::Uncategorized;
+    };
+
+    macro_rules! match_errno {
+        ($($($errno:ident)|+ => $errkind:ident),*, _ => $wildcard:ident $(,)?) => {
+            match errno {
+                $(e if $(e == ::wasi::$errno.raw())||+ => ErrorKind::$errkind),*,
+                _ => ErrorKind::$wildcard,
+            }
+        };
     }
 
-    match errno {
-        e if e == wasi::ERRNO_CONNREFUSED.raw().into() => ConnectionRefused,
-        e if e == wasi::ERRNO_CONNRESET.raw().into() => ConnectionReset,
-        e if e == wasi::ERRNO_PERM.raw().into() || e == wasi::ERRNO_ACCES.raw().into() => {
-            PermissionDenied
-        }
-        e if e == wasi::ERRNO_PIPE.raw().into() => BrokenPipe,
-        e if e == wasi::ERRNO_NOTCONN.raw().into() => NotConnected,
-        e if e == wasi::ERRNO_CONNABORTED.raw().into() => ConnectionAborted,
-        e if e == wasi::ERRNO_ADDRNOTAVAIL.raw().into() => AddrNotAvailable,
-        e if e == wasi::ERRNO_ADDRINUSE.raw().into() => AddrInUse,
-        e if e == wasi::ERRNO_NOENT.raw().into() => NotFound,
-        e if e == wasi::ERRNO_INTR.raw().into() => Interrupted,
-        e if e == wasi::ERRNO_INVAL.raw().into() => InvalidInput,
-        e if e == wasi::ERRNO_TIMEDOUT.raw().into() => TimedOut,
-        e if e == wasi::ERRNO_EXIST.raw().into() => AlreadyExists,
-        e if e == wasi::ERRNO_AGAIN.raw().into() => WouldBlock,
-        e if e == wasi::ERRNO_NOSYS.raw().into() => Unsupported,
-        e if e == wasi::ERRNO_NOMEM.raw().into() => OutOfMemory,
-        _ => Uncategorized,
+    match_errno! {
+        ERRNO_2BIG           => ArgumentListTooLong,
+        ERRNO_ACCES          => PermissionDenied,
+        ERRNO_ADDRINUSE      => AddrInUse,
+        ERRNO_ADDRNOTAVAIL   => AddrNotAvailable,
+        ERRNO_AFNOSUPPORT    => Unsupported,
+        ERRNO_AGAIN          => WouldBlock,
+        //    ALREADY        => "connection already in progress",
+        //    BADF           => "bad file descriptor",
+        //    BADMSG         => "bad message",
+        ERRNO_BUSY           => ResourceBusy,
+        //    CANCELED       => "operation canceled",
+        //    CHILD          => "no child processes",
+        ERRNO_CONNABORTED    => ConnectionAborted,
+        ERRNO_CONNREFUSED    => ConnectionRefused,
+        ERRNO_CONNRESET      => ConnectionReset,
+        ERRNO_DEADLK         => Deadlock,
+        //    DESTADDRREQ    => "destination address required",
+        ERRNO_DOM            => InvalidInput,
+        //    DQUOT          => /* reserved */,
+        ERRNO_EXIST          => AlreadyExists,
+        //    FAULT          => "bad address",
+        ERRNO_FBIG           => FileTooLarge,
+        ERRNO_HOSTUNREACH    => HostUnreachable,
+        //    IDRM           => "identifier removed",
+        //    ILSEQ          => "illegal byte sequence",
+        //    INPROGRESS     => "operation in progress",
+        ERRNO_INTR           => Interrupted,
+        ERRNO_INVAL          => InvalidInput,
+        ERRNO_IO             => Uncategorized,
+        //    ISCONN         => "socket is connected",
+        ERRNO_ISDIR          => IsADirectory,
+        ERRNO_LOOP           => FilesystemLoop,
+        //    MFILE          => "file descriptor value too large",
+        ERRNO_MLINK          => TooManyLinks,
+        //    MSGSIZE        => "message too large",
+        //    MULTIHOP       => /* reserved */,
+        ERRNO_NAMETOOLONG    => InvalidFilename,
+        ERRNO_NETDOWN        => NetworkDown,
+        //    NETRESET       => "connection aborted by network",
+        ERRNO_NETUNREACH     => NetworkUnreachable,
+        //    NFILE          => "too many files open in system",
+        //    NOBUFS         => "no buffer space available",
+        ERRNO_NODEV          => NotFound,
+        ERRNO_NOENT          => NotFound,
+        //    NOEXEC         => "executable file format error",
+        //    NOLCK          => "no locks available",
+        //    NOLINK         => /* reserved */,
+        ERRNO_NOMEM          => OutOfMemory,
+        //    NOMSG          => "no message of the desired type",
+        //    NOPROTOOPT     => "protocol not available",
+        ERRNO_NOSPC          => StorageFull,
+        ERRNO_NOSYS          => Unsupported,
+        ERRNO_NOTCONN        => NotConnected,
+        ERRNO_NOTDIR         => NotADirectory,
+        ERRNO_NOTEMPTY       => DirectoryNotEmpty,
+        //    NOTRECOVERABLE => "state not recoverable",
+        //    NOTSOCK        => "not a socket",
+        ERRNO_NOTSUP         => Unsupported,
+        //    NOTTY          => "inappropriate I/O control operation",
+        ERRNO_NXIO           => NotFound,
+        //    OVERFLOW       => "value too large to be stored in data type",
+        //    OWNERDEAD      => "previous owner died",
+        ERRNO_PERM           => PermissionDenied,
+        ERRNO_PIPE           => BrokenPipe,
+        //    PROTO          => "protocol error",
+        ERRNO_PROTONOSUPPORT => Unsupported,
+        //    PROTOTYPE      => "protocol wrong type for socket",
+        //    RANGE          => "result too large",
+        ERRNO_ROFS           => ReadOnlyFilesystem,
+        ERRNO_SPIPE          => NotSeekable,
+        ERRNO_SRCH           => NotFound,
+        //    STALE          => /* reserved */,
+        ERRNO_TIMEDOUT       => TimedOut,
+        ERRNO_TXTBSY         => ResourceBusy,
+        ERRNO_XDEV           => CrossesDevices,
+        ERRNO_NOTCAPABLE     => PermissionDenied,
+        _                    => Uncategorized,
     }
 }
 
@@ -124,6 +192,7 @@ pub fn hashmap_random_keys() -> (u64, u64) {
     return ret;
 }
 
+#[inline]
 fn err2io(err: wasi::Errno) -> std_io::Error {
     std_io::Error::from_raw_os_error(err.raw().into())
 }
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index f3637cbb981..a349e24b039 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -46,6 +46,10 @@ pub use FD_SET as fd_set;
 pub use LINGER as linger;
 pub use TIMEVAL as timeval;
 
+// https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure?view=msvc-170
+pub const EXIT_SUCCESS: u32 = 0;
+pub const EXIT_FAILURE: u32 = 1;
+
 pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: ptr::null_mut() };
 pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: ptr::null_mut() };
 pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: ptr::null_mut() };
diff --git a/library/std/src/sys/windows/cmath.rs b/library/std/src/sys/windows/cmath.rs
index 1b2a86f3c0e..36578d5a34e 100644
--- a/library/std/src/sys/windows/cmath.rs
+++ b/library/std/src/sys/windows/cmath.rs
@@ -1,6 +1,6 @@
 #![cfg(not(test))]
 
-use libc::{c_double, c_float, c_int};
+use core::ffi::{c_double, c_float, c_int};
 
 extern "C" {
     pub fn acos(n: c_double) -> c_double;
@@ -33,7 +33,7 @@ pub use self::shims::*;
 
 #[cfg(not(all(target_env = "msvc", target_arch = "x86")))]
 mod shims {
-    use libc::c_float;
+    use core::ffi::c_float;
 
     extern "C" {
         pub fn acosf(n: c_float) -> c_float;
@@ -52,7 +52,7 @@ mod shims {
 // back to f32. While not precisely correct should be "correct enough" for now.
 #[cfg(all(target_env = "msvc", target_arch = "x86"))]
 mod shims {
-    use libc::c_float;
+    use core::ffi::c_float;
 
     #[inline]
     pub unsafe fn acosf(n: c_float) -> c_float {
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index 21a65bc25f3..0113196b824 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -16,6 +16,8 @@ use crate::sys::{c, cvt, Align8};
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::thread;
 
+use core::ffi::c_void;
+
 use super::path::maybe_verbatim;
 use super::to_u16s;
 
@@ -371,7 +373,7 @@ impl File {
             cvt(c::GetFileInformationByHandleEx(
                 self.handle.as_raw_handle(),
                 c::FileBasicInfo,
-                &mut info as *mut _ as *mut libc::c_void,
+                &mut info as *mut _ as *mut c_void,
                 size as c::DWORD,
             ))?;
             let mut attr = FileAttr {
@@ -399,7 +401,7 @@ impl File {
             cvt(c::GetFileInformationByHandleEx(
                 self.handle.as_raw_handle(),
                 c::FileStandardInfo,
-                &mut info as *mut _ as *mut libc::c_void,
+                &mut info as *mut _ as *mut c_void,
                 size as c::DWORD,
             ))?;
             attr.file_size = info.AllocationSize as u64;
@@ -624,7 +626,7 @@ impl File {
             cvt(c::GetFileInformationByHandleEx(
                 self.handle.as_raw_handle(),
                 c::FileBasicInfo,
-                &mut info as *mut _ as *mut libc::c_void,
+                &mut info as *mut _ as *mut c_void,
                 size as c::DWORD,
             ))?;
             Ok(info)
diff --git a/library/std/src/sys/windows/io.rs b/library/std/src/sys/windows/io.rs
index fc9856caed6..9b540ee071f 100644
--- a/library/std/src/sys/windows/io.rs
+++ b/library/std/src/sys/windows/io.rs
@@ -3,7 +3,7 @@ use crate::mem::size_of;
 use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle};
 use crate::slice;
 use crate::sys::c;
-use libc;
+use core::ffi::c_void;
 
 #[derive(Copy, Clone)]
 #[repr(transparent)]
@@ -136,7 +136,7 @@ unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
     let res = c::GetFileInformationByHandleEx(
         handle,
         c::FileNameInfo,
-        &mut name_info as *mut _ as *mut libc::c_void,
+        &mut name_info as *mut _ as *mut c_void,
         size_of::<FILE_NAME_INFO>() as u32,
     );
     if res == 0 {
diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs
index abdcab4247f..4b7115f97c5 100644
--- a/library/std/src/sys/windows/net.rs
+++ b/library/std/src/sys/windows/net.rs
@@ -15,7 +15,7 @@ use crate::sys_common::net;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::time::Duration;
 
-use libc::{c_int, c_long, c_ulong, c_ushort};
+use core::ffi::{c_int, c_long, c_ulong, c_ushort};
 
 pub type wrlen_t = i32;
 
diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index cd5bf7f1538..f4078d35944 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -19,8 +19,7 @@ use crate::path::{Path, PathBuf};
 use crate::ptr;
 use crate::sync::Mutex;
 use crate::sys::args::{self, Arg};
-use crate::sys::c;
-use crate::sys::c::NonZeroDWORD;
+use crate::sys::c::{self, NonZeroDWORD, EXIT_FAILURE, EXIT_SUCCESS};
 use crate::sys::cvt;
 use crate::sys::fs::{File, OpenOptions};
 use crate::sys::handle::Handle;
@@ -30,7 +29,7 @@ use crate::sys::stdio;
 use crate::sys_common::process::{CommandEnv, CommandEnvs};
 use crate::sys_common::IntoInner;
 
-use libc::{c_void, EXIT_FAILURE, EXIT_SUCCESS};
+use core::ffi::c_void;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
diff --git a/library/std/src/sys/windows/thread.rs b/library/std/src/sys/windows/thread.rs
index 18cecb65681..4b825d2a9f5 100644
--- a/library/std/src/sys/windows/thread.rs
+++ b/library/std/src/sys/windows/thread.rs
@@ -10,7 +10,7 @@ use crate::sys::stack_overflow;
 use crate::sys_common::FromInner;
 use crate::time::Duration;
 
-use libc::c_void;
+use core::ffi::c_void;
 
 use super::to_u16s;
 
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index c638cc61856..90ac0098dec 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -58,6 +58,8 @@ pub use core::time::TryFromFloatSecsError;
 /// some seconds may be longer than others). An instant may jump forwards or
 /// experience time dilation (slow down or speed up), but it will never go
 /// backwards.
+/// As part of this non-guarantee it is also not specified whether system suspends count as
+/// elapsed time or not. The behavior varies across platforms and rust versions.
 ///
 /// Instants are opaque types that can only be compared to one another. There is
 /// no method to get "the number of seconds" from an instant. Instead, it only
@@ -151,6 +153,7 @@ pub use core::time::TryFromFloatSecsError;
 ///
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[stable(feature = "time2", since = "1.8.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Instant")]
 pub struct Instant(time::Instant);
 
 /// A measurement of the system clock, useful for talking to
diff --git a/library/stdarch b/library/stdarch
-Subproject 6100854c4b360f84da5ab25e7c75cb2080667dd
+Subproject 333e9e9977188d0748327e9b5be0f3f41206317
diff --git a/rust-bors.toml b/rust-bors.toml
new file mode 100644
index 00000000000..54f4f641248
--- /dev/null
+++ b/rust-bors.toml
@@ -0,0 +1 @@
+timeout = 7200
diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md
deleted file mode 100644
index 1aba0713850..00000000000
--- a/src/bootstrap/CHANGELOG.md
+++ /dev/null
@@ -1,71 +0,0 @@
-# Changelog
-
-All notable changes to bootstrap will be documented in this file.
-
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-
-## [Changes since the last major version]
-
-- Vendoring is no longer done automatically when building from git sources. To use vendoring, run `cargo vendor` manually, or use the pre-vendored `rustc-src` tarball.
-- `llvm-libunwind` now accepts `in-tree` (formerly true), `system` or `no` (formerly false) [#77703](https://github.com/rust-lang/rust/pull/77703)
-- The options `infodir`, `localstatedir`, and `gpg-password-file` are no longer allowed in config.toml. Previously, they were ignored without warning. Note that `infodir` and `localstatedir` are still accepted by `./configure`, with a warning. [#82451](https://github.com/rust-lang/rust/pull/82451)
-- Change the names for `dist` commands to match the component they generate. [#90684](https://github.com/rust-lang/rust/pull/90684)
-- The `build.fast-submodules` option has been removed. Fast submodule checkouts are enabled unconditionally. Automatic submodule handling can still be disabled with `build.submodules = false`.
-- Several unsupported `./configure` options have been removed: `optimize`, `parallel-compiler`. These can still be enabled with `--set`, although it isn't recommended.
-- `remote-test-server`'s `verbose` argument has been removed in favor of the `--verbose` flag
-- `remote-test-server`'s `remote` argument has been removed in favor of the `--bind` flag. Use `--bind 0.0.0.0:12345` to replicate the behavior of the `remote` argument.
-- `x.py fmt` now formats only files modified between the merge-base of HEAD and the last commit in the master branch of the rust-lang repository and the current working directory. To restore old behaviour, use `x.py fmt .`. The check mode is not affected by this change. [#105702](https://github.com/rust-lang/rust/pull/105702)
-- The `llvm.version-check` config option has been removed. Older versions were never supported. If you still need to support older versions (e.g. you are applying custom patches), patch `check_llvm_version` in bootstrap to change the minimum version. [#108619](https://github.com/rust-lang/rust/pull/108619)
-- The `rust.ignore-git` option has been renamed to `rust.omit-git-hash`. [#110059](https://github.com/rust-lang/rust/pull/110059)
-- `--exclude` no longer accepts a `Kind` as part of a Step; instead it uses the top-level Kind of the subcommand. If this matches how you were already using --exclude (e.g. `x test --exclude test::std`), simply remove the kind: `--exclude std`. If you were using a kind that did not match the top-level subcommand, please open an issue explaining why you wanted this feature.
-
-### Non-breaking changes
-
-- `x.py check` needs opt-in to check tests (--all-targets) [#77473](https://github.com/rust-lang/rust/pull/77473)
-- The default bootstrap profiles are now located at `bootstrap/defaults/config.$PROFILE.toml` (previously they were located at `bootstrap/defaults/config.toml.$PROFILE`) [#77558](https://github.com/rust-lang/rust/pull/77558)
-- If you have Rust already installed, `x.py` will now infer the host target
-  from the default rust toolchain. [#78513](https://github.com/rust-lang/rust/pull/78513)
-- Add options for enabling overflow checks, one for std (`overflow-checks-std`) and one for everything else (`overflow-checks`). Both default to false.
-- Add llvm option `enable-warnings` to have control on llvm compilation warnings. Default to false.
-- Add `rpath` option in `target` section to support set rpath option for each target independently. [#111242](https://github.com/rust-lang/rust/pull/111242)
-
-
-## [Version 2] - 2020-09-25
-
-- `host` now defaults to the value of `build` in all cases
-  + Previously `host` defaulted to an empty list when `target` was overridden, and to `build` otherwise
-
-### Non-breaking changes
-
-- Add `x.py setup` [#76631](https://github.com/rust-lang/rust/pull/76631)
-- Add a changelog for x.py [#76626](https://github.com/rust-lang/rust/pull/76626)
-- Optionally, download LLVM from CI on Linux and NixOS. This can be enabled with `download-ci-llvm = true` under `[llvm]`.
-  + [#76439](https://github.com/rust-lang/rust/pull/76349)
-  + [#76667](https://github.com/rust-lang/rust/pull/76667)
-  + [#76708](https://github.com/rust-lang/rust/pull/76708)
-- Distribute rustc sources as part of `rustc-dev` [#76856](https://github.com/rust-lang/rust/pull/76856)
-- Make the default stage for x.py configurable [#76625](https://github.com/rust-lang/rust/pull/76625). This can be enabled with `build-stage = N`, `doc-stage = N`, etc.
-- Add a dedicated debug-logging option [#76588](https://github.com/rust-lang/rust/pull/76588). Previously, `debug-logging` could only be set with `debug-assertions`, slowing down the compiler more than necessary.
-- Add sample defaults for x.py [#76628](https://github.com/rust-lang/rust/pull/76628)
-- Add `--keep-stage-std`, which behaves like `keep-stage` but allows the stage
-  0 compiler artifacts (i.e., stage1/bin/rustc) to be rebuilt if changed
-  [#77120](https://github.com/rust-lang/rust/pull/77120).
-- File locking is now used to avoid collisions between multiple running instances of `x.py` (e.g. when using `rust-analyzer` and `x.py` at the same time). Note that Solaris and possibly other non Unix and non Windows systems don't support it [#108607](https://github.com/rust-lang/rust/pull/108607). This might possibly lead to build data corruption.
-
-
-## [Version 1] - 2020-09-11
-
-This is the first changelog entry, and it does not attempt to be an exhaustive list of features in x.py.
-Instead, this documents the changes to bootstrap in the past 2 months.
-
-- Improve defaults in `x.py` [#73964](https://github.com/rust-lang/rust/pull/73964)
-  (see [blog post] for details)
-- Set `ninja = true` by default [#74922](https://github.com/rust-lang/rust/pull/74922)
-- Avoid trying to inversely cross-compile for build triple from host triples [#76415](https://github.com/rust-lang/rust/pull/76415)
-- Allow blessing expect-tests in tools [#75975](https://github.com/rust-lang/rust/pull/75975)
-- `x.py check` checks tests/examples/benches [#76258](https://github.com/rust-lang/rust/pull/76258)
-- Fix `rust.use-lld` when linker is not set [#76326](https://github.com/rust-lang/rust/pull/76326)
-- Build tests with LLD if `use-lld = true` was passed [#76378](https://github.com/rust-lang/rust/pull/76378)
-
-[blog post]: https://blog.rust-lang.org/inside-rust/2020/08/30/changes-to-x-py-defaults.html
diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md
index 548281ca506..e7998a40a65 100644
--- a/src/bootstrap/README.md
+++ b/src/bootstrap/README.md
@@ -181,11 +181,10 @@ Some general areas that you may be interested in modifying are:
   `Config` struct.
 * Adding a sanity check? Take a look at `bootstrap/sanity.rs`.
 
-If you make a major change, please remember to:
+If you make a major change on bootstrap configuration, please remember to:
 
-+ Update `VERSION` in `src/bootstrap/main.rs`.
-* Update `changelog-seen = N` in `config.example.toml`.
-* Add an entry in `src/bootstrap/CHANGELOG.md`.
++ Update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/lib.rs`.
+* Update `change-id = {pull-request-id}` in `config.example.toml`.
 
 A 'major change' includes
 
@@ -193,7 +192,7 @@ A 'major change' includes
 * A change in the default options.
 
 Changes that do not affect contributors to the compiler or users
-building rustc from source don't need an update to `VERSION`.
+building rustc from source don't need an update to `CONFIG_CHANGE_HISTORY`.
 
 If you have any questions, feel free to reach out on the `#t-infra/bootstrap` channel
 at [Rust Bootstrap Zulip server][rust-bootstrap-zulip]. When you encounter bugs,
@@ -201,3 +200,8 @@ please file issues on the [Rust issue tracker][rust-issue-tracker].
 
 [rust-bootstrap-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/t-infra.2Fbootstrap
 [rust-issue-tracker]: https://github.com/rust-lang/rust/issues
+
+## Changelog
+
+Because we do not release bootstrap with versions, we also do not maintain CHANGELOG files. To
+review the changes made to bootstrap, simply run `git log --no-merges --oneline -- src/bootstrap`.
diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs
index c497cabbd69..d87fb6a9cef 100644
--- a/src/bootstrap/bin/main.rs
+++ b/src/bootstrap/bin/main.rs
@@ -13,7 +13,7 @@ use std::{env, fs};
 
 #[cfg(all(any(unix, windows), not(target_os = "solaris")))]
 use bootstrap::t;
-use bootstrap::{Build, Config, Subcommand, VERSION};
+use bootstrap::{find_recent_config_change_ids, Build, Config, Subcommand, CONFIG_CHANGE_HISTORY};
 
 fn main() {
     let args = env::args().skip(1).collect::<Vec<_>>();
@@ -42,7 +42,7 @@ fn main() {
             }
             err => {
                 drop(err);
-                println!("warning: build directory locked by process {pid}, waiting for lock");
+                println!("WARNING: build directory locked by process {pid}, waiting for lock");
                 let mut lock = t!(build_lock.write());
                 t!(lock.write(&process::id().to_string().as_ref()));
                 lock
@@ -51,7 +51,7 @@ fn main() {
     }
 
     #[cfg(any(not(any(unix, windows)), target_os = "solaris"))]
-    println!("warning: file locking not supported for target, not locking build directory");
+    println!("WARNING: file locking not supported for target, not locking build directory");
 
     // check_version warnings are not printed during setup
     let changelog_suggestion =
@@ -61,7 +61,7 @@ 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!("WARNING: you have not made a `config.toml`");
         println!(
             "help: consider running `./x.py setup` or copying `config.example.toml` by running \
             `cp config.example.toml config.toml`"
@@ -74,7 +74,7 @@ fn main() {
     Build::new(config).build();
 
     if suggest_setup {
-        println!("warning: you have not made a `config.toml`");
+        println!("WARNING: you have not made a `config.toml`");
         println!(
             "help: consider running `./x.py setup` or copying `config.example.toml` by running \
             `cp config.example.toml config.toml`"
@@ -91,7 +91,7 @@ fn main() {
         contents.contains("https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570")
     }) {
         println!(
-            "warning: You have the pre-push script installed to .git/hooks/pre-commit. \
+            "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."
         );
     }
@@ -104,19 +104,34 @@ fn main() {
 fn check_version(config: &Config) -> Option<String> {
     let mut msg = String::new();
 
-    let suggestion = if let Some(seen) = config.changelog_seen {
-        if seen != VERSION {
-            msg.push_str("warning: there have been changes to x.py since you last updated.\n");
-            format!("update `config.toml` to use `changelog-seen = {VERSION}` instead")
+    if config.changelog_seen.is_some() {
+        msg.push_str("WARNING: The use of `changelog-seen` is deprecated. Please refer to `change-id` option in `config.example.toml` instead.\n");
+    }
+
+    let latest_config_id = CONFIG_CHANGE_HISTORY.last().unwrap();
+    let suggestion = if let Some(id) = config.change_id {
+        if &id != latest_config_id {
+            msg.push_str("WARNING: there have been changes to x.py since you last updated.\n");
+            let change_links: Vec<String> = find_recent_config_change_ids(id)
+                .iter()
+                .map(|id| format!("https://github.com/rust-lang/rust/pull/{id}"))
+                .collect();
+            if !change_links.is_empty() {
+                msg.push_str("To see more detail about these changes, visit the following PRs:\n");
+                for link in change_links {
+                    msg.push_str(&format!("  - {link}\n"));
+                }
+            }
+            msg.push_str("WARNING: there have been changes to x.py since you last updated.\n");
+            format!("update `config.toml` to use `change-id = {latest_config_id}` instead")
         } else {
             return None;
         }
     } else {
-        msg.push_str("warning: x.py has made several changes recently you may want to look at\n");
-        format!("add `changelog-seen = {VERSION}` at the top of `config.toml`")
+        msg.push_str("WARNING: The `change-id` is missing in the `config.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n");
+        format!("add `change-id = {latest_config_id}` at the top of `config.toml`")
     };
 
-    msg.push_str("help: consider looking at the changes in `src/bootstrap/CHANGELOG.md`\n");
     msg.push_str("note: to silence this warning, ");
     msg.push_str(&suggestion);
 
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index fac0cdf2038..4af97b2f466 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -1042,6 +1042,12 @@ def bootstrap(args):
     """Configure, fetch, build and run the initial bootstrap"""
     rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
 
+    if not os.path.exists(os.path.join(rust_root, '.git')) and \
+            os.path.exists(os.path.join(rust_root, '.github')):
+        eprint("warn: Looks like you are trying to bootstrap Rust from a source that is neither a "
+               "git clone nor distributed tarball.\nThis build may fail due to missing submodules "
+               "unless you put them in place manually.")
+
     # Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`,
     # then `config.toml` in the root directory.
     toml_path = args.config or os.getenv('RUST_BOOTSTRAP_CONFIG')
diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py
index dc06a4c9734..fefd6b18739 100644
--- a/src/bootstrap/bootstrap_test.py
+++ b/src/bootstrap/bootstrap_test.py
@@ -103,7 +103,7 @@ class GenerateAndParseConfig(unittest.TestCase):
     """Test that we can serialize and deserialize a config.toml file"""
     def test_no_args(self):
         build = serialize_and_parse([])
-        self.assertEqual(build.get_toml("changelog-seen"), '2')
+        self.assertEqual(build.get_toml("change-id"), '115898')
         self.assertEqual(build.get_toml("profile"), 'dist')
         self.assertIsNone(build.get_toml("llvm.download-ci-llvm"))
 
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 292ccc5780f..cf1f97c5b41 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -158,6 +158,25 @@ impl Step for Std {
         target_deps.extend(copy_third_party_objects(builder, &compiler, target));
         target_deps.extend(copy_self_contained_objects(builder, &compiler, target));
 
+        // The LLD wrappers and `rust-lld` are self-contained linking components that can be
+        // necessary to link the stdlib on some targets. We'll also need to copy these binaries to
+        // the `stage0-sysroot` to ensure the linker is found when bootstrapping on such a target.
+        if compiler.stage == 0 && compiler.host == builder.config.build {
+            // We want to copy the host `bin` folder within the `rustlib` folder in the sysroot.
+            let src_sysroot_bin = builder
+                .rustc_snapshot_sysroot()
+                .join("lib")
+                .join("rustlib")
+                .join(compiler.host.triple)
+                .join("bin");
+            if src_sysroot_bin.exists() {
+                let target_sysroot_bin =
+                    builder.sysroot_libdir(compiler, target).parent().unwrap().join("bin");
+                t!(fs::create_dir_all(&target_sysroot_bin));
+                builder.cp_r(&src_sysroot_bin, &target_sysroot_bin);
+            }
+        }
+
         let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "build");
         std_cargo(builder, target, compiler.stage, &mut cargo);
         for krate in &*self.crates {
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 836328f94ef..1755c3166de 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -112,7 +112,8 @@ impl Display for DebuginfoLevel {
 /// `config.example.toml`.
 #[derive(Default, Clone)]
 pub struct Config {
-    pub changelog_seen: Option<usize>,
+    pub changelog_seen: Option<usize>, // FIXME: Deprecated field. Remove it at 2024.
+    pub change_id: Option<usize>,
     pub ccache: Option<String>,
     /// Call Build::ninja() instead of this.
     pub ninja_in_file: bool,
@@ -546,7 +547,8 @@ impl Target {
 #[derive(Deserialize, Default)]
 #[serde(deny_unknown_fields, rename_all = "kebab-case")]
 struct TomlConfig {
-    changelog_seen: Option<usize>,
+    changelog_seen: Option<usize>, // FIXME: Deprecated field. Remove it at 2024.
+    change_id: Option<usize>,
     build: Option<Build>,
     install: Option<Install>,
     llvm: Option<Llvm>,
@@ -574,7 +576,17 @@ trait Merge {
 impl Merge for TomlConfig {
     fn merge(
         &mut self,
-        TomlConfig { build, install, llvm, rust, dist, target, profile: _, changelog_seen }: Self,
+        TomlConfig {
+            build,
+            install,
+            llvm,
+            rust,
+            dist,
+            target,
+            profile: _,
+            changelog_seen,
+            change_id,
+        }: Self,
         replace: ReplaceOpt,
     ) {
         fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
@@ -587,6 +599,7 @@ impl Merge for TomlConfig {
             }
         }
         self.changelog_seen.merge(changelog_seen, replace);
+        self.change_id.merge(change_id, replace);
         do_merge(&mut self.build, build, replace);
         do_merge(&mut self.install, install, replace);
         do_merge(&mut self.llvm, llvm, replace);
@@ -1242,6 +1255,7 @@ impl Config {
         toml.merge(override_toml, ReplaceOpt::Override);
 
         config.changelog_seen = toml.changelog_seen;
+        config.change_id = toml.change_id;
 
         let build = toml.build.unwrap_or_default();
         if let Some(file_build) = build.build {
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index aac76cdcbcf..d091f33eee4 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -102,7 +102,7 @@ fn override_toml() {
         &[
             "check".to_owned(),
             "--config=/does/not/exist".to_owned(),
-            "--set=changelog-seen=1".to_owned(),
+            "--set=change-id=1".to_owned(),
             "--set=rust.lto=fat".to_owned(),
             "--set=rust.deny-warnings=false".to_owned(),
             "--set=build.gdb=\"bar\"".to_owned(),
@@ -112,7 +112,7 @@ fn override_toml() {
         |&_| {
             toml::from_str(
                 r#"
-changelog-seen = 0
+change-id = 0
 [rust]
 lto = "off"
 deny-warnings = true
@@ -129,7 +129,7 @@ build-config = {}
             .unwrap()
         },
     );
-    assert_eq!(config.changelog_seen, Some(1), "setting top-level value");
+    assert_eq!(config.change_id, Some(1), "setting top-level value");
     assert_eq!(
         config.rust_lto,
         crate::config::RustcLto::Fat,
@@ -156,10 +156,10 @@ fn override_toml_duplicate() {
         &[
             "check".to_owned(),
             "--config=/does/not/exist".to_owned(),
-            "--set=changelog-seen=1".to_owned(),
-            "--set=changelog-seen=2".to_owned(),
+            "--set=change-id=1".to_owned(),
+            "--set=change-id=2".to_owned(),
         ],
-        |&_| toml::from_str("changelog-seen = 0").unwrap(),
+        |&_| toml::from_str("change-id = 0").unwrap(),
     );
 }
 
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index 85cd8abb995..885b3a78236 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -46,10 +46,10 @@ fn sanitize_sh(path: &Path) -> String {
 }
 
 fn is_dir_writable_for_user(dir: &PathBuf) -> bool {
-    let tmp_file = dir.join(".tmp");
-    match fs::File::create(&tmp_file) {
+    let tmp = dir.join(".tmp");
+    match fs::create_dir_all(&tmp) {
         Ok(_) => {
-            fs::remove_file(tmp_file).unwrap();
+            fs::remove_dir_all(tmp).unwrap();
             true
         }
         Err(e) => {
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 8b8d4b23795..5c78015e560 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -112,7 +112,15 @@ const LLVM_TOOLS: &[&str] = &[
 /// LLD file names for all flavors.
 const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"];
 
-pub const VERSION: usize = 2;
+/// Keeps track of major changes made to the bootstrap configuration.
+///
+/// These values also represent the IDs of the PRs that caused major changes.
+/// You can visit `https://github.com/rust-lang/rust/pull/{any-id-from-the-list}` to
+/// check for more details regarding each change.
+///
+/// If you make any major changes (such as adding new values or changing default values), please
+/// ensure that the associated PR ID is added to the end of this list.
+pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898];
 
 /// Extra --check-cfg to add when building
 /// (Mode restriction, config name, config values (if any))
@@ -1844,3 +1852,16 @@ fn envify(s: &str) -> String {
         .flat_map(|c| c.to_uppercase())
         .collect()
 }
+
+pub fn find_recent_config_change_ids(current_id: usize) -> Vec<usize> {
+    let index = CONFIG_CHANGE_HISTORY
+        .iter()
+        .position(|&id| id == current_id)
+        .expect(&format!("Value `{}` was not found in `CONFIG_CHANGE_HISTORY`.", current_id));
+
+    CONFIG_CHANGE_HISTORY
+        .iter()
+        .skip(index + 1) // Skip the current_id and IDs before it
+        .cloned()
+        .collect()
+}
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index a9865e262fe..0b67079917c 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -6,6 +6,13 @@ Q := @
 BOOTSTRAP_ARGS :=
 endif
 
+# Pass `-jN` to the bootstrap if it is specified.
+ifdef MAKEFLAGS
+  ifneq (,$(findstring -j, $(MAKEFLAGS)))
+    BOOTSTRAP_ARGS += $(filter -j%, $(MAKEFLAGS))
+  endif
+endif
+
 BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py
 
 all:
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index ef0234957b5..14ec33147fb 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -1,6 +1,6 @@
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::Config;
-use crate::{t, VERSION};
+use crate::{t, CONFIG_CHANGE_HISTORY};
 use sha2::Digest;
 use std::env::consts::EXE_SUFFIX;
 use std::fmt::Write as _;
@@ -208,10 +208,11 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
         crate::exit!(1);
     }
 
+    let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap();
     let settings = format!(
         "# Includes one of the default files in src/bootstrap/defaults\n\
     profile = \"{profile}\"\n\
-    changelog-seen = {VERSION}\n"
+    change-id = {latest_change_id}\n"
     );
 
     t!(fs::write(path, settings));
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index 6f1b2a6a638..c04121a8bee 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -84,7 +84,8 @@ ENV RUST_CONFIGURE_ARGS \
       --set llvm.ninja=false \
       --set rust.jemalloc \
       --set rust.use-lld=true \
-      --set rust.lto=thin
+      --set rust.lto=thin \
+      --set rust.codegen-units=1
 
 ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \
     ./build/$HOSTS/stage0-tools-bin/opt-dist linux-ci -- python3 ../x.py dist \
diff --git a/src/ci/docker/host-x86_64/wasm32/Dockerfile b/src/ci/docker/host-x86_64/wasm32/Dockerfile
deleted file mode 100644
index 0d0f1edd003..00000000000
--- a/src/ci/docker/host-x86_64/wasm32/Dockerfile
+++ /dev/null
@@ -1,63 +0,0 @@
-FROM ubuntu:22.04
-
-ARG DEBIAN_FRONTEND=noninteractive
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
-  make \
-  ninja-build \
-  file \
-  curl \
-  ca-certificates \
-  python3 \
-  git \
-  cmake \
-  sudo \
-  gdb \
-  xz-utils \
-  libssl-dev \
-  bzip2 \
-  && rm -rf /var/lib/apt/lists/*
-
-COPY scripts/emscripten.sh /scripts/
-RUN bash /scripts/emscripten.sh
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-# emcc seems to need python to specifically be "python" and not "python3"
-RUN ln `which python3` /usr/bin/python
-
-ENV PATH=$PATH:/emsdk-portable
-ENV PATH=$PATH:/emsdk-portable/upstream/emscripten/
-
-# Rust's build system requires NodeJS to be in the path, but the directory in
-# which emsdk stores it contains the version number. This caused breakages in
-# the past when emsdk bumped the node version causing the path to point to a
-# missing directory.
-#
-# To avoid the problem this symlinks the latest NodeJs version available to
-# "latest", and adds that to the path.
-RUN ln -s /emsdk-portable/node/$(ls /emsdk-portable/node | sort -V | tail -n 1) \
-          /emsdk-portable/node/latest
-ENV PATH=$PATH:/emsdk-portable/node/latest/bin/
-
-ENV BINARYEN_ROOT=/emsdk-portable/upstream/
-ENV EMSDK=/emsdk-portable
-ENV EM_CONFIG=/emsdk-portable/.emscripten
-ENV EM_CACHE=/emsdk-portable/upstream/emscripten/cache
-
-ENV TARGETS=wasm32-unknown-emscripten
-
-# Use -O1 optimizations in the link step to reduce time spent optimizing.
-ENV EMCC_CFLAGS=-O1
-
-COPY static/gitconfig /etc/gitconfig
-
-# Emscripten installation is user-specific
-ENV NO_CHANGE_USER=1
-RUN chown 10719 -R /emsdk-portable/
-
-# Exclude library/alloc due to OOM in benches.
-# FIXME: Fix std tests
-ENV SCRIPT python3 ../x.py test --stage 2 --host='' --target $TARGETS \
-    --skip library/alloc --skip library/std
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index cbf848cb4a3..838c72612d6 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -281,6 +281,8 @@ on:
       - auto
       - try
       - try-perf
+      - automation/bors/try
+      - automation/bors/try-merge
       - master
   pull_request:
     branches:
@@ -427,9 +429,6 @@ jobs:
           - name: test-various
             <<: *job-linux-8c
 
-          - name: wasm32
-            <<: *job-linux-8c
-
           - name: x86_64-gnu
             <<: *job-linux-4c
 
@@ -691,7 +690,7 @@ jobs:
     env:
       DIST_TRY_BUILD: 1
       <<: [*shared-ci-variables, *prod-variables]
-    if: github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'
+    if: github.event_name == 'push' && (((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust') || ((github.ref == 'refs/heads/automation/bors/try') && github.repository == 'rust-lang/rust'))
     strategy:
       matrix:
         include:
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index ff831a20504..ef4eb5a1965 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -33,9 +33,9 @@ All tier 1 targets with host tools support the full standard library.
 target | notes
 -------|-------
 `aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+) [^missing-stack-probes]
-`i686-pc-windows-gnu` | 32-bit MinGW (Windows 7+) [^windows-support]
-`i686-pc-windows-msvc` | 32-bit MSVC (Windows 7+) [^windows-support]
-`i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+)
+`i686-pc-windows-gnu` | 32-bit MinGW (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI]
+`i686-pc-windows-msvc` | 32-bit MSVC (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI]
+`i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) [^x86_32-floats-return-ABI]
 `x86_64-apple-darwin` | 64-bit macOS (10.12+, Sierra+)
 `x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 7+) [^windows-support]
 `x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 7+) [^windows-support]
@@ -47,7 +47,10 @@ target | notes
 
 [^windows-support]: Only Windows 10 currently undergoes automated testing. Earlier versions of Windows rely on testing and support from the community.
 
+[^x86_32-floats-return-ABI]: Due to limitations of the C ABI, floating-point support on `i686` targets is non-compliant: floating-point return values are passed via an x87 register, so NaN payload bits can be lost. See [issue #114479][x86-32-float-issue].
+
 [77071]: https://github.com/rust-lang/rust/issues/77071
+[x86-32-float-issue]: https://github.com/rust-lang/rust/issues/114479
 
 ## Tier 1
 
@@ -150,12 +153,12 @@ target | std | notes
 `armv7r-none-eabi` | * | Bare ARMv7-R
 `armv7r-none-eabihf` | * | Bare ARMv7-R, hardfloat
 `asmjs-unknown-emscripten` | ✓ | asm.js via Emscripten
-`i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE
-`i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17)
-`i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL
-[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android
-`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD
-`i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL
+`i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE [^x86_32-floats-x87]
+`i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17) [^x86_32-floats-x87]
+`i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL [^x86_32-floats-x87]
+[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android [^x86_32-floats-return-ABI]
+`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD [^x86_32-floats-return-ABI]
+`i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL [^x86_32-floats-return-ABI]
 [`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | 32-bit UEFI
 [`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64D ABI)
 [`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64S ABI)
@@ -195,6 +198,8 @@ target | std | notes
 `x86_64-unknown-redox` | ✓ | Redox OS
 [`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | 64-bit UEFI
 
+[^x86_32-floats-x87]: Floating-point support on `i586` targets is non-compliant: the `x87` registers and instructions used for these targets do not provide IEEE-754-compliant behavior, in particular when it comes to rounding and NaN payload bits. See [issue #114479][x86-32-float-issue].
+
 [Fortanix ABI]: https://edp.fortanix.com/
 
 ## Tier 3
@@ -264,18 +269,18 @@ target | std | host | notes
 `bpfel-unknown-none` | * |  | BPF (little endian)
 `csky-unknown-linux-gnuabiv2` | ✓ |  | C-SKY abiv2 Linux(little endian)
 `hexagon-unknown-linux-musl` | ? |  |
-`i386-apple-ios` | ✓ |  | 32-bit x86 iOS
-[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * |  | 32-bit x86 QNX Neutrino 7.0 RTOS |
-`i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+)
-`i686-pc-windows-msvc` | * |  | 32-bit Windows XP support
-[`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
-`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku
-[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd
-[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2
-[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD
-`i686-uwp-windows-gnu` | ? |  |
-`i686-uwp-windows-msvc` | ? |  |
-`i686-wrs-vxworks` | ? |  |
+`i386-apple-ios` | ✓ |  | 32-bit x86 iOS [^x86_32-floats-return-ABI]
+[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * |  | 32-bit x86 QNX Neutrino 7.0 RTOS  [^x86_32-floats-return-ABI]
+`i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+) [^x86_32-floats-return-ABI]
+`i686-pc-windows-msvc` | * |  | 32-bit Windows XP support [^x86_32-floats-return-ABI]
+[`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | [^x86_32-floats-return-ABI]
+`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku [^x86_32-floats-return-ABI]
+[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd [^x86_32-floats-return-ABI]
+[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2 [^x86_32-floats-return-ABI]
+[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD [^x86_32-floats-return-ABI]
+`i686-uwp-windows-gnu` | ? |  | [^x86_32-floats-return-ABI]
+`i686-uwp-windows-msvc` | ? |  | [^x86_32-floats-return-ABI]
+`i686-wrs-vxworks` | ? |  | [^x86_32-floats-return-ABI]
 [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? |  | Motorola 680x0 Linux
 `mips-unknown-linux-uclibc` | ✓ |  | MIPS Linux with uClibc
 [`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? |  | MIPS64 for OpenWrt Linux MUSL
diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md
index f8cd92f9257..9233a36db3d 100644
--- a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md
+++ b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md
@@ -58,7 +58,7 @@ To build a rust toolchain, create a `config.toml` with the following contents:
 
 ```toml
 profile = "compiler"
-changelog-seen = 2
+change-id = 115898
 
 [build]
 sanitizers = true
diff --git a/src/doc/rustc/src/platform-support/mips-release-6.md b/src/doc/rustc/src/platform-support/mips-release-6.md
index 3f1912fc6f9..9203a31e9f4 100644
--- a/src/doc/rustc/src/platform-support/mips-release-6.md
+++ b/src/doc/rustc/src/platform-support/mips-release-6.md
@@ -67,7 +67,7 @@ The following procedure outlines the build process for the MIPS64 R6 target with
 
 ### Prerequisite: Disable debuginfo
 
-A LLVM bug makes rustc crash if debug or debug info generation is enabled. You need to edit `config.toml` to disable this:
+An LLVM bug makes rustc crash if debug or debug info generation is enabled. You need to edit `config.toml` to disable this:
 
 ```toml
 [rust]
diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md
index b376c4a84ac..9f0662783a4 100644
--- a/src/doc/rustc/src/platform-support/nto-qnx.md
+++ b/src/doc/rustc/src/platform-support/nto-qnx.md
@@ -98,7 +98,7 @@ Example content:
 
 ```toml
 profile = "compiler"
-changelog-seen = 2
+change-id = 115898
 ```
 
 2. Compile the Rust toolchain for an `x86_64-unknown-linux-gnu` host (for both `aarch64` and `x86_64` targets)
diff --git a/src/doc/rustc/src/platform-support/openharmony.md b/src/doc/rustc/src/platform-support/openharmony.md
index 89539f3888c..05fd407ed71 100644
--- a/src/doc/rustc/src/platform-support/openharmony.md
+++ b/src/doc/rustc/src/platform-support/openharmony.md
@@ -101,7 +101,7 @@ To build a rust toolchain, create a `config.toml` with the following contents:
 
 ```toml
 profile = "compiler"
-changelog-seen = 2
+change-id = 115898
 
 [build]
 sanitizers = true
diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md
index 68cd7fae319..370939520dc 100644
--- a/src/doc/rustc/src/platform-support/unknown-uefi.md
+++ b/src/doc/rustc/src/platform-support/unknown-uefi.md
@@ -265,9 +265,12 @@ cargo build --target x86_64-unknown-uefi -Zbuild-std=std,panic_abort
 #### os_str
 - While the strings in UEFI should be valid UCS-2, in practice, many implementations just do not care and use UTF-16 strings.
 - Thus, the current implementation supports full UTF-16 strings.
+#### stdio
+- Uses `Simple Text Input Protocol` and `Simple Text Output Protocol`.
+- Note: UEFI uses CRLF for new line. This means Enter key is registered as CR instead of LF.
 
 ## Example: Hello World With std
-The following code features a valid UEFI application, including stdio and `alloc` (`OsString` and `Vec`):
+The following code features a valid UEFI application, including `stdio` and `alloc` (`OsString` and `Vec`):
 
 This example can be compiled as binary crate via `cargo` using the toolchain
 compiled from the above source (named custom):
@@ -286,6 +289,9 @@ use std::{
 };
 
 pub fn main() {
+  println!("Starting Rust Application...");
+
+  // Use System Table Directly
   let st = env::system_table().as_ptr() as *mut efi::SystemTable;
   let mut s: Vec<u16> = OsString::from("Hello World!\n").encode_wide().collect();
   s.push(0);
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index 49389b28c8f..502853f39ae 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -197,22 +197,26 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
 
 # ControlFlowIntegrity
 
-The LLVM Control Flow Integrity (CFI) support in the Rust compiler provides
-forward-edge control flow protection for both Rust-compiled code only and for C
-or C++ and Rust -compiled code mixed-language binaries, also known as “mixed
-binaries” (i.e., for when C or C++ and Rust -compiled code share the same
-virtual address space), by aggregating function pointers in groups identified by
-their return and parameter types.
-
-LLVM CFI can be enabled with `-Zsanitizer=cfi` and requires LTO (i.e., `-Clto`).
-Cross-language LLVM CFI can be enabled with `-Zsanitizer=cfi`, and requires the
-`-Zsanitizer-cfi-normalize-integers` option to be used with Clang
-`-fsanitize-cfi-icall-normalize-integers` for normalizing integer types, and
-proper (i.e., non-rustc) LTO (i.e., `-Clinker-plugin-lto`).
+The LLVM CFI support in the Rust compiler provides forward-edge control flow
+protection for both Rust-compiled code only and for C or C++ and Rust -compiled
+code mixed-language binaries, also known as “mixed binaries” (i.e., for when C
+or C++ and Rust -compiled code share the same virtual address space), by
+aggregating function pointers in groups identified by their return and parameter
+types.
+
+LLVM CFI can be enabled with `-Zsanitizer=cfi` and requires LTO (i.e.,
+`-Clinker-plugin-lto` or `-Clto`). Cross-language LLVM CFI can be enabled with
+`-Zsanitizer=cfi`, and requires the `-Zsanitizer-cfi-normalize-integers` option
+to be used with Clang `-fsanitize-cfi-icall-experimental-normalize-integers`
+option for cross-language LLVM CFI support, and proper (i.e., non-rustc) LTO
+(i.e., `-Clinker-plugin-lto`).
+
+It is recommended to rebuild the standard library with CFI enabled by using the
+Cargo build-std feature (i.e., `-Zbuild-std`) when enabling CFI.
 
 See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details.
 
-## Example
+## Example 1: Redirecting control flow using an indirect branch/call to an invalid destination
 
 ```rust,ignore (making doc tests pass cross-platform is hard)
 #![feature(naked_functions)]
@@ -239,7 +243,7 @@ pub extern "C" fn add_two(x: i32) {
              nop
              nop
              nop
-             lea eax, [edi+2]
+             lea eax, [rdi+2]
              ret
         ",
             options(noreturn)
@@ -258,8 +262,9 @@ fn main() {
 
     println!("With CFI enabled, you should not see the next answer");
     let f: fn(i32) -> i32 = unsafe {
-        // Offsets 0-8 make it land in the landing pad/nop block, and offsets 1-8 are
-        // invalid branch/call destinations (i.e., within the body of the function).
+        // Offset 0 is a valid branch/call destination (i.e., the function entry
+        // point), but offsets 1-8 within the landing pad/nop block are invalid
+        // branch/call destinations (i.e., within the body of the function).
         mem::transmute::<*const u8, fn(i32) -> i32>((add_two as *const u8).offset(5))
     };
     let next_answer = do_twice(f, 5);
@@ -267,38 +272,40 @@ fn main() {
     println!("The next answer is: {}", next_answer);
 }
 ```
-Fig. 1. Modified example from the [Advanced Functions and
-Closures][rust-book-ch19-05] chapter of the [The Rust Programming
-Language][rust-book] book.
+Fig. 1. Redirecting control flow using an indirect branch/call to an invalid
+destination (i.e., within the body of the function).
 
 ```shell
 $ cargo run --release
    Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
-    Finished release [optimized] target(s) in 0.76s
+    Finished release [optimized] target(s) in 0.42s
      Running `target/release/rust-cfi-1`
 The answer is: 12
 With CFI enabled, you should not see the next answer
 The next answer is: 14
 $
 ```
-Fig. 2. Build and execution of the modified example with LLVM CFI disabled.
+Fig. 2. Build and execution of Fig. 1 with LLVM CFI disabled.
 
 ```shell
-$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
+$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu
+   ...
    Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
-    Finished release [optimized] target(s) in 3.39s
-     Running `target/release/rust-cfi-1`
+    Finished release [optimized] target(s) in 1m 08s
+     Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-1`
 The answer is: 12
 With CFI enabled, you should not see the next answer
 Illegal instruction
 $
 ```
-Fig. 3. Build and execution of the modified example with LLVM CFI enabled.
+Fig. 3. Build and execution of Fig. 1 with LLVM CFI enabled.
 
 When LLVM CFI is enabled, if there are any attempts to change/hijack control
 flow using an indirect branch/call to an invalid destination, the execution is
 terminated (see Fig. 3).
 
+## Example 2: Redirecting control flow using an indirect branch/call to a function with a different number of parameters
+
 ```rust
 use std::mem;
 
@@ -327,39 +334,42 @@ fn main() {
     println!("The next answer is: {}", next_answer);
 }
 ```
-Fig. 4. Another modified example from the [Advanced Functions and
-Closures][rust-book-ch19-05] chapter of the [The Rust Programming
-Language][rust-book] book.
+Fig. 4. Redirecting control flow using an indirect branch/call to a function
+with a different number of parameters than arguments intended/passed in the
+call/branch site.
 
 ```shell
 $ cargo run --release
    Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
-    Finished release [optimized] target(s) in 0.76s
+    Finished release [optimized] target(s) in 0.43s
      Running `target/release/rust-cfi-2`
 The answer is: 12
 With CFI enabled, you should not see the next answer
 The next answer is: 14
 $
 ```
-Fig. 5. Build and execution of the modified example with LLVM CFI disabled.
+Fig. 5. Build and execution of Fig. 4 with LLVM CFI disabled.
 
 ```shell
-$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release
+$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu
+   ...
    Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
-    Finished release [optimized] target(s) in 3.38s
-     Running `target/release/rust-cfi-2`
+    Finished release [optimized] target(s) in 1m 08s
+     Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-2`
 The answer is: 12
 With CFI enabled, you should not see the next answer
 Illegal instruction
 $
 ```
-Fig. 6. Build and execution of the modified example with LLVM CFI enabled.
+Fig. 6. Build and execution of Fig. 4 with LLVM CFI enabled.
 
 When LLVM CFI is enabled, if there are any attempts to change/hijack control
 flow using an indirect branch/call to a function with different number of
 parameters than arguments intended/passed in the call/branch site, the
 execution is also terminated (see Fig. 6).
 
+## Example 3: Redirecting control flow using an indirect branch/call to a function with different return and parameter types
+
 ```rust
 use std::mem;
 
@@ -388,42 +398,46 @@ fn main() {
     println!("The next answer is: {}", next_answer);
 }
 ```
-Fig. 7. Another modified example from the [Advanced Functions and
-Closures][rust-book-ch19-05] chapter of the [The Rust Programming
-Language][rust-book] book.
+Fig. 7. Redirecting control flow using an indirect branch/call to a function
+with different return and parameter types than the return type expected and
+arguments intended/passed at the call/branch site.
 
 ```shell
 $ cargo run --release
    Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
-    Finished release [optimized] target(s) in 0.74s
+    Finished release [optimized] target(s) in 0.44s
      Running `target/release/rust-cfi-3`
 The answer is: 12
 With CFI enabled, you should not see the next answer
 The next answer is: 14
 $
 ```
-Fig. 8. Build and execution of the modified example with LLVM CFI disabled.
+Fig. 8. Build and execution of Fig. 7 with LLVM CFI disabled.
 
 ```shell
-$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release
+$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu
+   ...
    Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
-    Finished release [optimized] target(s) in 3.40s
-     Running `target/release/rust-cfi-3`
+    Finished release [optimized] target(s) in 1m 07s
+     Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-3`
 The answer is: 12
 With CFI enabled, you should not see the next answer
 Illegal instruction
 $
 ```
-Fig. 9. Build and execution of the modified example with LLVM CFI enabled.
+Fig. 9. Build and execution of Fig. 7 with LLVM CFI enabled.
 
 When LLVM CFI is enabled, if there are any attempts to change/hijack control
 flow using an indirect branch/call to a function with different return and
 parameter types than the return type expected and arguments intended/passed in
 the call/branch site, the execution is also terminated (see Fig. 9).
 
+## Example 4: Redirecting control flow using an indirect branch/call to a function with different return and parameter types across the FFI boundary
+
 ```ignore (cannot-test-this-because-uses-custom-build)
 int
-do_twice(int (*fn)(int), int arg) {
+do_twice(int (*fn)(int), int arg)
+{
     return fn(arg) + fn(arg);
 }
 ```
@@ -459,54 +473,49 @@ fn main() {
     println!("The next answer is: {}", next_answer);
 }
 ```
-Fig. 11. Another modified example from the [Advanced Functions and
-Closures][rust-book-ch19-05] chapter of the [The Rust Programming
-Language][rust-book] book.
+Fig. 11. Redirecting control flow using an indirect branch/call to a function
+with different return and parameter types than the return type expected and
+arguments intended/passed in the call/branch site, across the FFI boundary.
 
 ```shell
 $ make
-mkdir -p target/debug
-clang -I. -Isrc -Wall -flto -fvisibility=hidden -c -emit-llvm src/foo.c -o target/debug/libfoo.bc
-llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc
-RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build
-   Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1)
-    Finished dev [unoptimized + debuginfo] target(s) in 0.45s
-$ ./target/debug/main
+mkdir -p target/release
+clang -I. -Isrc -Wall -c src/foo.c -o target/release/libfoo.o
+llvm-ar rcs target/release/libfoo.a target/release/libfoo.o
+RUSTFLAGS="-L./target/release -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build --release
+   Compiling rust-cfi-4 v0.1.0 (/home/rcvalle/rust-cfi-4)
+    Finished release [optimized] target(s) in 0.49s
+$ ./target/release/rust-cfi-4
 The answer is: 12
 With CFI enabled, you should not see the next answer
 The next answer is: 14
 $
 ```
-Fig. 12. Build and execution of the modified example with LLVM CFI disabled.
+Fig. 12. Build and execution of Figs. 10–11 with LLVM CFI disabled.
 
 ```shell
 $ make
-mkdir -p target/debug
-clang -I. -Isrc -Wall -flto -fvisibility=hidden -fsanitize=cfi -fsanitize-cfi-icall-normalize-integers -c -emit-llvm src/foo.c -o target/debug/libfoo.bc
-llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc
-RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers" cargo build
-   Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1)
-    Finished dev [unoptimized + debuginfo] target(s) in 0.45s
-$ ./target/debug/main
+mkdir -p target/release
+clang -I. -Isrc -Wall -flto -fsanitize=cfi -fsanitize-cfi-icall-experimental-normalize-integers -fvisibility=hidden -c -emit-llvm src/foo.c -o target/release/libfoo.bc
+llvm-ar rcs target/release/libfoo.a target/release/libfoo.bc
+RUSTFLAGS="-L./target/release -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers" cargo build -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu
+   ...
+   Compiling rust-cfi-4 v0.1.0 (/home/rcvalle/rust-cfi-4)
+    Finished release [optimized] target(s) in 1m 06s
+$ ./target/x86_64-unknown-linux-gnu/release/rust-cfi-4
 The answer is: 12
 With CFI enabled, you should not see the next answer
 Illegal instruction
 $
 ```
-Fig. 13. Build and execution of the modified example with LLVM CFI enabled.
-
-When LLVM CFI is enabled, if there are any attempts to change/hijack control
-flow using an indirect branch/call to a function with different return and
-parameter types than the return type expected and arguments intended/passed in
-the call/branch site, even across the FFI boundary and for extern "C" function
-types indirectly called (i.e., callbacks/function pointers) across the FFI
-boundary, in C or C++ and Rust -compiled code mixed-language binaries, also
-known as “mixed binaries” (i.e., for when C or C++ and Rust -compiled code share
-the same virtual address space), the execution is also terminated (see Fig. 13).
-
-
-[rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html
-[rust-book]: https://doc.rust-lang.org/book/title-page.html
+Fig. 13. Build and execution of FIgs. 10–11 with LLVM CFI enabled.
+
+When LLVM CFI is enabled, if there are any attempts to redirect control flow
+using an indirect branch/call to a function with different return and parameter
+types than the return type expected and arguments intended/passed in the
+call/branch site, even across the FFI boundary and for extern "C" function types
+indirectly called (i.e., callbacks/function pointers) across the FFI boundary,
+the execution is also terminated (see Fig. 13).
 
 # HWAddressSanitizer
 
diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md
index 189cc910a8d..d9421a428f1 100644
--- a/src/doc/unstable-book/src/language-features/plugin.md
+++ b/src/doc/unstable-book/src/language-features/plugin.md
@@ -33,7 +33,7 @@ of a library.
 Plugins can extend [Rust's lint
 infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with
 additional checks for code style, safety, etc. Now let's write a plugin
-[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/tests/ui-fulldeps/auxiliary/lint-plugin-test.rs)
+[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs)
 that warns about any item named `lintme`.
 
 ```rust,ignore (requires-stage-2)
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index a06f31a9329..bdf6a0f6b23 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -551,8 +551,8 @@ where
                 WherePredicate::RegionPredicate { lifetime, bounds } => {
                     lifetime_to_bounds.entry(lifetime).or_default().extend(bounds);
                 }
-                WherePredicate::EqPredicate { lhs, rhs, bound_params } => {
-                    match *lhs {
+                WherePredicate::EqPredicate { lhs, rhs } => {
+                    match lhs {
                         Type::QPath(box QPathData {
                             ref assoc,
                             ref self_type,
@@ -590,14 +590,13 @@ where
                                 GenericArgs::AngleBracketed { ref mut bindings, .. } => {
                                     bindings.push(TypeBinding {
                                         assoc: assoc.clone(),
-                                        kind: TypeBindingKind::Equality { term: *rhs },
+                                        kind: TypeBindingKind::Equality { term: rhs },
                                     });
                                 }
                                 GenericArgs::Parenthesized { .. } => {
                                     existing_predicates.push(WherePredicate::EqPredicate {
                                         lhs: lhs.clone(),
                                         rhs,
-                                        bound_params,
                                     });
                                     continue; // If something other than a Fn ends up
                                     // with parentheses, leave it alone
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index fcbcfbf5c67..eb18ecf662c 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -18,9 +18,9 @@ use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
 
 use crate::clean::{
-    self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_assoc_item,
-    clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty,
-    clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes,
+    self, clean_bound_vars, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item,
+    clean_middle_assoc_item, clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings,
+    clean_ty, clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes,
     AttributesExt, ImplKind, ItemId, Type,
 };
 use crate::core::DocContext;
@@ -239,20 +239,13 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
 
 fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box<clean::Function> {
     let sig = cx.tcx.fn_sig(did).instantiate_identity();
-
-    let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
-        ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => {
-            Some(clean::GenericParamDef::lifetime(name))
-        }
-        _ => None,
-    });
-
     let predicates = cx.tcx.explicit_predicates_of(did);
+
     let (generics, decl) = clean::enter_impl_trait(cx, |cx| {
         // NOTE: generics need to be cleaned before the decl!
         let mut generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
         // FIXME: This does not place parameters in source order (late-bound ones come last)
-        generics.params.extend(late_bound_regions);
+        generics.params.extend(clean_bound_vars(sig.bound_vars()));
         let decl = clean_fn_decl_from_did_and_sig(cx, Some(did), sig);
         (generics, decl)
     });
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 5a1612e76e3..b9d7acee63c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -232,20 +232,11 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
     poly_trait_ref: ty::PolyTraitRef<'tcx>,
     bindings: ThinVec<TypeBinding>,
 ) -> GenericBound {
-    // collect any late bound regions
-    let late_bound_regions: Vec<_> = cx
-        .tcx
-        .collect_referenced_late_bound_regions(&poly_trait_ref)
-        .into_iter()
-        .filter_map(|br| match br {
-            ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)),
-            _ => None,
-        })
-        .collect();
-
-    let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings);
     GenericBound::TraitBound(
-        PolyTrait { trait_, generic_params: late_bound_regions },
+        PolyTrait {
+            trait_: clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings),
+            generic_params: clean_bound_vars(poly_trait_ref.bound_vars()),
+        },
         hir::TraitBoundModifier::None,
     )
 }
@@ -338,9 +329,8 @@ fn clean_where_predicate<'tcx>(
         },
 
         hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
-            lhs: Box::new(clean_ty(wrp.lhs_ty, cx)),
-            rhs: Box::new(clean_ty(wrp.rhs_ty, cx).into()),
-            bound_params: Vec::new(),
+            lhs: clean_ty(wrp.lhs_ty, cx),
+            rhs: clean_ty(wrp.rhs_ty, cx).into(),
         },
     })
 }
@@ -436,20 +426,9 @@ fn clean_projection_predicate<'tcx>(
     pred: ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>,
     cx: &mut DocContext<'tcx>,
 ) -> WherePredicate {
-    let late_bound_regions = cx
-        .tcx
-        .collect_referenced_late_bound_regions(&pred)
-        .into_iter()
-        .filter_map(|br| match br {
-            ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)),
-            _ => None,
-        })
-        .collect();
-
     WherePredicate::EqPredicate {
-        lhs: Box::new(clean_projection(pred.map_bound(|p| p.projection_ty), cx, None)),
-        rhs: Box::new(clean_middle_term(pred.map_bound(|p| p.term), cx)),
-        bound_params: late_bound_regions,
+        lhs: clean_projection(pred.map_bound(|p| p.projection_ty), cx, None),
+        rhs: clean_middle_term(pred.map_bound(|p| p.term), cx),
     }
 }
 
@@ -703,8 +682,8 @@ pub(crate) fn clean_generics<'tcx>(
                     }
                 }
             }
-            WherePredicate::EqPredicate { lhs, rhs, bound_params } => {
-                eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs, bound_params });
+            WherePredicate::EqPredicate { lhs, rhs } => {
+                eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs });
             }
         }
     }
@@ -798,11 +777,9 @@ fn clean_ty_generics<'tcx>(
         })
         .collect::<ThinVec<GenericParamDef>>();
 
-    // param index -> [(trait DefId, associated type name & generics, term, higher-ranked params)]
-    let mut impl_trait_proj = FxHashMap::<
-        u32,
-        Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>, Vec<GenericParamDef>)>,
-    >::default();
+    // param index -> [(trait DefId, associated type name & generics, term)]
+    let mut impl_trait_proj =
+        FxHashMap::<u32, Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>)>>::default();
 
     let where_predicates = preds
         .predicates
@@ -854,11 +831,6 @@ fn clean_ty_generics<'tcx>(
                         trait_did,
                         name,
                         proj.map_bound(|p| p.term),
-                        pred.get_bound_params()
-                            .into_iter()
-                            .flatten()
-                            .cloned()
-                            .collect(),
                     ));
                 }
 
@@ -894,9 +866,9 @@ fn clean_ty_generics<'tcx>(
 
         let crate::core::ImplTraitParam::ParamIndex(idx) = param else { unreachable!() };
         if let Some(proj) = impl_trait_proj.remove(&idx) {
-            for (trait_did, name, rhs, bound_params) in proj {
+            for (trait_did, name, rhs) in proj {
                 let rhs = clean_middle_term(rhs, cx);
-                simplify::merge_bounds(cx, &mut bounds, bound_params, trait_did, name, &rhs);
+                simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs);
             }
         }
 
@@ -1363,23 +1335,13 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
         }
         ty::AssocKind::Fn => {
             let sig = tcx.fn_sig(assoc_item.def_id).instantiate_identity();
-
-            let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
-                ty::BoundVariableKind::Region(ty::BrNamed(_, name))
-                    if name != kw::UnderscoreLifetime =>
-                {
-                    Some(GenericParamDef::lifetime(name))
-                }
-                _ => None,
-            });
-
             let mut generics = clean_ty_generics(
                 cx,
                 tcx.generics_of(assoc_item.def_id),
                 tcx.explicit_predicates_of(assoc_item.def_id),
             );
             // FIXME: This does not place parameters in source order (late-bound ones come last)
-            generics.params.extend(late_bound_regions);
+            generics.params.extend(clean_bound_vars(sig.bound_vars()));
 
             let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(assoc_item.def_id), sig);
 
@@ -2115,9 +2077,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
             // FIXME: should we merge the outer and inner binders somehow?
             let sig = bound_ty.skip_binder().fn_sig(cx.tcx);
             let decl = clean_fn_decl_from_did_and_sig(cx, None, sig);
+            let generic_params = clean_bound_vars(sig.bound_vars());
+
             BareFunction(Box::new(BareFunctionDecl {
                 unsafety: sig.unsafety(),
-                generic_params: Vec::new(),
+                generic_params,
                 decl,
                 abi: sig.abi(),
             }))
@@ -2193,8 +2157,8 @@ pub(crate) fn clean_middle_ty<'tcx>(
 
             let late_bound_regions: FxIndexSet<_> = obj
                 .iter()
-                .flat_map(|pb| pb.bound_vars())
-                .filter_map(|br| match br {
+                .flat_map(|pred| pred.bound_vars())
+                .filter_map(|var| match var {
                     ty::BoundVariableKind::Region(ty::BrNamed(_, name))
                         if name != kw::UnderscoreLifetime =>
                     {
@@ -2268,6 +2232,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
             }
         }
 
+        ty::Bound(_, ref ty) => match ty.kind {
+            ty::BoundTyKind::Param(_, name) => Generic(name),
+            ty::BoundTyKind::Anon => panic!("unexpected anonymous bound type variable"),
+        },
+
         ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
             // If it's already in the same alias, don't get an infinite loop.
             if cx.current_type_aliases.contains_key(&def_id) {
@@ -2296,7 +2265,6 @@ pub(crate) fn clean_middle_ty<'tcx>(
 
         ty::Closure(..) => panic!("Closure"),
         ty::Generator(..) => panic!("Generator"),
-        ty::Bound(..) => panic!("Bound"),
         ty::Placeholder(..) => panic!("Placeholder"),
         ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
         ty::Infer(..) => panic!("Infer"),
@@ -3127,3 +3095,30 @@ fn clean_type_binding<'tcx>(
         },
     }
 }
+
+fn clean_bound_vars<'tcx>(
+    bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
+) -> Vec<GenericParamDef> {
+    bound_vars
+        .into_iter()
+        .filter_map(|var| match var {
+            ty::BoundVariableKind::Region(ty::BrNamed(_, name))
+                if name != kw::UnderscoreLifetime =>
+            {
+                Some(GenericParamDef::lifetime(name))
+            }
+            ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(did, name)) => Some(GenericParamDef {
+                name,
+                kind: GenericParamDefKind::Type {
+                    did,
+                    bounds: Vec::new(),
+                    default: None,
+                    synthetic: false,
+                },
+            }),
+            // FIXME(non_lifetime_binders): Support higher-ranked const parameters.
+            ty::BoundVariableKind::Const => None,
+            _ => None,
+        })
+        .collect()
+}
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 7b8f20326ed..eea8c1906c5 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -40,18 +40,18 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP
             WP::RegionPredicate { lifetime, bounds } => {
                 lifetimes.push((lifetime, bounds));
             }
-            WP::EqPredicate { lhs, rhs, bound_params } => equalities.push((lhs, rhs, bound_params)),
+            WP::EqPredicate { lhs, rhs } => equalities.push((lhs, rhs)),
         }
     }
 
     // Look for equality predicates on associated types that can be merged into
     // general bound predicates.
-    equalities.retain(|(lhs, rhs, bound_params)| {
+    equalities.retain(|(lhs, rhs)| {
         let Some((ty, trait_did, name)) = lhs.projection() else {
             return true;
         };
         let Some((bounds, _)) = tybounds.get_mut(ty) else { return true };
-        merge_bounds(cx, bounds, bound_params.clone(), trait_did, name, rhs)
+        merge_bounds(cx, bounds, trait_did, name, rhs)
     });
 
     // And finally, let's reassemble everything
@@ -64,18 +64,13 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP
         bounds,
         bound_params,
     }));
-    clauses.extend(equalities.into_iter().map(|(lhs, rhs, bound_params)| WP::EqPredicate {
-        lhs,
-        rhs,
-        bound_params,
-    }));
+    clauses.extend(equalities.into_iter().map(|(lhs, rhs)| WP::EqPredicate { lhs, rhs }));
     clauses
 }
 
 pub(crate) fn merge_bounds(
     cx: &clean::DocContext<'_>,
     bounds: &mut Vec<clean::GenericBound>,
-    mut bound_params: Vec<clean::GenericParamDef>,
     trait_did: DefId,
     assoc: clean::PathSegment,
     rhs: &clean::Term,
@@ -93,12 +88,6 @@ pub(crate) fn merge_bounds(
         }
         let last = trait_ref.trait_.segments.last_mut().expect("segments were empty");
 
-        trait_ref.generic_params.append(&mut bound_params);
-        // Sort parameters (likely) originating from a hashset alphabetically to
-        // produce predictable output (and to allow for full deduplication).
-        trait_ref.generic_params.sort_unstable_by(|p, q| p.name.as_str().cmp(q.name.as_str()));
-        trait_ref.generic_params.dedup_by_key(|p| p.name);
-
         match last.args {
             PP::AngleBracketed { ref mut bindings, .. } => {
                 bindings.push(clean::TypeBinding {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 1d8fa2e636e..b891dc59cb1 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1289,7 +1289,7 @@ impl Lifetime {
 pub(crate) enum WherePredicate {
     BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
     RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
-    EqPredicate { lhs: Box<Type>, rhs: Box<Term>, bound_params: Vec<GenericParamDef> },
+    EqPredicate { lhs: Type, rhs: Term },
 }
 
 impl WherePredicate {
@@ -1300,15 +1300,6 @@ impl WherePredicate {
             _ => None,
         }
     }
-
-    pub(crate) fn get_bound_params(&self) -> Option<&[GenericParamDef]> {
-        match self {
-            Self::BoundPredicate { bound_params, .. } | Self::EqPredicate { bound_params, .. } => {
-                Some(bound_params)
-            }
-            _ => None,
-        }
-    }
 }
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 170e559e698..1983bb11e5b 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -326,8 +326,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
                         bounds_display.truncate(bounds_display.len() - " + ".len());
                         write!(f, "{}: {bounds_display}", lifetime.print())
                     }
-                    // FIXME(fmease): Render bound params.
-                    clean::WherePredicate::EqPredicate { lhs, rhs, bound_params: _ } => {
+                    clean::WherePredicate::EqPredicate { lhs, rhs } => {
                         if f.alternate() {
                             write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx))
                         } else {
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 2f0cae0a48e..7a282a99e9c 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -1555,7 +1555,7 @@ function initSearch(rawSearchIndex) {
                         return false;
                     }
                 }
-            } else if (fnType.id !== null) {
+            } else {
                 if (queryElem.id === typeNameIdOfArrayOrSlice &&
                     (fnType.id === typeNameIdOfSlice || fnType.id === typeNameIdOfArray)
                 ) {
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 08865015960..472cde51be5 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -506,9 +506,8 @@ impl FromWithTcx<clean::WherePredicate> for WherePredicate {
                 lifetime: convert_lifetime(lifetime),
                 bounds: bounds.into_tcx(tcx),
             },
-            // FIXME(fmease): Convert bound parameters as well.
-            EqPredicate { lhs, rhs, bound_params: _ } => {
-                WherePredicate::EqPredicate { lhs: (*lhs).into_tcx(tcx), rhs: (*rhs).into_tcx(tcx) }
+            EqPredicate { lhs, rhs } => {
+                WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) }
             }
         }
     }
diff --git a/src/tools/build_helper/src/ci.rs b/src/tools/build_helper/src/ci.rs
index a8505ec9596..09489b0d9b7 100644
--- a/src/tools/build_helper/src/ci.rs
+++ b/src/tools/build_helper/src/ci.rs
@@ -82,15 +82,15 @@ pub mod gha {
 
     fn start_group(name: impl std::fmt::Display) {
         if is_in_gha() {
-            eprintln!("::group::{name}");
+            println!("::group::{name}");
         } else {
-            eprintln!("{name}")
+            println!("{name}")
         }
     }
 
     fn end_group() {
         if is_in_gha() {
-            eprintln!("::endgroup::");
+            println!("::endgroup::");
         }
     }
 
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 59596f0f31a94fde48b5aa7e945cd0b7ceca962
+Subproject 794d0a82547f3081044c0aca7b6083733ce5134
diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
index 7dd808a7b3b..accff9b0a34 100644
--- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
+++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
@@ -287,5 +287,5 @@ fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool {
 }
 
 fn is_refcell_ref(cx: &LateContext<'_>, def_id: DefId) -> bool {
-    match_def_path(cx, def_id, &paths::REFCELL_REF) || match_def_path(cx, def_id, &paths::REFCELL_REFMUT)
+    matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::RefCellRef | sym::RefCellRefMut))
 }
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
index fa9c525fc08..3f1ff66b8cf 100644
--- a/src/tools/clippy/clippy_lints/src/box_default.rs
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -1,10 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::macros::macro_backtrace;
 use clippy_utils::ty::expr_sig;
-use clippy_utils::{get_parent_node, is_default_equivalent, match_path, path_def_id, paths};
+use clippy_utils::{get_parent_node, is_default_equivalent, path_def_id};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_ty, Visitor};
-use rustc_hir::{Block, Expr, ExprKind, Local, Node, QPath, TyKind};
+use rustc_hir::{def::Res, Block, Expr, ExprKind, Local, Node, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
@@ -55,7 +55,7 @@ impl LateLintPass<'_> for BoxDefault {
                 expr.span,
                 "`Box::new(_)` of default value",
                 "try",
-                if is_plain_default(arg_path) || given_type(cx, expr) {
+                if is_plain_default(cx, arg_path) || given_type(cx, expr) {
                     "Box::default()".into()
                 } else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) {
                     with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
@@ -68,11 +68,13 @@ impl LateLintPass<'_> for BoxDefault {
     }
 }
 
-fn is_plain_default(arg_path: &Expr<'_>) -> bool {
+fn is_plain_default(cx: &LateContext<'_>, arg_path: &Expr<'_>) -> bool {
     // we need to match the actual path so we don't match e.g. "u8::default"
-    if let ExprKind::Path(QPath::Resolved(None, path)) = &arg_path.kind {
+    if let ExprKind::Path(QPath::Resolved(None, path)) = &arg_path.kind
+        && let Res::Def(_, def_id) = path.res
+    {
         // avoid generic parameters
-        match_path(path, &paths::DEFAULT_TRAIT_METHOD) && path.segments.iter().all(|seg| seg.args.is_none())
+        cx.tcx.is_diagnostic_item(sym::default_fn, def_id) && path.segments.iter().all(|seg| seg.args.is_none())
     } else {
         false
     }
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
index 1de69122101..9e8ef282537 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::is_c_void;
-use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, match_any_def_paths, paths};
+use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant};
 use rustc_hir::{Expr, ExprKind, GenericArg};
 use rustc_lint::LateContext;
 use rustc_middle::ty::layout::LayoutOf;
@@ -75,16 +75,17 @@ fn is_used_as_unaligned(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
             }
         },
         ExprKind::Call(func, [arg, ..]) if arg.hir_id == e.hir_id => {
-            static PATHS: &[&[&str]] = &[
-                paths::PTR_READ_UNALIGNED.as_slice(),
-                paths::PTR_UNALIGNED_VOLATILE_LOAD.as_slice(),
-                paths::PTR_UNALIGNED_VOLATILE_STORE.as_slice(),
-            ];
-
             if let ExprKind::Path(path) = &func.kind
                 && let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
-                && (match_any_def_paths(cx, def_id, PATHS).is_some()
-                    || cx.tcx.is_diagnostic_item(sym::ptr_write_unaligned, def_id))
+                && matches!(
+                    cx.tcx.get_diagnostic_name(def_id),
+                    Some(
+                        sym::ptr_write_unaligned
+                        | sym::ptr_read_unaligned
+                        | sym::intrinsics_unaligned_volatile_load
+                        | sym::intrinsics_unaligned_volatile_store
+                    )
+                )
             {
                 true
             } else {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs
index 5e0123842b0..eb0f75b2f60 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs
@@ -1,13 +1,13 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_context;
-use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
+use rustc_span::sym;
 
 use super::CAST_SLICE_FROM_RAW_PARTS;
 
@@ -17,12 +17,10 @@ enum RawPartsKind {
 }
 
 fn raw_parts_kind(cx: &LateContext<'_>, did: DefId) -> Option<RawPartsKind> {
-    if match_def_path(cx, did, &paths::SLICE_FROM_RAW_PARTS) {
-        Some(RawPartsKind::Immutable)
-    } else if match_def_path(cx, did, &paths::SLICE_FROM_RAW_PARTS_MUT) {
-        Some(RawPartsKind::Mutable)
-    } else {
-        None
+    match cx.tcx.get_diagnostic_name(did)? {
+        sym::slice_from_raw_parts => Some(RawPartsKind::Immutable),
+        sym::slice_from_raw_parts_mut => Some(RawPartsKind::Mutable),
+        _ => None,
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/create_dir.rs b/src/tools/clippy/clippy_lints/src/create_dir.rs
index 878248a6bdc..2bca695c43b 100644
--- a/src/tools/clippy/clippy_lints/src/create_dir.rs
+++ b/src/tools/clippy/clippy_lints/src/create_dir.rs
@@ -1,11 +1,11 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
-use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -37,7 +37,7 @@ impl LateLintPass<'_> for CreateDir {
             if let ExprKind::Call(func, [arg, ..]) = expr.kind;
             if let ExprKind::Path(ref path) = func.kind;
             if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
-            if match_def_path(cx, def_id, &paths::STD_FS_CREATE_DIR);
+            if cx.tcx.is_diagnostic_item(sym::fs_create_dir, def_id);
             then {
                 span_lint_and_sugg(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs
index 763ad0264ad..5787f19cc6c 100644
--- a/src/tools/clippy/clippy_lints/src/default.rs
+++ b/src/tools/clippy/clippy_lints/src/default.rs
@@ -1,9 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::{has_drop, is_copy};
-use clippy_utils::{
-    any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro, match_def_path, paths,
-};
+use clippy_utils::{any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro};
 use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
@@ -14,7 +12,7 @@ use rustc_middle::ty;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::Span;
+use rustc_span::{sym, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -91,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
             if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
             if let ExprKind::Path(ref qpath) = path.kind;
             if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
-            if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
+            if cx.tcx.is_diagnostic_item(sym::default_fn, def_id);
             if !is_update_syntax_base(cx, expr);
             // Detect and ignore <Foo as Default>::default() because these calls do explicitly name the type.
             if let QPath::Resolved(None, _path) = qpath;
@@ -268,7 +266,7 @@ fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool
         if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
         then {
             // right hand side of assignment is `Default::default`
-            match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD)
+            cx.tcx.is_diagnostic_item(sym::default_fn, def_id)
         } else {
             false
         }
diff --git a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
index a294c693787..0676777e796 100644
--- a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
+++ b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::{is_ty_alias, match_def_path, paths};
+use clippy_utils::is_ty_alias;
 use hir::def::Res;
 use hir::ExprKind;
 use rustc_errors::Applicability;
@@ -7,6 +7,7 @@ use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -63,7 +64,7 @@ impl LateLintPass<'_> for DefaultConstructedUnitStructs {
             // `<Foo as Bar>::Assoc` cannot be used as a constructor
             if !is_alias(*base);
             if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
-            if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
+            if cx.tcx.is_diagnostic_item(sym::default_fn, def_id);
             // make sure we have a struct with no fields (unit struct)
             if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind();
             if def.is_struct();
diff --git a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
index 572990aaba1..3d6d257e386 100644
--- a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
+++ b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
@@ -1,11 +1,11 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_context;
-use clippy_utils::{last_path_segment, match_def_path, paths};
+use clippy_utils::last_path_segment;
 use rustc_errors::Applicability;
 use rustc_hir::{def, Expr, ExprKind, GenericArg, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::SyntaxContext;
+use rustc_span::{sym, SyntaxContext};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -37,7 +37,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty {
             && let TyKind::Path(ty_path) = &ty.kind
             && let QPath::Resolved(None, path) = ty_path
             && let def::Res::Def(_, def_id) = &path.res
-            && match_def_path(cx, *def_id, &paths::ITER_EMPTY)
+            && cx.tcx.is_diagnostic_item(sym::IterEmpty, *def_id)
             && let ctxt = expr.span.ctxt()
             && ty.span.ctxt() == ctxt
         {
diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs
index 8ba6a9e4876..5de79133c7d 100644
--- a/src/tools/clippy/clippy_lints/src/exit.rs
+++ b/src/tools/clippy/clippy_lints/src/exit.rs
@@ -1,9 +1,10 @@
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::{is_entrypoint_fn, match_def_path, paths};
+use clippy_utils::{is_entrypoint_fn};
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -45,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for Exit {
             if let ExprKind::Call(path_expr, _args) = e.kind;
             if let ExprKind::Path(ref path) = path_expr.kind;
             if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id();
-            if match_def_path(cx, def_id, &paths::EXIT);
+            if cx.tcx.is_diagnostic_item(sym::process_exit, def_id);
             let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id;
             if let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find_by_def_id(parent);
             // If the next item up is a function we check if it is an entry point
diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs
index b612cc00bf9..6f6177340f4 100644
--- a/src/tools/clippy/clippy_lints/src/explicit_write.rs
+++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::macros::{find_format_args, format_args_inputs_span};
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_expn_of, match_function_call, paths};
+use clippy_utils::{is_expn_of, path_def_id};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
@@ -47,18 +47,19 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
         if let ExprKind::MethodCall(unwrap_fun, write_call, [], _) = expr.kind
             && unwrap_fun.ident.name == sym::unwrap
             // match call to write_fmt
-            && let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = look_in_block(cx, &write_call.kind)
+            && let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = *look_in_block(cx, &write_call.kind)
+            && let ExprKind::Call(write_recv_path, _) = write_recv.kind
             && write_fun.ident.name == sym!(write_fmt)
-            // match calls to std::io::stdout() / std::io::stderr ()
-            && let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() {
-                Some("stdout")
-            } else if match_function_call(cx, write_recv, &paths::STDERR).is_some() {
-                Some("stderr")
-            } else {
-                None
-            }
-            && let Some(format_args) = find_format_args(cx, write_arg, ExpnId::root())
+            && let Some(def_id) = path_def_id(cx, write_recv_path)
         {
+            // match calls to std::io::stdout() / std::io::stderr ()
+            let (dest_name, prefix) = match cx.tcx.get_diagnostic_name(def_id) {
+                Some(sym::io_stdout) => ("stdout", ""),
+                Some(sym::io_stderr) => ("stderr", "e"),
+                _ => return,
+            };
+            let Some(format_args) = find_format_args(cx, write_arg, ExpnId::root()) else { return; };
+
             // ordering is important here, since `writeln!` uses `write!` internally
             let calling_macro = if is_expn_of(write_call.span, "writeln").is_some() {
                 Some("writeln")
@@ -67,11 +68,6 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
             } else {
                 None
             };
-            let prefix = if dest_name == "stderr" {
-                "e"
-            } else {
-                ""
-            };
 
             // We need to remove the last trailing newline from the string because the
             // underlying `fmt::write` function doesn't know whether `println!` or `print!` was
diff --git a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
index 5e859d97c62..d82ea6d2fc8 100644
--- a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::ty::is_c_void;
-use clippy_utils::{match_def_path, path_def_id, paths};
+use clippy_utils::path_def_id;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
@@ -68,7 +68,7 @@ fn def_id_matches_type(cx: &LateContext<'_>, def_id: DefId) -> Option<&'static s
         }
     }
 
-    if match_def_path(cx, def_id, &paths::WEAK_RC) || match_def_path(cx, def_id, &paths::WEAK_ARC) {
+    if matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::RcWeak | sym::ArcWeak)) {
         Some("Weak")
     } else {
         None
diff --git a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
index 8df7dfb8b9e..a1a115f6d79 100644
--- a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
+++ b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
@@ -130,11 +130,7 @@ fn is_instant_now_call(cx: &LateContext<'_>, expr_block: &'_ Expr<'_>) -> bool {
 
 fn is_an_instant(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let expr_ty = cx.typeck_results().expr_ty(expr);
-
-    match expr_ty.kind() {
-        rustc_middle::ty::Adt(def, _) => clippy_utils::match_def_path(cx, def.did(), &clippy_utils::paths::INSTANT),
-        _ => false,
-    }
+    ty::is_type_diagnostic_item(cx, expr_ty, sym::Instant)
 }
 
 fn is_a_duration(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
index 49425ff0a8e..ac949b67260 100644
--- a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
+++ b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::ty::match_type;
+use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{is_diag_item_method, is_trait_method, match_def_path, path_to_local_id, paths};
 use rustc_errors::Applicability;
 use rustc_hir::{Body, Closure, Expr, ExprKind};
@@ -62,7 +62,7 @@ impl LateLintPass<'_> for LinesFilterMapOk {
         if let ExprKind::MethodCall(fm_method, fm_receiver, [fm_arg], fm_span) = expr.kind &&
             is_trait_method(cx, expr, sym::Iterator) &&
             (fm_method.ident.as_str() == "filter_map" || fm_method.ident.as_str() == "flat_map") &&
-            match_type(cx, cx.typeck_results().expr_ty_adjusted(fm_receiver), &paths::STD_IO_LINES)
+            is_type_diagnostic_item(cx, cx.typeck_results().expr_ty_adjusted(fm_receiver), sym::IoLines)
         {
             let lint = match &fm_arg.kind {
                 // Detect `Result::ok`
diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs
index 1a69a48c582..f923413f434 100644
--- a/src/tools/clippy/clippy_lints/src/manual_retain.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs
@@ -135,7 +135,7 @@ fn check_to_owned(
     if msrv.meets(msrvs::STRING_RETAIN)
         && let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind
         && let Some(to_owned_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
-        && match_def_path(cx, to_owned_def_id, &paths::TO_OWNED_METHOD)
+        && cx.tcx.is_diagnostic_item(sym::to_owned_method, to_owned_def_id)
         && let hir::ExprKind::MethodCall(_, chars_expr, [_], _) = &filter_expr.kind
         && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id)
         && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
diff --git a/src/tools/clippy/clippy_lints/src/methods/bytecount.rs b/src/tools/clippy/clippy_lints/src/methods/bytecount.rs
index f490a717554..35370355f83 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bytecount.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bytecount.rs
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::ty::match_type;
+use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::is_local_used;
-use clippy_utils::{path_to_local_id, paths, peel_blocks, peel_ref_operators, strip_pat_refs};
+use clippy_utils::{path_to_local_id, peel_blocks, peel_ref_operators, strip_pat_refs};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Closure, Expr, ExprKind, PatKind};
@@ -25,9 +25,9 @@ pub(super) fn check<'tcx>(
         if let PatKind::Binding(_, arg_id, _, _) = strip_pat_refs(param.pat).kind;
         if let ExprKind::Binary(ref op, l, r) = body.value.kind;
         if op.node == BinOpKind::Eq;
-        if match_type(cx,
+        if is_type_diagnostic_item(cx,
                     cx.typeck_results().expr_ty(filter_recv).peel_refs(),
-                    &paths::SLICE_ITER);
+                    sym::SliceIter);
         let operand_is_arg = |expr| {
             let expr = peel_ref_operators(cx, peel_blocks(expr));
             path_to_local_id(expr, arg_id)
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
index ddf3c9f27df..926bd06bacb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
@@ -1,7 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::paths;
 use clippy_utils::source::snippet_with_context;
-use clippy_utils::ty::{is_type_diagnostic_item, match_type};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -22,15 +20,14 @@ pub(super) fn check(
     }
     let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs();
 
-    if let ty::Adt(_, subst) = obj_ty.kind() {
-        let caller_type = if is_type_diagnostic_item(cx, obj_ty, sym::Rc) {
-            "Rc"
-        } else if is_type_diagnostic_item(cx, obj_ty, sym::Arc) {
-            "Arc"
-        } else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) {
-            "Weak"
-        } else {
-            return;
+    if let ty::Adt(adt, subst) = obj_ty.kind()
+        && let Some(name) = cx.tcx.get_diagnostic_name(adt.did())
+    {
+        let caller_type = match name {
+            sym::Rc => "Rc",
+            sym::Arc => "Arc",
+            sym::RcWeak | sym::ArcWeak => "Weak",
+            _ => return,
         };
 
         // Sometimes unnecessary ::<_> after Rc/Arc/Weak
diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
index 66dfce3682b..4040d3a5fe1 100644
--- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{is_expr_path_def_path, paths, sugg};
+use clippy_utils::{is_path_diagnostic_item, sugg};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -13,7 +13,7 @@ use super::FROM_ITER_INSTEAD_OF_COLLECT;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>], func: &hir::Expr<'_>) {
     if_chain! {
-        if is_expr_path_def_path(cx, func, &paths::FROM_ITERATOR_METHOD);
+        if is_path_diagnostic_item(cx, func, sym::from_iter_fn);
         let ty = cx.typeck_results().expr_ty(expr);
         let arg_ty = cx.typeck_results().expr_ty(&args[0]);
         if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
diff --git a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
index 631741d9290..6686d42c95f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{is_type_lang_item, walk_ptrs_ty_depth};
-use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -22,7 +21,7 @@ pub fn check(
     if_chain! {
         if args.is_empty() && method_name == sym::to_string;
         if let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if match_def_path(cx, to_string_meth_did, &paths::TO_STRING_METHOD);
+        if cx.tcx.is_diagnostic_item(sym::to_string_method, to_string_meth_did);
         if let Some(args) = cx.typeck_results().node_args_opt(expr.hir_id);
         let arg_ty = cx.typeck_results().expr_ty_adjusted(receiver);
         let self_ty = args.type_at(0);
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs b/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs
index 79c6d63254b..99ea7f03df4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_note;
 use clippy_utils::higher::VecArgs;
-use clippy_utils::{expr_or_init, is_trait_method, match_def_path, paths};
+use clippy_utils::{expr_or_init, is_trait_method};
 use rustc_ast::LitKind;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -26,14 +26,14 @@ fn get_iterator_length<'tcx>(cx: &LateContext<'tcx>, iter: &'tcx Expr<'tcx>) ->
     };
     let did = adt.did();
 
-    if match_def_path(cx, did, &paths::ARRAY_INTO_ITER) {
+    if cx.tcx.is_diagnostic_item(sym::ArrayIntoIter, did) {
         // For array::IntoIter<T, const N: usize>, the length is the second generic
         // parameter.
         substs
             .const_at(1)
             .try_eval_target_usize(cx.tcx, cx.param_env)
             .map(u128::from)
-    } else if match_def_path(cx, did, &paths::SLICE_ITER)
+    } else if cx.tcx.is_diagnostic_item(sym::SliceIter, did)
         && let ExprKind::MethodCall(_, recv, ..) = iter.kind
     {
         if let ty::Array(_, len) = cx.typeck_results().expr_ty(recv).peel_refs().kind() {
@@ -47,9 +47,9 @@ fn get_iterator_length<'tcx>(cx: &LateContext<'tcx>, iter: &'tcx Expr<'tcx>) ->
         } else {
             None
         }
-    } else if match_def_path(cx, did, &paths::ITER_EMPTY) {
+    } else if cx.tcx.is_diagnostic_item(sym::IterEmpty, did) {
         Some(0)
-    } else if match_def_path(cx, did, &paths::ITER_ONCE) {
+    } else if cx.tcx.is_diagnostic_item(sym::IterOnce, did) {
         Some(1)
     }  else {
         None
diff --git a/src/tools/clippy/clippy_lints/src/methods/open_options.rs b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
index 1c664e76d74..c0f5a279945 100644
--- a/src/tools/clippy/clippy_lints/src/methods/open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
@@ -1,17 +1,17 @@
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::paths;
-use clippy_utils::ty::match_type;
+use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_ast::ast::LitKind;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_span::source_map::{Span, Spanned};
+use rustc_span::sym;
 
 use super::NONSENSICAL_OPEN_OPTIONS;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) {
     if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
         && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
-        && match_type(cx, cx.tcx.type_of(impl_id).instantiate_identity(), &paths::OPEN_OPTIONS)
+        && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::FsOpenOptions)
     {
         let mut options = Vec::new();
         get_open_options(cx, recv, &mut options);
@@ -40,7 +40,7 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec
         let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs();
 
         // Only proceed if this is a call on some object of type std::fs::OpenOptions
-        if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && !arguments.is_empty() {
+        if is_type_diagnostic_item(cx, obj_ty, sym::FsOpenOptions) && !arguments.is_empty() {
             let argument_option = match arguments[0].kind {
                 ExprKind::Lit(span) => {
                     if let Spanned {
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
index 3e33f919337..d0c27f9631f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -32,8 +32,7 @@ pub(super) fn check(
         return;
     }
 
-    let deref_aliases: [&[&str]; 8] = [
-        &paths::DEREF_MUT_TRAIT_METHOD,
+    let deref_aliases: [&[&str]; 7] = [
         &paths::CSTRING_AS_C_STR,
         &paths::OS_STRING_AS_OS_STR,
         &paths::PATH_BUF_AS_PATH,
@@ -49,6 +48,7 @@ pub(super) fn check(
                 .opt_def_id()
                 .map_or(false, |fun_def_id| {
                     cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id)
+                        || cx.tcx.is_diagnostic_item(sym::deref_mut_method, fun_def_id)
                         || deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path))
                 })
         },
@@ -70,6 +70,7 @@ pub(super) fn check(
                         then {
                             let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap();
                             cx.tcx.is_diagnostic_item(sym::deref_method, method_did)
+                                || cx.tcx.is_diagnostic_item(sym::deref_mut_method, method_did)
                                 || deref_aliases.iter().any(|path| match_def_path(cx, method_did, path))
                         } else {
                             false
diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
index f3d6a15ede0..4ea87027a9e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
@@ -2,18 +2,19 @@ use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
+use rustc_span::sym;
 
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{get_trait_def_id, match_def_path, paths};
+use clippy_utils::{match_def_path, paths};
 
 use super::SEEK_FROM_CURRENT;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) {
     let ty = cx.typeck_results().expr_ty(recv);
 
-    if let Some(def_id) = get_trait_def_id(cx, &paths::STD_IO_SEEK) {
+    if let Some(def_id) = cx.tcx.get_diagnostic_item(sym::IoSeek) {
         if implements_trait(cx, ty, def_id, &[]) && arg_is_seek_from_current(cx, arg) {
             let mut applicability = Applicability::MachineApplicable;
             let snip = snippet_with_applicability(cx, recv.span, "..", &mut applicability);
diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
index 787e9e0ebd2..50d4de7a680 100644
--- a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
@@ -1,11 +1,11 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{get_trait_def_id, is_expr_used_or_unified, match_def_path, paths};
+use clippy_utils::{is_expr_used_or_unified, match_def_path, paths};
 use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
-use rustc_span::Span;
+use rustc_span::{sym, Span};
 
 use super::SEEK_TO_START_INSTEAD_OF_REWIND;
 
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(
         return;
     }
 
-    if let Some(seek_trait_id) = get_trait_def_id(cx, &paths::STD_IO_SEEK) &&
+    if let Some(seek_trait_id) = cx.tcx.get_diagnostic_item(sym::IoSeek) &&
         implements_trait(cx, ty, seek_trait_id, &[]) &&
         let ExprKind::Call(func, args1) = arg.kind &&
         let ExprKind::Path(ref path) = func.kind &&
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs
index bc8f0176764..8959e2c1d75 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs
@@ -1,9 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::paths;
-use clippy_utils::ty::match_type;
+use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_lint::LateContext;
-use rustc_span::Span;
+use rustc_span::{sym, Span};
 use {rustc_ast as ast, rustc_hir as hir};
 
 use super::SUSPICIOUS_COMMAND_ARG_SPACE;
@@ -11,7 +10,7 @@ use super::SUSPICIOUS_COMMAND_ARG_SPACE;
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>, span: Span) {
     let ty = cx.typeck_results().expr_ty(recv).peel_refs();
 
-    if match_type(cx, ty, &paths::STD_PROCESS_COMMAND)
+    if is_type_diagnostic_item(cx, ty, sym::Command)
         && let hir::ExprKind::Lit(lit) = &arg.kind
         && let ast::LitKind::Str(s, _) = &lit.node
         && let Some((arg1, arg2)) = s.as_str().split_once(' ')
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
index 937aac8d25e..24c0ea3f60a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
@@ -102,14 +102,10 @@ pub(super) fn check(
             ]),
             ("None", "unwrap_or_else", _) => match args[0].kind {
                 hir::ExprKind::Closure(hir::Closure {
-                    fn_decl:
-                        hir::FnDecl {
-                            output: hir::FnRetTy::DefaultReturn(span) | hir::FnRetTy::Return(hir::Ty { span, .. }),
-                            ..
-                        },
+                    body,
                     ..
                 }) => Some(vec![
-                    (expr.span.with_hi(span.hi()), String::new()),
+                    (expr.span.with_hi(cx.tcx.hir().body(*body).value.span.lo()), String::new()),
                     (expr.span.with_lo(args[0].span.hi()), String::new()),
                 ]),
                 _ => None,
diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
index 2f63b9b9f0b..f0b865be804 100644
--- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
@@ -1,9 +1,9 @@
 use std::ops::ControlFlow;
 
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::ty::match_type;
+use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::{for_each_expr, Visitable};
-use clippy_utils::{is_path_lang_item, paths};
+use clippy_utils::is_path_lang_item;
 use rustc_ast::LitKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
@@ -114,9 +114,11 @@ fn should_lint<'tcx>(
         if let ExprKind::MethodCall(path, recv, ..) = &expr.kind {
             let recv_ty = typeck_results.expr_ty(recv).peel_refs();
 
-            if path.ident.name == sym::debug_struct && match_type(cx, recv_ty, &paths::FORMATTER) {
+            if path.ident.name == sym::debug_struct && is_type_diagnostic_item(cx, recv_ty, sym::Formatter) {
                 has_debug_struct = true;
-            } else if path.ident.name == sym!(finish_non_exhaustive) && match_type(cx, recv_ty, &paths::DEBUG_STRUCT) {
+            } else if path.ident.name == sym!(finish_non_exhaustive)
+                && is_type_diagnostic_item(cx, recv_ty, sym::DebugStruct)
+            {
                 has_finish_non_exhaustive = true;
             }
         }
@@ -137,7 +139,7 @@ fn as_field_call<'tcx>(
 ) -> Option<Symbol> {
     if let ExprKind::MethodCall(path, recv, [debug_field, _], _) = &expr.kind
         && let recv_ty = typeck_results.expr_ty(recv).peel_refs()
-        && match_type(cx, recv_ty, &paths::DEBUG_STRUCT)
+        && is_type_diagnostic_item(cx, recv_ty, sym::DebugStruct)
         && path.ident.name == sym::field
         && let ExprKind::Lit(lit) = &debug_field.kind
         && let LitKind::Str(sym, ..) = lit.node
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index 367cd6bd413..ea6a9bc5657 100644
--- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -134,15 +134,30 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
     }
 }
 
+fn stmt_might_diverge(stmt: &Stmt<'_>) -> bool {
+    match stmt.kind {
+        StmtKind::Item(..) => false,
+        _ => true,
+    }
+}
+
 impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
         match e.kind {
             // fix #10776
             ExprKind::Block(block, ..) => match (block.stmts, block.expr) {
-                ([], Some(e)) => self.visit_expr(e),
-                ([stmt], None) => match stmt.kind {
-                    StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e),
-                    _ => {},
+                (stmts, Some(e)) => {
+                    if stmts.iter().all(|stmt| !stmt_might_diverge(stmt)) {
+                        self.visit_expr(e)
+                    }
+                },
+                ([first @ .., stmt], None) => {
+                    if first.iter().all(|stmt| !stmt_might_diverge(stmt)) {
+                        match stmt.kind {
+                            StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e),
+                            _ => {},
+                        }
+                    }
                 },
                 _ => {},
             },
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 5ee26966fa7..6d7df2eac62 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -4,7 +4,7 @@ use clippy_utils::source::{snippet, snippet_opt};
 use clippy_utils::ty::{
     implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item,
 };
-use clippy_utils::{get_trait_def_id, is_self, paths};
+use clippy_utils::is_self;
 use if_chain::if_chain;
 use rustc_ast::ast::Attribute;
 use rustc_errors::{Applicability, Diagnostic};
@@ -115,7 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
             need!(cx.tcx.lang_items().fn_trait()),
             need!(cx.tcx.lang_items().fn_once_trait()),
             need!(cx.tcx.lang_items().fn_mut_trait()),
-            need!(get_trait_def_id(cx, &paths::RANGE_ARGUMENT_TRAIT)),
+            need!(cx.tcx.get_diagnostic_item(sym::RangeBounds)),
         ];
 
         let sized_trait = need!(cx.tcx.lang_items().sized_trait());
diff --git a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
index 20b4b4f03ed..4be140647fc 100644
--- a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
@@ -1,7 +1,6 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::paths::ORD_CMP;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{get_parent_node, is_res_lang_ctor, last_path_segment, match_def_path, path_res, std_or_core};
+use clippy_utils::{get_parent_node, is_res_lang_ctor, last_path_segment, path_res, std_or_core};
 use rustc_errors::Applicability;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, LangItem, Node, UnOp};
@@ -261,7 +260,7 @@ fn self_cmp_call<'tcx>(
     match cmp_expr.kind {
         ExprKind::Call(path, [_self, _other]) => path_res(cx, path)
             .opt_def_id()
-            .is_some_and(|def_id| match_def_path(cx, def_id, &ORD_CMP)),
+            .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::ord_cmp_method, def_id)),
         ExprKind::MethodCall(_, _, [_other], ..) => {
             // We can set this to true here no matter what as if it's a `MethodCall` and goes to the
             // `else` branch, it must be a method named `cmp` that isn't `Ord::cmp`
@@ -273,7 +272,7 @@ fn self_cmp_call<'tcx>(
             cx.tcx
                 .typeck(def_id)
                 .type_dependent_def_id(cmp_expr.hir_id)
-                .is_some_and(|def_id| match_def_path(cx, def_id, &ORD_CMP))
+                .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::ord_cmp_method, def_id))
         },
         _ => false,
     }
diff --git a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
index e1de494eb41..d47728f190a 100644
--- a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
+++ b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{snippet_opt, snippet_with_applicability};
-use clippy_utils::ty::{is_type_diagnostic_item, match_type};
 use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -45,13 +44,12 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         match &expr.kind {
             ExprKind::MethodCall(path, func, [param], _) => {
-                let obj_ty = cx.typeck_results().expr_ty(func).peel_refs();
-
                 if_chain! {
+                    if let Some(adt) = cx.typeck_results().expr_ty(func).peel_refs().ty_adt_def();
                     if (path.ident.name == sym!(mode)
-                        && (match_type(cx, obj_ty, &paths::OPEN_OPTIONS)
-                            || is_type_diagnostic_item(cx, obj_ty, sym::DirBuilder)))
-                        || (path.ident.name == sym!(set_mode) && match_type(cx, obj_ty, &paths::PERMISSIONS));
+                        && matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::FsOpenOptions | sym::DirBuilder)))
+                        || (path.ident.name == sym!(set_mode)
+                            && cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did()));
                     if let ExprKind::Lit(_) = param.kind;
                     if param.span.ctxt() == expr.span.ctxt();
 
diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
index c5e777c2070..d388dfc08f3 100644
--- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
+++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::{implements_trait, is_copy};
-use clippy_utils::{is_lint_allowed, match_def_path, paths};
+use clippy_utils::is_lint_allowed;
 use rustc_ast::ImplPolarity;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{FieldDef, Item, ItemKind, Node};
@@ -233,7 +233,7 @@ fn contains_pointer_like<'tcx>(cx: &LateContext<'tcx>, target_ty: Ty<'tcx>) -> b
                     return true;
                 },
                 ty::Adt(adt_def, _) => {
-                    if match_def_path(cx, adt_def.did(), &paths::PTR_NON_NULL) {
+                    if cx.tcx.is_diagnostic_item(sym::NonNull, adt_def.did()) {
                         return true;
                     }
                 },
diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
index d3de9699fe9..136642d69dc 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::{implements_trait, is_copy};
-use clippy_utils::{match_def_path, path_def_id, paths};
+use clippy_utils::path_def_id;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
 use rustc_lint::LateContext;
@@ -50,7 +50,7 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
         },
         ExprKind::Call(path, [arg])
             if path_def_id(cx, path).map_or(false, |did| {
-                if match_def_path(cx, did, &paths::FROM_STR_METHOD) {
+                if cx.tcx.is_diagnostic_item(sym::from_str_method, did) {
                     true
                 } else if cx.tcx.is_diagnostic_item(sym::from_fn, did) {
                     !is_copy(cx, typeck.expr_ty(expr))
diff --git a/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs
index 664d44d6504..f3089d716ff 100644
--- a/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs
+++ b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs
@@ -1,10 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::paths;
-use clippy_utils::ty::match_type;
+use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_ast::ast::LitKind;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -31,7 +31,7 @@ declare_lint_pass!(PermissionsSetReadonlyFalse => [PERMISSIONS_SET_READONLY_FALS
 impl<'tcx> LateLintPass<'tcx> for PermissionsSetReadonlyFalse {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         if let ExprKind::MethodCall(path, receiver, [arg], _) = &expr.kind
-            && match_type(cx, cx.typeck_results().expr_ty(receiver), &paths::PERMISSIONS)
+            && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::FsPermissions)
             && path.ident.name == sym!(set_readonly)
             && let ExprKind::Lit(lit) = &arg.kind
             && LitKind::Bool(false) == lit.node
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 7dabdcd58ec..310051efc50 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -4,9 +4,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::expr_sig;
 use clippy_utils::visitors::contains_unsafe_block;
-use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local, paths};
+use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local};
 use hir::LifetimeName;
-use if_chain::if_chain;
 use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir::def_id::DefId;
 use rustc_hir::hir_id::HirIdMap;
@@ -271,60 +270,43 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
 }
 
 fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-    // (fn_path, arg_indices) - `arg_indices` are the `arg` positions where null would cause U.B.
-    const INVALID_NULL_PTR_USAGE_TABLE: [(&[&str], &[usize]); 13] = [
-        (&paths::SLICE_FROM_RAW_PARTS, &[0]),
-        (&paths::SLICE_FROM_RAW_PARTS_MUT, &[0]),
-        (&paths::PTR_COPY, &[0, 1]),
-        (&paths::PTR_COPY_NONOVERLAPPING, &[0, 1]),
-        (&paths::PTR_READ, &[0]),
-        (&paths::PTR_READ_UNALIGNED, &[0]),
-        (&paths::PTR_READ_VOLATILE, &[0]),
-        (&paths::PTR_REPLACE, &[0]),
-        (&paths::PTR_SLICE_FROM_RAW_PARTS, &[0]),
-        (&paths::PTR_SLICE_FROM_RAW_PARTS_MUT, &[0]),
-        (&paths::PTR_SWAP, &[0, 1]),
-        (&paths::PTR_SWAP_NONOVERLAPPING, &[0, 1]),
-        (&paths::PTR_WRITE_BYTES, &[0]),
-    ];
-    let invalid_null_ptr_usage_table_diag_items: [(Option<DefId>, &[usize]); 3] = [
-        (cx.tcx.get_diagnostic_item(sym::ptr_write), &[0]),
-        (cx.tcx.get_diagnostic_item(sym::ptr_write_unaligned), &[0]),
-        (cx.tcx.get_diagnostic_item(sym::ptr_write_volatile), &[0]),
-    ];
-
-    if_chain! {
-        if let ExprKind::Call(fun, args) = expr.kind;
-        if let ExprKind::Path(ref qpath) = fun.kind;
-        if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
-        let fun_def_path = cx.get_def_path(fun_def_id).into_iter().map(Symbol::to_ident_string).collect::<Vec<_>>();
-        if let Some(arg_indices) = INVALID_NULL_PTR_USAGE_TABLE
-            .iter()
-            .find_map(|&(fn_path, indices)| if fn_path == fun_def_path { Some(indices) } else { None })
-            .or_else(|| {
-                invalid_null_ptr_usage_table_diag_items
-                    .iter()
-                    .find_map(|&(def_id, indices)| {
-                        if def_id == Some(fun_def_id) {
-                            Some(indices)
-                        } else {
-                            None
-                        }
-                    })
-            });
-        then {
-            for &arg_idx in arg_indices {
-                if let Some(arg) = args.get(arg_idx).filter(|arg| is_null_path(cx, arg)) {
-                    span_lint_and_sugg(
-                        cx,
-                        INVALID_NULL_PTR_USAGE,
-                        arg.span,
-                        "pointer must be non-null",
-                        "change this to",
-                        "core::ptr::NonNull::dangling().as_ptr()".to_string(),
-                        Applicability::MachineApplicable,
-                    );
-                }
+    if let ExprKind::Call(fun, args) = expr.kind
+        && let ExprKind::Path(ref qpath) = fun.kind
+        && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
+        && let Some(name) = cx.tcx.get_diagnostic_name(fun_def_id)
+    {
+        // `arg` positions where null would cause U.B.
+        let arg_indices: &[_] = match name {
+            sym::ptr_read
+            | sym::ptr_read_unaligned
+            | sym::ptr_read_volatile
+            | sym::ptr_replace
+            | sym::ptr_slice_from_raw_parts
+            | sym::ptr_slice_from_raw_parts_mut
+            | sym::ptr_write
+            | sym::ptr_write_bytes
+            | sym::ptr_write_unaligned
+            | sym::ptr_write_volatile
+            | sym::slice_from_raw_parts
+            | sym::slice_from_raw_parts_mut => &[0],
+            sym::ptr_copy
+            | sym::ptr_copy_nonoverlapping
+            | sym::ptr_swap
+            | sym::ptr_swap_nonoverlapping => &[0, 1],
+            _ => return,
+        };
+
+        for &arg_idx in arg_indices {
+            if let Some(arg) = args.get(arg_idx).filter(|arg| is_null_path(cx, arg)) {
+                span_lint_and_sugg(
+                    cx,
+                    INVALID_NULL_PTR_USAGE,
+                    arg.span,
+                    "pointer must be non-null",
+                    "change this to",
+                    "core::ptr::NonNull::dangling().as_ptr()".to_string(),
+                    Applicability::MachineApplicable,
+                );
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs
index 8e85c55e756..1a127c2bcf6 100644
--- a/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs
+++ b/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs
@@ -2,11 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::VecArgs;
 use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::source::{indent_of, snippet};
-use clippy_utils::ty::match_type;
-use clippy_utils::{last_path_segment, paths};
+use clippy_utils::last_path_segment;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Span, Symbol};
 
@@ -133,8 +133,9 @@ fn ref_init(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<(Symbol, Span)> {
                 return Some((symbol, func.span));
             }
 
-            let ty_path = cx.typeck_results().expr_ty(expr);
-            if match_type(cx, ty_path, &paths::WEAK_RC) || match_type(cx, ty_path, &paths::WEAK_ARC) {
+            if let ty::Adt(adt, _) = *cx.typeck_results().expr_ty(expr).kind()
+                && matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::RcWeak | sym::ArcWeak))
+            {
                 return Some((Symbol::intern("Weak"), func.span));
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index e36adef555e..2c0086b0981 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -99,8 +99,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                 unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind));
 
             let from_borrow = match_def_path(cx, fn_def_id, &paths::CLONE_TRAIT_METHOD)
-                || match_def_path(cx, fn_def_id, &paths::TO_OWNED_METHOD)
-                || (match_def_path(cx, fn_def_id, &paths::TO_STRING_METHOD)
+                || cx.tcx.is_diagnostic_item(sym::to_owned_method, fn_def_id)
+                || (cx.tcx.is_diagnostic_item(sym::to_string_method, fn_def_id)
                     && is_type_lang_item(cx, arg_ty, LangItem::String));
 
             let from_deref = !from_borrow
diff --git a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs
index bd783b4e005..b940cac6047 100644
--- a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs
+++ b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs
@@ -2,7 +2,6 @@
 //! expecting a count of T
 
 use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -67,16 +66,6 @@ fn get_pointee_ty_and_count_expr<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'_>,
 ) -> Option<(Ty<'tcx>, &'tcx Expr<'tcx>)> {
-    const FUNCTIONS: [&[&str]; 8] = [
-        &paths::PTR_COPY_NONOVERLAPPING,
-        &paths::PTR_COPY,
-        &paths::PTR_WRITE_BYTES,
-        &paths::PTR_SWAP_NONOVERLAPPING,
-        &paths::PTR_SLICE_FROM_RAW_PARTS,
-        &paths::PTR_SLICE_FROM_RAW_PARTS_MUT,
-        &paths::SLICE_FROM_RAW_PARTS,
-        &paths::SLICE_FROM_RAW_PARTS_MUT,
-    ];
     const METHODS: [&str; 11] = [
         "write_bytes",
         "copy_to",
@@ -97,7 +86,16 @@ fn get_pointee_ty_and_count_expr<'tcx>(
         if let ExprKind::Call(func, [.., count]) = expr.kind;
         if let ExprKind::Path(ref func_qpath) = func.kind;
         if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
-        if FUNCTIONS.iter().any(|func_path| match_def_path(cx, def_id, func_path));
+        if matches!(cx.tcx.get_diagnostic_name(def_id), Some(
+            sym::ptr_copy
+            | sym::ptr_copy_nonoverlapping
+            | sym::ptr_slice_from_raw_parts
+            | sym::ptr_slice_from_raw_parts_mut
+            | sym::ptr_swap_nonoverlapping
+            | sym::ptr_write_bytes
+            | sym::slice_from_raw_parts
+            | sym::slice_from_raw_parts_mut
+        ));
 
         // Get the pointee type
         if let Some(pointee_ty) = cx.typeck_results().node_args(func.hir_id).types().next();
diff --git a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
index d085dda3582..3685432a253 100644
--- a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
@@ -1,11 +1,11 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_context;
-use clippy_utils::{match_def_path, path_def_id, paths};
+use clippy_utils::path_def_id;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::{Span, SyntaxContext};
+use rustc_span::{sym, Span, SyntaxContext};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -42,7 +42,7 @@ impl LateLintPass<'_> for SwapPtrToRef {
     fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) {
         if let ExprKind::Call(fn_expr, [arg1, arg2]) = e.kind
             && let Some(fn_id) = path_def_id(cx, fn_expr)
-            && match_def_path(cx, fn_id, &paths::MEM_SWAP)
+            && cx.tcx.is_diagnostic_item(sym::mem_swap, fn_id)
             && let ctxt = e.span.ctxt()
             && let (from_ptr1, arg1_span) = is_ptr_to_ref(cx, arg1, ctxt)
             && let (from_ptr2, arg2_span) = is_ptr_to_ref(cx, arg2, ctxt)
diff --git a/src/tools/clippy/clippy_lints/src/unnamed_address.rs b/src/tools/clippy/clippy_lints/src/unnamed_address.rs
index dea8a1e35bb..996e7edf557 100644
--- a/src/tools/clippy/clippy_lints/src/unnamed_address.rs
+++ b/src/tools/clippy/clippy_lints/src/unnamed_address.rs
@@ -1,10 +1,10 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
-use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -96,7 +96,7 @@ impl LateLintPass<'_> for UnnamedAddress {
             if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind;
             if let ExprKind::Path(ref func_qpath) = func.kind;
             if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
-            if match_def_path(cx, def_id, &paths::PTR_EQ);
+            if cx.tcx.is_diagnostic_item(sym::ptr_eq, def_id);
             let ty_param = cx.typeck_results().node_args(func.hir_id).type_at(0);
             if ty_param.is_trait();
             then {
diff --git a/src/tools/clippy/clippy_lints/src/unused_peekable.rs b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
index 4ee16d9a5e4..db91beec0ef 100644
--- a/src/tools/clippy/clippy_lints/src/unused_peekable.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::{match_type, peel_mid_ty_refs_is_mutable};
-use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, paths, peel_ref_operators};
+use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable};
+use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, peel_ref_operators};
 use rustc_ast::Mutability;
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind};
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable {
         // Don't lint `Peekable`s returned from a block
         if let Some(expr) = block.expr
             && let Some(ty) = cx.typeck_results().expr_ty_opt(peel_ref_operators(cx, expr))
-            && match_type(cx, ty, &paths::PEEKABLE)
+            && is_type_diagnostic_item(cx, ty, sym::IterPeekable)
         {
             return;
         }
@@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable {
                 && !init.span.from_expansion()
                 && let Some(ty) = cx.typeck_results().expr_ty_opt(init)
                 && let (ty, _, Mutability::Mut) = peel_mid_ty_refs_is_mutable(ty)
-                && match_type(cx, ty, &paths::PEEKABLE)
+                && is_type_diagnostic_item(cx, ty, sym::IterPeekable)
             {
                 let mut vis = PeekableVisitor::new(cx, binding);
 
@@ -222,7 +222,7 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
 fn arg_is_mut_peekable(cx: &LateContext<'_>, arg: &Expr<'_>) -> bool {
     if let Some(ty) = cx.typeck_results().expr_ty_opt(arg)
         && let (ty, _, Mutability::Mut) = peel_mid_ty_refs_is_mutable(ty)
-        && match_type(cx, ty, &paths::PEEKABLE)
+        && is_type_diagnostic_item(cx, ty, sym::IterPeekable)
     {
         true
     } else {
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index f32e7edad6c..3cc91838c00 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lin
 use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts};
-use clippy_utils::{get_parent_expr, is_trait_method, is_ty_alias, match_def_path, path_to_local, paths};
+use clippy_utils::{get_parent_expr, is_trait_method, is_ty_alias, path_to_local};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::DefKind;
@@ -331,7 +331,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                         let a = cx.typeck_results().expr_ty(e);
                         let b = cx.typeck_results().expr_ty(arg);
                         if_chain! {
-                            if match_def_path(cx, def_id, &paths::TRY_FROM);
+                            if cx.tcx.is_diagnostic_item(sym::try_from_fn, def_id);
                             if is_type_diagnostic_item(cx, a, sym::Result);
                             if let ty::Adt(_, args) = a.kind();
                             if let Some(a_type) = args.types().next();
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index 802adbd4d2d..741f9f54883 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -457,7 +457,7 @@ pub fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -
                 };
             },
             ExprKind::Path(QPath::Resolved(_, path))
-                if match_def_path(cx, path.res.opt_def_id()?, &paths::DEFAULT_TRAIT_METHOD)
+                if cx.tcx.is_diagnostic_item(sym::default_fn, path.res.opt_def_id()?)
                     && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec) =>
             {
                 return Some(VecInitKind::Default);
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 13da79fba7e..64ca2ff7873 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -2076,7 +2076,7 @@ pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool
 
     match expr.kind {
         ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir().body(body)),
-        _ => path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, &paths::CONVERT_IDENTITY)),
+        _ => path_def_id(cx, expr).map_or(false, |id| cx.tcx.is_diagnostic_item(sym::convert_identity, id)),
     }
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 82508bcdb85..eaf590f6ad7 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -228,16 +228,26 @@ pub enum PanicExpn<'a> {
 
 impl<'a> PanicExpn<'a> {
     pub fn parse(expr: &'a Expr<'a>) -> Option<Self> {
-        let ExprKind::Call(callee, [arg, rest @ ..]) = &expr.kind else {
+        let ExprKind::Call(callee, args) = &expr.kind else {
             return None;
         };
         let ExprKind::Path(QPath::Resolved(_, path)) = &callee.kind else {
             return None;
         };
-        let result = match path.segments.last().unwrap().ident.as_str() {
+        let name = path.segments.last().unwrap().ident.as_str();
+
+        // This has no argument
+        if name == "panic_cold_explicit" {
+            return Some(Self::Empty);
+        };
+
+        let [arg, rest @ ..] = args else {
+            return None;
+        };
+        let result = match name {
             "panic" if arg.span.ctxt() == expr.span.ctxt() => Self::Empty,
             "panic" | "panic_str" => Self::Str(arg),
-            "panic_display" => {
+            "panic_display" | "panic_cold_display" => {
                 let ExprKind::AddrOf(_, _, e) = &arg.kind else {
                     return None;
                 };
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 2fb24b5c7ed..1f2bb16f459 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -25,17 +25,12 @@ pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "
 pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"];
 pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"];
 pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
-pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"];
-pub const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"];
 #[cfg(feature = "internal")]
 pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
 #[cfg(feature = "internal")]
 pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"];
-pub const EXIT: [&str; 3] = ["std", "process", "exit"];
 pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
 pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl f64>", "EPSILON"];
-pub const FROM_ITERATOR_METHOD: [&str; 6] = ["core", "iter", "traits", "collect", "FromIterator", "from_iter"];
-pub const FROM_STR_METHOD: [&str; 5] = ["core", "str", "traits", "FromStr", "from_str"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
@@ -48,8 +43,6 @@ pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
 #[cfg(feature = "internal")]
 pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
 pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"];
-pub const ITER_EMPTY: [&str; 5] = ["core", "iter", "sources", "empty", "Empty"];
-pub const ITER_ONCE: [&str; 5] = ["core", "iter", "sources", "once", "Once"];
 pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
 #[cfg(feature = "internal")]
 pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
@@ -59,10 +52,8 @@ pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"];
 pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
 #[cfg(feature = "internal")]
 pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
-pub const MEM_SWAP: [&str; 3] = ["core", "mem", "swap"];
 #[cfg(feature = "internal")]
 pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"];
-pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
 pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"];
 pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
 pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
@@ -71,28 +62,9 @@ pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "Rw
 pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
 pub const PATH_MAIN_SEPARATOR: [&str; 3] = ["std", "path", "MAIN_SEPARATOR"];
 pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
-pub const PEEKABLE: [&str; 5] = ["core", "iter", "adapters", "peekable", "Peekable"];
-pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"];
 #[cfg_attr(not(unix), allow(clippy::invalid_paths))]
 pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
-pub const PTR_COPY: [&str; 3] = ["core", "intrinsics", "copy"];
-pub const PTR_COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"];
-pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"];
-pub const PTR_SLICE_FROM_RAW_PARTS: [&str; 3] = ["core", "ptr", "slice_from_raw_parts"];
-pub const PTR_SLICE_FROM_RAW_PARTS_MUT: [&str; 3] = ["core", "ptr", "slice_from_raw_parts_mut"];
-pub const PTR_SWAP_NONOVERLAPPING: [&str; 3] = ["core", "ptr", "swap_nonoverlapping"];
-pub const PTR_READ: [&str; 3] = ["core", "ptr", "read"];
-pub const PTR_READ_UNALIGNED: [&str; 3] = ["core", "ptr", "read_unaligned"];
-pub const PTR_READ_VOLATILE: [&str; 3] = ["core", "ptr", "read_volatile"];
-pub const PTR_REPLACE: [&str; 3] = ["core", "ptr", "replace"];
-pub const PTR_SWAP: [&str; 3] = ["core", "ptr", "swap"];
-pub const PTR_UNALIGNED_VOLATILE_LOAD: [&str; 3] = ["core", "intrinsics", "unaligned_volatile_load"];
-pub const PTR_UNALIGNED_VOLATILE_STORE: [&str; 3] = ["core", "intrinsics", "unaligned_volatile_store"];
-pub const PTR_WRITE_BYTES: [&str; 3] = ["core", "intrinsics", "write_bytes"];
 pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
-pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
-pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"];
-pub const REFCELL_REFMUT: [&str; 3] = ["core", "cell", "RefMut"];
 pub const REGEX_BUILDER_NEW: [&str; 3] = ["regex", "RegexBuilder", "new"];
 pub const REGEX_BYTES_BUILDER_NEW: [&str; 4] = ["regex", "bytes", "RegexBuilder", "new"];
 pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "bytes", "Regex", "new"];
@@ -101,21 +73,11 @@ pub const REGEX_NEW: [&str; 3] = ["regex", "Regex", "new"];
 pub const REGEX_SET_NEW: [&str; 3] = ["regex", "RegexSet", "new"];
 pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
 pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
-pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"];
-pub const SLICE_FROM_RAW_PARTS_MUT: [&str; 4] = ["core", "slice", "raw", "from_raw_parts_mut"];
 pub const SLICE_GET: [&str; 4] = ["core", "slice", "<impl [T]>", "get"];
 pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
 pub const SLICE_INTO: [&str; 4] = ["core", "slice", "<impl [T]>", "iter"];
-pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"];
-pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"];
-pub const STDOUT: [&str; 4] = ["std", "io", "stdio", "stdout"];
-pub const CONVERT_IDENTITY: [&str; 3] = ["core", "convert", "identity"];
-pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"];
-pub const STD_IO_LINES: [&str; 3] = ["std", "io", "Lines"];
-pub const STD_IO_SEEK: [&str; 3] = ["std", "io", "Seek"];
 pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
 pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
-pub const STD_PROCESS_COMMAND: [&str; 3] = ["std", "process", "Command"];
 pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
 pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
 pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
@@ -136,13 +98,11 @@ pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol",
 pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
 #[cfg(feature = "internal")]
 pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
-pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"];
 pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_IO_ASYNCREADEXT: [&str; 5] = ["tokio", "io", "util", "async_read_ext", "AsyncReadExt"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_write_ext", "AsyncWriteExt"];
-pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"];
 pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"];
 pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"];
 pub const VEC_DEQUE_ITER: [&str; 5] = ["alloc", "collections", "vec_deque", "VecDeque", "iter"];
@@ -150,18 +110,10 @@ pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"];
 pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"];
 pub const VEC_WITH_CAPACITY: [&str; 4] = ["alloc", "vec", "Vec", "with_capacity"];
 pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"];
-pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"];
-pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"];
-pub const PTR_NON_NULL: [&str; 4] = ["core", "ptr", "non_null", "NonNull"];
 pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"];
-pub const INSTANT: [&str; 3] = ["std", "time", "Instant"];
 pub const VEC_IS_EMPTY: [&str; 4] = ["alloc", "vec", "Vec", "is_empty"];
 pub const VEC_POP: [&str; 4] = ["alloc", "vec", "Vec", "pop"];
 pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"];
 pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"];
-pub const FORMATTER: [&str; 3] = ["core", "fmt", "Formatter"];
-pub const DEBUG_STRUCT: [&str; 4] = ["core", "fmt", "builders", "DebugStruct"];
-pub const ORD_CMP: [&str; 4] = ["core", "cmp", "Ord", "cmp"];
 #[expect(clippy::invalid_paths)] // not sure why it thinks this, it works so
 pub const BOOL_THEN: [&str; 4] = ["core", "bool", "<impl bool>", "then"];
-pub const ARRAY_INTO_ITER: [&str; 4] = ["core", "array", "iter", "IntoIter"];
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 17233058c9c..55f9cb27ad4 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -272,6 +272,7 @@ fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &B
             | ProjectionElem::Downcast(..)
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Deref
+            | ProjectionElem::Subtype(_)
             | ProjectionElem::Index(_) => {},
         }
     }
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 604dc76912e..2d305a63eca 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -31,7 +31,7 @@ use rustc_trait_selection::traits::{Obligation, ObligationCause};
 use std::assert_matches::debug_assert_matches;
 use std::iter;
 
-use crate::{match_def_path, path_res, paths};
+use crate::{match_def_path, path_res};
 
 mod type_certainty;
 pub use type_certainty::expr_type_is_certain;
@@ -461,10 +461,8 @@ pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
         else if is_type_lang_item(cx, ty, LangItem::OwnedBox)
             || matches!(
                 get_type_diagnostic_name(cx, ty),
-                Some(sym::HashSet | sym::Rc | sym::Arc | sym::cstring_type)
+                Some(sym::HashSet | sym::Rc | sym::Arc | sym::cstring_type | sym::RcWeak | sym::ArcWeak)
             )
-            || match_type(cx, ty, &paths::WEAK_RC)
-            || match_type(cx, ty, &paths::WEAK_ARC)
         {
             // Check all of the generic arguments.
             if let ty::Adt(_, subs) = ty.kind() {
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs
index b5ff3a54205..60be2978813 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs
@@ -11,6 +11,6 @@ fn main() {
     const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
     const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
 
-    // Don't lint, not yet a diagnostic or language item
-    const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"];
+    // Don't lint, not a diagnostic or language item
+    const OPS_MOD: [&str; 5] = ["core", "ops"];
 }
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
index 58b1fd92b5d..076786329cd 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
@@ -19,8 +19,8 @@ LL |     const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"]
 error: hardcoded path to a diagnostic item
   --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
    |
-LL |     const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     const OPS_MOD: [&str; 5] = ["core", "ops"];
+   |                                ^^^^^^^^^^^^^^^
    |
    = help: convert all references to use `sym::deref_method`
 
diff --git a/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr b/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr
index a52e1fcb9e3..8b9d159b59c 100644
--- a/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr
+++ b/src/tools/clippy/tests/ui-toml/too_many_arguments/too_many_arguments.stderr
@@ -2,7 +2,7 @@ error: this function has too many arguments (11/10)
   --> $DIR/too_many_arguments.rs:4:1
    |
 LL | fn too_many(p1: u8, p2: u8, p3: u8, p4: u8, p5: u8, p6: u8, p7: u8, p8: u8, p9: u8, p10: u8, p11: u8) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::too-many-arguments` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]`
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10645.stderr b/src/tools/clippy/tests/ui/crashes/ice-10645.stderr
index fc5347c86cd..7fc62d4fcf8 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-10645.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-10645.stderr
@@ -1,8 +1,8 @@
 warning: future cannot be sent between threads safely
-  --> $DIR/ice-10645.rs:5:35
+  --> $DIR/ice-10645.rs:5:1
    |
 LL | pub async fn bar<'a, T: 'a>(_: T) {}
-   |                                   ^ future returned by `bar` is not `Send`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `bar` is not `Send`
    |
 note: captured value is not `Send`
   --> $DIR/ice-10645.rs:5:29
diff --git a/src/tools/clippy/tests/ui/functions.stderr b/src/tools/clippy/tests/ui/functions.stderr
index 371ea161260..4b06cd03889 100644
--- a/src/tools/clippy/tests/ui/functions.stderr
+++ b/src/tools/clippy/tests/ui/functions.stderr
@@ -2,7 +2,7 @@ error: this function has too many arguments (8/7)
   --> $DIR/functions.rs:8:1
    |
 LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::too-many-arguments` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]`
@@ -17,7 +17,7 @@ LL | |     two: u32,
 ...  |
 LL | |     eight: ()
 LL | | ) {
-   | |__^
+   | |_^
 
 error: this function has too many arguments (8/7)
   --> $DIR/functions.rs:48:5
@@ -29,7 +29,7 @@ error: this function has too many arguments (8/7)
   --> $DIR/functions.rs:58:5
    |
 LL |     fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this public function might dereference a raw pointer but is not marked `unsafe`
   --> $DIR/functions.rs:68:34
diff --git a/src/tools/clippy/tests/ui/future_not_send.stderr b/src/tools/clippy/tests/ui/future_not_send.stderr
index f43e3c8ff9f..7ef4947f1d6 100644
--- a/src/tools/clippy/tests/ui/future_not_send.stderr
+++ b/src/tools/clippy/tests/ui/future_not_send.stderr
@@ -1,8 +1,8 @@
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:7:62
+  --> $DIR/future_not_send.rs:7:1
    |
 LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
-   |                                                              ^^^^ future returned by `private_future` is not `Send`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
   --> $DIR/future_not_send.rs:9:20
@@ -23,10 +23,10 @@ LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    = help: to override `-D warnings` add `#[allow(clippy::future_not_send)]`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:12:42
+  --> $DIR/future_not_send.rs:12:1
    |
 LL | pub async fn public_future(rc: Rc<[u8]>) {
-   |                                          ^ future returned by `public_future` is not `Send`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
   --> $DIR/future_not_send.rs:14:20
@@ -39,10 +39,10 @@ LL |     async { true }.await;
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:21:63
+  --> $DIR/future_not_send.rs:21:1
    |
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
-   |                                                               ^^^^ future returned by `private_future2` is not `Send`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future2` is not `Send`
    |
 note: captured value is not `Send`
   --> $DIR/future_not_send.rs:21:26
@@ -58,10 +58,10 @@ LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
    = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:26:43
+  --> $DIR/future_not_send.rs:26:1
    |
 LL | pub async fn public_future2(rc: Rc<[u8]>) {}
-   |                                           ^ future returned by `public_future2` is not `Send`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future2` is not `Send`
    |
 note: captured value is not `Send`
   --> $DIR/future_not_send.rs:26:29
@@ -71,10 +71,10 @@ LL | pub async fn public_future2(rc: Rc<[u8]>) {}
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:38:39
+  --> $DIR/future_not_send.rs:38:5
    |
 LL |     async fn private_future(&self) -> usize {
-   |                                       ^^^^^ future returned by `private_future` is not `Send`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
   --> $DIR/future_not_send.rs:40:24
@@ -87,10 +87,10 @@ LL |         async { true }.await;
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:44:39
+  --> $DIR/future_not_send.rs:44:5
    |
 LL |     pub async fn public_future(&self) {
-   |                                       ^ future returned by `public_future` is not `Send`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send`
    |
 note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
   --> $DIR/future_not_send.rs:44:32
@@ -100,10 +100,13 @@ LL |     pub async fn public_future(&self) {
    = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:55:37
+  --> $DIR/future_not_send.rs:55:1
    |
-LL | async fn generic_future<T>(t: T) -> T
-   |                                     ^ future returned by `generic_future` is not `Send`
+LL | / async fn generic_future<T>(t: T) -> T
+LL | |
+LL | | where
+LL | |     T: Send,
+   | |____________^ future returned by `generic_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
   --> $DIR/future_not_send.rs:61:20
@@ -115,10 +118,10 @@ LL |     async { true }.await;
    = note: `T` doesn't implement `std::marker::Sync`
 
 error: future cannot be sent between threads safely
-  --> $DIR/future_not_send.rs:73:34
+  --> $DIR/future_not_send.rs:73:1
    |
 LL | async fn unclear_future<T>(t: T) {}
-   |                                  ^ future returned by `unclear_future` is not `Send`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `unclear_future` is not `Send`
    |
 note: captured value is not `Send`
   --> $DIR/future_not_send.rs:73:28
diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
index 1ee048bf7f6..e1b95aa5776 100644
--- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
@@ -4,14 +4,18 @@
 //@no-rustfix
 use std::sync::atomic::Ordering; // #[non_exhaustive] enum
 
+fn repeat() -> ! {
+    panic!()
+}
+
 pub fn f(x: Ordering) {
     match x {
         Ordering::Relaxed => println!("relaxed"),
         Ordering::Release => println!("release"),
         Ordering::Acquire => println!("acquire"),
-        Ordering::AcqRel | Ordering::SeqCst => panic!(),
+        Ordering::AcqRel | Ordering::SeqCst => repeat(),
         #[deny(non_exhaustive_omitted_patterns)]
-        _ => panic!(),
+        _ => repeat(),
     }
 }
 
@@ -25,8 +29,8 @@ mod f {
             Ordering::Relaxed => println!("relaxed"),
             Ordering::Release => println!("release"),
             Ordering::Acquire => println!("acquire"),
-            Ordering::AcqRel | Ordering::SeqCst => panic!(),
-            _ => panic!(),
+            Ordering::AcqRel | Ordering::SeqCst => repeat(),
+            _ => repeat(),
         }
     }
 }
@@ -38,9 +42,9 @@ pub fn g(x: Ordering) {
         Ordering::Relaxed => println!("relaxed"),
         Ordering::Release => println!("release"),
         Ordering::Acquire => println!("acquire"),
-        Ordering::AcqRel | Ordering::SeqCst => panic!(),
+        Ordering::AcqRel | Ordering::SeqCst => repeat(),
         //~^ ERROR: this match arm has an identical body to the `_` wildcard arm
-        _ => panic!(),
+        _ => repeat(),
     }
 }
 
@@ -52,9 +56,9 @@ mod g {
             Ordering::Relaxed => println!("relaxed"),
             Ordering::Release => println!("release"),
             Ordering::Acquire => println!("acquire"),
-            Ordering::AcqRel | Ordering::SeqCst => panic!(),
+            Ordering::AcqRel | Ordering::SeqCst => repeat(),
             //~^ ERROR: this match arm has an identical body to the `_` wildcard arm
-            _ => panic!(),
+            _ => repeat(),
         }
     }
 }
diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr
index a039536338b..ae6b02ab1b5 100644
--- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr
@@ -1,29 +1,29 @@
 error: this match arm has an identical body to the `_` wildcard arm
-  --> $DIR/match_same_arms_non_exhaustive.rs:41:9
+  --> $DIR/match_same_arms_non_exhaustive.rs:45:9
    |
-LL |         Ordering::AcqRel | Ordering::SeqCst => panic!(),
+LL |         Ordering::AcqRel | Ordering::SeqCst => repeat(),
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
    |
    = help: or try changing either arm body
 note: `_` wildcard arm here
-  --> $DIR/match_same_arms_non_exhaustive.rs:43:9
+  --> $DIR/match_same_arms_non_exhaustive.rs:47:9
    |
-LL |         _ => panic!(),
+LL |         _ => repeat(),
    |         ^^^^^^^^^^^^^
    = note: `-D clippy::match-same-arms` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::match_same_arms)]`
 
 error: this match arm has an identical body to the `_` wildcard arm
-  --> $DIR/match_same_arms_non_exhaustive.rs:55:13
+  --> $DIR/match_same_arms_non_exhaustive.rs:59:13
    |
-LL |             Ordering::AcqRel | Ordering::SeqCst => panic!(),
+LL |             Ordering::AcqRel | Ordering::SeqCst => repeat(),
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
    |
    = help: or try changing either arm body
 note: `_` wildcard arm here
-  --> $DIR/match_same_arms_non_exhaustive.rs:57:13
+  --> $DIR/match_same_arms_non_exhaustive.rs:61:13
    |
-LL |             _ => panic!(),
+LL |             _ => repeat(),
    |             ^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui/must_use_unit.stderr b/src/tools/clippy/tests/ui/must_use_unit.stderr
index e67d9b5b9d8..f2ee185857d 100644
--- a/src/tools/clippy/tests/ui/must_use_unit.stderr
+++ b/src/tools/clippy/tests/ui/must_use_unit.stderr
@@ -4,7 +4,7 @@ error: this unit-returning function has a `#[must_use]` attribute
 LL | #[must_use]
    | ----------- help: remove the attribute
 LL | pub fn must_use_default() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::must-use-unit` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::must_use_unit)]`
@@ -23,7 +23,7 @@ error: this unit-returning function has a `#[must_use]` attribute
 LL | #[must_use = "With note"]
    | ------------------------- help: remove the attribute
 LL | pub fn must_use_with_note() {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed
index 87df1f8cb08..b17343aa9ba 100644
--- a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.fixed
@@ -23,7 +23,7 @@ fn unwrap_option_none() {
     let _val: u16 = 234;
     let _val: u16 = 234;
     let _val: u16 = { 234 };
-    let _val: u16 =  { 234 };
+    let _val: u16 = { 234 };
 
     panic!();
     panic!("this always happens");
@@ -31,7 +31,7 @@ fn unwrap_option_none() {
     234;
     234;
     { 234 };
-     { 234 };
+    { 234 };
 }
 
 fn unwrap_result_ok() {
diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr
index 013907f59c4..4940091be60 100644
--- a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr
@@ -116,7 +116,7 @@ LL |     let _val: u16 = None.unwrap_or_else(|| -> u16 { 234 });
 help: remove the `None` and `unwrap_or_else()`
    |
 LL -     let _val: u16 = None.unwrap_or_else(|| -> u16 { 234 });
-LL +     let _val: u16 =  { 234 };
+LL +     let _val: u16 = { 234 };
    |
 
 error: used `unwrap()` on `None` value
@@ -187,7 +187,7 @@ LL |     None::<u16>.unwrap_or_else(|| -> u16 { 234 });
 help: remove the `None` and `unwrap_or_else()`
    |
 LL -     None::<u16>.unwrap_or_else(|| -> u16 { 234 });
-LL +      { 234 };
+LL +     { 234 };
    |
 
 error: used `unwrap()` on `Ok` value
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index b60de8344d9..dc2601e9e9f 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-bb6c66be3793ac5c738eeac91ecdc4b99388d0b4
+1bc0463b183392ad4e0ae9c5f7a76630d487230d
diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs
index 31aabca09f3..8000c9e7fdd 100644
--- a/src/tools/opt-dist/src/tests.rs
+++ b/src/tools/opt-dist/src/tests.rs
@@ -61,7 +61,7 @@ pub fn run_tests(env: &Environment) -> anyhow::Result<()> {
 
     let config_content = format!(
         r#"profile = "user"
-changelog-seen = 2
+change-id = 115898
 
 [build]
 rustc = "{rustc}"
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index d5bc38303e0..002cffa9b0c 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -2599,7 +2599,8 @@ fn rewrite_fn_base(
     if where_clause_str.is_empty() {
         if let ast::FnRetTy::Default(ret_span) = fd.output {
             match recover_missing_comment_in_span(
-                mk_sp(params_span.hi(), ret_span.hi()),
+                // from after the closing paren to right before block or semicolon
+                mk_sp(ret_span.lo(), span.hi()),
                 shape,
                 context,
                 last_line_width(&result),
diff --git a/src/version b/src/version
index dc87e8af82f..7c7053aa238 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.74.0
+1.75.0
diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
index a7c9e4845c7..e46b902df07 100644
--- a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
+++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
@@ -9,6 +9,7 @@
 // [basic] compile-flags: -Z stack-protector=basic
 // [none] compile-flags: -Z stack-protector=none
 // compile-flags: -C opt-level=2 -Z merge-functions=disabled
+// min-llvm-version: 17.0.2
 
 #![crate_type = "lib"]
 
@@ -371,7 +372,7 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) {
 
 
     // all: __stack_chk_fail
-    // strong: __stack_chk_fail
+    // strong-NOT: __stack_chk_fail
     // basic-NOT: __stack_chk_fail
     // none-NOT: __stack_chk_fail
     // missing-NOT: __stack_chk_fail
diff --git a/tests/codegen/issue-97217.rs b/tests/codegen/issue-97217.rs
new file mode 100644
index 00000000000..af7345442fc
--- /dev/null
+++ b/tests/codegen/issue-97217.rs
@@ -0,0 +1,22 @@
+// compile-flags: -C opt-level=3
+// ignore-debug: the debug assertions get in the way
+// min-llvm-version: 17.0.2
+#![crate_type = "lib"]
+
+// Regression test for issue 97217 (the following should result in no allocations)
+
+// CHECK-LABEL: @issue97217
+#[no_mangle]
+pub fn issue97217() -> i32 {
+    // drop_in_place should be inlined and never appear
+    // CHECK-NOT: drop_in_place
+
+    // __rust_alloc should be optimized out
+    // CHECK-NOT: __rust_alloc
+
+    let v1 = vec![5, 6, 7];
+    let v1_iter = v1.iter();
+    let total: i32 = v1_iter.sum();
+    println!("{}",total);
+    total
+}
diff --git a/tests/codegen/simd/simd-wide-sum.rs b/tests/codegen/simd/simd-wide-sum.rs
index 3116f9597bc..6e7d3d9316a 100644
--- a/tests/codegen/simd/simd-wide-sum.rs
+++ b/tests/codegen/simd/simd-wide-sum.rs
@@ -11,14 +11,14 @@
 #![feature(portable_simd)]
 
 use std::simd::{Simd, SimdUint};
-const N: usize = 8;
+const N: usize = 16;
 
 #[no_mangle]
 // CHECK-LABEL: @wider_reduce_simd
 pub fn wider_reduce_simd(x: Simd<u8, N>) -> u16 {
-    // CHECK: zext <8 x i8>
-    // CHECK-SAME: to <8 x i16>
-    // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
+    // CHECK: zext <16 x i8>
+    // CHECK-SAME: to <16 x i16>
+    // CHECK: call i16 @llvm.vector.reduce.add.v16i16(<16 x i16>
     let x: Simd<u16, N> = x.cast();
     x.reduce_sum()
 }
@@ -26,9 +26,9 @@ pub fn wider_reduce_simd(x: Simd<u8, N>) -> u16 {
 #[no_mangle]
 // CHECK-LABEL: @wider_reduce_loop
 pub fn wider_reduce_loop(x: Simd<u8, N>) -> u16 {
-    // CHECK: zext <8 x i8>
-    // CHECK-SAME: to <8 x i16>
-    // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
+    // CHECK: zext <16 x i8>
+    // CHECK-SAME: to <16 x i16>
+    // CHECK: call i16 @llvm.vector.reduce.add.v16i16(<16 x i16>
     let mut sum = 0_u16;
     for i in 0..N {
         sum += u16::from(x[i]);
@@ -39,9 +39,9 @@ pub fn wider_reduce_loop(x: Simd<u8, N>) -> u16 {
 #[no_mangle]
 // CHECK-LABEL: @wider_reduce_iter
 pub fn wider_reduce_iter(x: Simd<u8, N>) -> u16 {
-    // CHECK: zext <8 x i8>
-    // CHECK-SAME: to <8 x i16>
-    // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
+    // CHECK: zext <16 x i8>
+    // CHECK-SAME: to <16 x i16>
+    // CHECK: call i16 @llvm.vector.reduce.add.v16i16(<16 x i16>
     x.as_array().iter().copied().map(u16::from).sum()
 }
 
@@ -52,8 +52,8 @@ pub fn wider_reduce_iter(x: Simd<u8, N>) -> u16 {
 #[no_mangle]
 // CHECK-LABEL: @wider_reduce_into_iter
 pub fn wider_reduce_into_iter(x: Simd<u8, N>) -> u16 {
-    // CHECK: zext <8 x i8>
-    // CHECK-SAME: to <8 x i16>
-    // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
+    // FIXME: It would be nice if this was exactly the same as the above tests,
+    // but at the time of writing this comment, that didn't happen on LLVM main.
+    // CHECK: call i16 @llvm.vector.reduce.add
     x.to_array().into_iter().map(u16::from).sum()
 }
diff --git a/tests/codegen/unwind-landingpad-cold.rs b/tests/codegen/unwind-landingpad-cold.rs
new file mode 100644
index 00000000000..3a902a7d712
--- /dev/null
+++ b/tests/codegen/unwind-landingpad-cold.rs
@@ -0,0 +1,16 @@
+// compile-flags: -Cno-prepopulate-passes
+// needs-unwind
+// min-llvm-version: 17.0.2
+#![crate_type = "lib"]
+
+// This test checks that drop calls in unwind landing pads
+// get the `cold` attribute.
+
+// CHECK-LABEL: @check_cold
+// CHECK: {{(call|invoke) void .+}}drop_in_place{{.+}} [[ATTRIBUTES:#[0-9]+]]
+// CHECK: attributes [[ATTRIBUTES]] = { cold }
+#[no_mangle]
+pub fn check_cold(f: fn(), x: Box<u32>) {
+    // this may unwind
+    f();
+}
diff --git a/tests/codegen/unwind-landingpad-inline.rs b/tests/codegen/unwind-landingpad-inline.rs
new file mode 100644
index 00000000000..0774cefdd2d
--- /dev/null
+++ b/tests/codegen/unwind-landingpad-inline.rs
@@ -0,0 +1,39 @@
+// min-llvm-version: 17.0.2
+// compile-flags: -Copt-level=3
+// ignore-debug: the debug assertions get in the way
+#![crate_type = "lib"]
+
+// This test checks that we can inline drop_in_place in
+// unwind landing pads.
+
+// Without inlining, the box pointers escape via the call to drop_in_place,
+// and LLVM will not optimize out the pointer comparison.
+// With inlining, everything should be optimized out.
+// See https://github.com/rust-lang/rust/issues/46515
+// CHECK-LABEL: @check_no_escape_in_landingpad
+// CHECK: start:
+// CHECK-NEXT: __rust_no_alloc_shim_is_unstable
+// CHECK-NEXT: __rust_no_alloc_shim_is_unstable
+// CHECK-NEXT: ret void
+#[no_mangle]
+pub fn check_no_escape_in_landingpad(f: fn()) {
+    let x = &*Box::new(0);
+    let y = &*Box::new(0);
+
+    if x as *const _ == y as *const _ {
+        f();
+    }
+}
+
+// Without inlining, the compiler can't tell that
+// dropping an empty string (in a landing pad) does nothing.
+// With inlining, the landing pad should be optimized out.
+// See https://github.com/rust-lang/rust/issues/87055
+// CHECK-LABEL: @check_eliminate_noop_drop
+// CHECK: call void %g()
+// CHECK-NEXT: ret void
+#[no_mangle]
+pub fn check_eliminate_noop_drop(g: fn()) {
+    let _var = String::new();
+    g();
+}
diff --git a/tests/coverage-map/status-quo/async.cov-map b/tests/coverage-map/status-quo/async.cov-map
index 5f28252ef80..598791537ad 100644
--- a/tests/coverage-map/status-quo/async.cov-map
+++ b/tests/coverage-map/status-quo/async.cov-map
@@ -38,42 +38,40 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 13, 20) to (start + 0, 25)
 
 Function name: async::e (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 01, 00, 14]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 0f, 01, 00, 14]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 20)
+- Code(Zero) at (prev + 15, 1) to (start + 0, 20)
 
 Function name: async::e::{closure#0} (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 14, 00, 19]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 0f, 14, 00, 19]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 15, 20) to (start + 0, 25)
+- Code(Zero) at (prev + 15, 20) to (start + 0, 25)
 
 Function name: async::executor::block_on::<core::pin::Pin<&mut async::i::{closure#0}>>
-Raw bytes (44): 0x[01, 01, 05, 0b, 05, 01, 05, 01, 05, 02, 00, 02, 00, 06, 01, 6e, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 0f, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 13, 02, 05, 00, 06]
+Raw bytes (40): 0x[01, 01, 03, 0b, 05, 01, 05, 01, 05, 06, 01, 6e, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 02, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 02, 02, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 5
+Number of expressions: 3
 - expression 0 operands: lhs = Expression(2, Add), rhs = Counter(1)
 - expression 1 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 2 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero
-- expression 4 operands: lhs = Expression(0, Sub), rhs = Zero
 Number of file 0 mappings: 6
 - Code(Counter(0)) at (prev + 110, 5) to (start + 10, 54)
 - Code(Expression(0, Sub)) at (prev + 13, 32) to (start + 0, 35)
     = ((c0 + c1) - c1)
 - Code(Expression(2, Add)) at (prev + 0, 39) to (start + 0, 73)
     = (c0 + c1)
-- Code(Expression(3, Add)) at (prev + 1, 23) to (start + 0, 26)
-    = (((c0 + c1) - c1) + Zero)
+- Code(Expression(0, Sub)) at (prev + 1, 23) to (start + 0, 26)
+    = ((c0 + c1) - c1)
 - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 15)
-- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6)
-    = (((c0 + c1) - c1) + Zero)
+- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6)
+    = ((c0 + c1) - c1)
 
 Function name: async::executor::block_on::VTABLE::{closure#0}
 Raw bytes (9): 0x[01, 01, 00, 01, 01, 72, 11, 00, 33]
@@ -124,20 +122,20 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 17, 20) to (start + 0, 25)
 
 Function name: async::foo (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 00, 1e]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 13, 01, 00, 1e]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 30)
+- Code(Zero) at (prev + 19, 1) to (start + 0, 30)
 
 Function name: async::foo::{closure#0} (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 1e, 00, 2d]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 13, 1e, 00, 2d]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 19, 30) to (start + 0, 45)
+- Code(Zero) at (prev + 19, 30) to (start + 0, 45)
 
 Function name: async::g
 Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 00, 17]
@@ -148,14 +146,14 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 21, 1) to (start + 0, 23)
 
 Function name: async::g::{closure#0} (unused)
-Raw bytes (69): 0x[01, 01, 00, 0d, 00, 15, 17, 01, 0c, 00, 02, 09, 00, 0a, 01, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
+Raw bytes (69): 0x[01, 01, 00, 0d, 00, 15, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 13
 - Code(Zero) at (prev + 21, 23) to (start + 1, 12)
 - Code(Zero) at (prev + 2, 9) to (start + 0, 10)
-- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 17)
+- Code(Zero) at (prev + 0, 14) to (start + 0, 17)
 - Code(Zero) at (prev + 0, 18) to (start + 0, 23)
 - Code(Zero) at (prev + 0, 27) to (start + 0, 28)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 34)
@@ -176,14 +174,14 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 29, 1) to (start + 0, 22)
 
 Function name: async::h::{closure#0} (unused)
-Raw bytes (44): 0x[01, 01, 00, 08, 00, 1d, 16, 03, 0c, 00, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 00, 00, 14, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
+Raw bytes (44): 0x[01, 01, 00, 08, 00, 1d, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 13, 00, 00, 14, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 8
 - Code(Zero) at (prev + 29, 22) to (start + 3, 12)
 - Code(Zero) at (prev + 4, 9) to (start + 0, 10)
-- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 19)
+- Code(Zero) at (prev + 0, 14) to (start + 0, 19)
 - Code(Zero) at (prev + 0, 20) to (start + 0, 25)
 - Code(Zero) at (prev + 0, 26) to (start + 0, 27)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 34)
@@ -199,58 +197,46 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 38, 1) to (start + 0, 19)
 
 Function name: async::i::{closure#0}
-Raw bytes (84): 0x[01, 01, 05, 01, 00, 0d, 00, 1d, 00, 19, 13, 1d, 21, 0e, 01, 26, 13, 04, 0c, 0d, 05, 09, 00, 0a, 03, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 07, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 0b, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 0f, 02, 01, 00, 02]
+Raw bytes (78): 0x[01, 01, 02, 19, 07, 1d, 21, 0e, 01, 26, 13, 04, 0c, 0d, 05, 09, 00, 0a, 01, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 0d, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 1d, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 5
-- expression 0 operands: lhs = Counter(0), rhs = Zero
-- expression 1 operands: lhs = Counter(3), rhs = Zero
-- expression 2 operands: lhs = Counter(7), rhs = Zero
-- expression 3 operands: lhs = Counter(6), rhs = Expression(4, Add)
-- expression 4 operands: lhs = Counter(7), rhs = Counter(8)
+Number of expressions: 2
+- expression 0 operands: lhs = Counter(6), rhs = Expression(1, Add)
+- expression 1 operands: lhs = Counter(7), rhs = Counter(8)
 Number of file 0 mappings: 14
 - Code(Counter(0)) at (prev + 38, 19) to (start + 4, 12)
 - Code(Counter(3)) at (prev + 5, 9) to (start + 0, 10)
-- Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 18)
-    = (c0 + Zero)
+- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 18)
 - Code(Counter(1)) at (prev + 0, 19) to (start + 0, 24)
 - Code(Counter(2)) at (prev + 0, 28) to (start + 0, 33)
-- Code(Expression(1, Add)) at (prev + 0, 39) to (start + 0, 42)
-    = (c3 + Zero)
+- Code(Counter(3)) at (prev + 0, 39) to (start + 0, 42)
 - Code(Counter(5)) at (prev + 0, 43) to (start + 0, 48)
 - Code(Counter(7)) at (prev + 1, 9) to (start + 0, 10)
 - Code(Counter(4)) at (prev + 0, 14) to (start + 0, 17)
 - Code(Counter(9)) at (prev + 0, 18) to (start + 0, 23)
 - Code(Counter(10)) at (prev + 0, 27) to (start + 0, 32)
-- Code(Expression(2, Add)) at (prev + 0, 36) to (start + 0, 38)
-    = (c7 + Zero)
+- Code(Counter(7)) at (prev + 0, 36) to (start + 0, 38)
 - Code(Counter(8)) at (prev + 1, 14) to (start + 0, 16)
-- Code(Expression(3, Add)) at (prev + 2, 1) to (start + 0, 2)
+- Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2)
     = (c6 + (c7 + c8))
 
 Function name: async::j
-Raw bytes (59): 0x[01, 01, 05, 01, 00, 05, 00, 09, 00, 05, 13, 09, 0d, 09, 01, 31, 01, 13, 0c, 05, 14, 09, 00, 0a, 03, 00, 0e, 00, 1b, 07, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 0b, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 0f, 02, 01, 00, 02]
+Raw bytes (53): 0x[01, 01, 02, 05, 07, 09, 0d, 09, 01, 31, 01, 13, 0c, 05, 14, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 5
-- expression 0 operands: lhs = Counter(0), rhs = Zero
-- expression 1 operands: lhs = Counter(1), rhs = Zero
-- expression 2 operands: lhs = Counter(2), rhs = Zero
-- expression 3 operands: lhs = Counter(1), rhs = Expression(4, Add)
-- expression 4 operands: lhs = Counter(2), rhs = Counter(3)
+Number of expressions: 2
+- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add)
+- expression 1 operands: lhs = Counter(2), rhs = Counter(3)
 Number of file 0 mappings: 9
 - Code(Counter(0)) at (prev + 49, 1) to (start + 19, 12)
 - Code(Counter(1)) at (prev + 20, 9) to (start + 0, 10)
-- Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 27)
-    = (c0 + Zero)
-- Code(Expression(1, Add)) at (prev + 0, 31) to (start + 0, 39)
-    = (c1 + Zero)
+- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 27)
+- Code(Counter(1)) at (prev + 0, 31) to (start + 0, 39)
 - Code(Counter(2)) at (prev + 1, 9) to (start + 0, 10)
 - Code(Counter(4)) at (prev + 0, 14) to (start + 0, 26)
-- Code(Expression(2, Add)) at (prev + 0, 30) to (start + 0, 32)
-    = (c2 + Zero)
+- Code(Counter(2)) at (prev + 0, 30) to (start + 0, 32)
 - Code(Counter(3)) at (prev + 1, 14) to (start + 0, 16)
-- Code(Expression(3, Add)) at (prev + 2, 1) to (start + 0, 2)
+- Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2)
     = (c1 + (c2 + c3))
 
 Function name: async::j::c
@@ -285,12 +271,12 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 67, 5) to (start + 0, 23)
 
 Function name: async::k (unused)
-Raw bytes (29): 0x[01, 01, 00, 05, 01, 4b, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
+Raw bytes (29): 0x[01, 01, 00, 05, 00, 4b, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 5
-- Code(Counter(0)) at (prev + 75, 1) to (start + 1, 12)
+- Code(Zero) at (prev + 75, 1) to (start + 1, 12)
 - Code(Zero) at (prev + 2, 14) to (start + 0, 16)
 - Code(Zero) at (prev + 1, 14) to (start + 0, 16)
 - Code(Zero) at (prev + 1, 14) to (start + 0, 16)
@@ -323,12 +309,12 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 91, 1) to (start + 0, 25)
 
 Function name: async::m::{closure#0} (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 5b, 19, 00, 22]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 5b, 19, 00, 22]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 91, 25) to (start + 0, 34)
+- Code(Zero) at (prev + 91, 25) to (start + 0, 34)
 
 Function name: async::main
 Raw bytes (9): 0x[01, 01, 00, 01, 01, 5d, 01, 08, 02]
diff --git a/tests/coverage-map/status-quo/async2.cov-map b/tests/coverage-map/status-quo/async2.cov-map
index fe74dcd8840..cc7aed9aee3 100644
--- a/tests/coverage-map/status-quo/async2.cov-map
+++ b/tests/coverage-map/status-quo/async2.cov-map
@@ -38,48 +38,44 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 19, 36) to (start + 2, 2)
 
 Function name: async2::executor::block_on::<async2::async_func::{closure#0}>
-Raw bytes (44): 0x[01, 01, 05, 0b, 05, 01, 05, 01, 05, 02, 00, 02, 00, 06, 01, 27, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 0f, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 13, 02, 05, 00, 06]
+Raw bytes (40): 0x[01, 01, 03, 0b, 05, 01, 05, 01, 05, 06, 01, 27, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 02, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 02, 02, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 5
+Number of expressions: 3
 - expression 0 operands: lhs = Expression(2, Add), rhs = Counter(1)
 - expression 1 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 2 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero
-- expression 4 operands: lhs = Expression(0, Sub), rhs = Zero
 Number of file 0 mappings: 6
 - Code(Counter(0)) at (prev + 39, 5) to (start + 10, 54)
 - Code(Expression(0, Sub)) at (prev + 13, 32) to (start + 0, 35)
     = ((c0 + c1) - c1)
 - Code(Expression(2, Add)) at (prev + 0, 39) to (start + 0, 73)
     = (c0 + c1)
-- Code(Expression(3, Add)) at (prev + 1, 23) to (start + 0, 26)
-    = (((c0 + c1) - c1) + Zero)
+- Code(Expression(0, Sub)) at (prev + 1, 23) to (start + 0, 26)
+    = ((c0 + c1) - c1)
 - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 15)
-- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6)
-    = (((c0 + c1) - c1) + Zero)
+- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6)
+    = ((c0 + c1) - c1)
 
 Function name: async2::executor::block_on::<async2::async_func_just_println::{closure#0}>
-Raw bytes (44): 0x[01, 01, 05, 0b, 05, 01, 05, 01, 05, 02, 00, 02, 00, 06, 01, 27, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 0f, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 13, 02, 05, 00, 06]
+Raw bytes (40): 0x[01, 01, 03, 0b, 05, 01, 05, 01, 05, 06, 01, 27, 05, 0a, 36, 02, 0d, 20, 00, 23, 0b, 00, 27, 00, 49, 02, 01, 17, 00, 1a, 05, 01, 0e, 00, 0f, 02, 02, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 5
+Number of expressions: 3
 - expression 0 operands: lhs = Expression(2, Add), rhs = Counter(1)
 - expression 1 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 2 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero
-- expression 4 operands: lhs = Expression(0, Sub), rhs = Zero
 Number of file 0 mappings: 6
 - Code(Counter(0)) at (prev + 39, 5) to (start + 10, 54)
 - Code(Expression(0, Sub)) at (prev + 13, 32) to (start + 0, 35)
     = ((c0 + c1) - c1)
 - Code(Expression(2, Add)) at (prev + 0, 39) to (start + 0, 73)
     = (c0 + c1)
-- Code(Expression(3, Add)) at (prev + 1, 23) to (start + 0, 26)
-    = (((c0 + c1) - c1) + Zero)
+- Code(Expression(0, Sub)) at (prev + 1, 23) to (start + 0, 26)
+    = ((c0 + c1) - c1)
 - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 15)
-- Code(Expression(4, Add)) at (prev + 2, 5) to (start + 0, 6)
-    = (((c0 + c1) - c1) + Zero)
+- Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6)
+    = ((c0 + c1) - c1)
 
 Function name: async2::executor::block_on::VTABLE::{closure#0}
 Raw bytes (9): 0x[01, 01, 00, 01, 01, 2b, 11, 00, 33]
diff --git a/tests/coverage-map/status-quo/closure.cov-map b/tests/coverage-map/status-quo/closure.cov-map
index 7dbf6ec834d..522c1e73afe 100644
--- a/tests/coverage-map/status-quo/closure.cov-map
+++ b/tests/coverage-map/status-quo/closure.cov-map
@@ -1,77 +1,36 @@
 Function name: closure::main
-Raw bytes (170): 0x[01, 01, 17, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 00, 01, 05, 05, 5a, 01, 05, 18, 01, 08, 01, 0f, 0d, 03, 16, 0e, 06, 0a, 07, 10, 05, 13, 0d, 0b, 1a, 0e, 06, 0a, 0f, 10, 05, 0c, 16, 13, 16, 05, 0d, 18, 17, 19, 09, 01, 1e, 1b, 04, 09, 00, 29, 1f, 01, 09, 00, 2d, 23, 01, 09, 00, 24, 27, 05, 09, 00, 24, 2b, 02, 09, 00, 21, 2f, 04, 09, 00, 21, 33, 04, 09, 00, 28, 37, 09, 09, 00, 32, 3b, 04, 09, 00, 33, 3f, 07, 09, 00, 4b, 43, 08, 09, 00, 48, 47, 0a, 09, 00, 47, 4b, 08, 09, 00, 44, 4f, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 5a, 04, 06, 00, 07, 57, 01, 05, 03, 02]
+Raw bytes (128): 0x[01, 01, 02, 01, 05, 05, 02, 18, 01, 08, 01, 0f, 0d, 01, 16, 0e, 06, 0a, 01, 10, 05, 13, 0d, 01, 1a, 0e, 06, 0a, 01, 10, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 06, 00, 07, 07, 01, 05, 03, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 23
-- expression 0 operands: lhs = Counter(0), rhs = Zero
-- expression 1 operands: lhs = Counter(0), rhs = Zero
-- expression 2 operands: lhs = Counter(0), rhs = Zero
-- expression 3 operands: lhs = Counter(0), rhs = Zero
-- expression 4 operands: lhs = Counter(0), rhs = Zero
-- expression 5 operands: lhs = Counter(0), rhs = Zero
-- expression 6 operands: lhs = Counter(0), rhs = Zero
-- expression 7 operands: lhs = Counter(0), rhs = Zero
-- expression 8 operands: lhs = Counter(0), rhs = Zero
-- expression 9 operands: lhs = Counter(0), rhs = Zero
-- expression 10 operands: lhs = Counter(0), rhs = Zero
-- expression 11 operands: lhs = Counter(0), rhs = Zero
-- expression 12 operands: lhs = Counter(0), rhs = Zero
-- expression 13 operands: lhs = Counter(0), rhs = Zero
-- expression 14 operands: lhs = Counter(0), rhs = Zero
-- expression 15 operands: lhs = Counter(0), rhs = Zero
-- expression 16 operands: lhs = Counter(0), rhs = Zero
-- expression 17 operands: lhs = Counter(0), rhs = Zero
-- expression 18 operands: lhs = Counter(0), rhs = Zero
-- expression 19 operands: lhs = Counter(0), rhs = Zero
-- expression 20 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 21 operands: lhs = Counter(1), rhs = Expression(22, Sub)
-- expression 22 operands: lhs = Counter(0), rhs = Counter(1)
+Number of expressions: 2
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
 Number of file 0 mappings: 24
 - Code(Counter(0)) at (prev + 8, 1) to (start + 15, 13)
-- Code(Expression(0, Add)) at (prev + 22, 14) to (start + 6, 10)
-    = (c0 + Zero)
-- Code(Expression(1, Add)) at (prev + 16, 5) to (start + 19, 13)
-    = (c0 + Zero)
-- Code(Expression(2, Add)) at (prev + 26, 14) to (start + 6, 10)
-    = (c0 + Zero)
-- Code(Expression(3, Add)) at (prev + 16, 5) to (start + 12, 22)
-    = (c0 + Zero)
-- Code(Expression(4, Add)) at (prev + 22, 5) to (start + 13, 24)
-    = (c0 + Zero)
-- Code(Expression(5, Add)) at (prev + 25, 9) to (start + 1, 30)
-    = (c0 + Zero)
-- Code(Expression(6, Add)) at (prev + 4, 9) to (start + 0, 41)
-    = (c0 + Zero)
-- Code(Expression(7, Add)) at (prev + 1, 9) to (start + 0, 45)
-    = (c0 + Zero)
-- Code(Expression(8, Add)) at (prev + 1, 9) to (start + 0, 36)
-    = (c0 + Zero)
-- Code(Expression(9, Add)) at (prev + 5, 9) to (start + 0, 36)
-    = (c0 + Zero)
-- Code(Expression(10, Add)) at (prev + 2, 9) to (start + 0, 33)
-    = (c0 + Zero)
-- Code(Expression(11, Add)) at (prev + 4, 9) to (start + 0, 33)
-    = (c0 + Zero)
-- Code(Expression(12, Add)) at (prev + 4, 9) to (start + 0, 40)
-    = (c0 + Zero)
-- Code(Expression(13, Add)) at (prev + 9, 9) to (start + 0, 50)
-    = (c0 + Zero)
-- Code(Expression(14, Add)) at (prev + 4, 9) to (start + 0, 51)
-    = (c0 + Zero)
-- Code(Expression(15, Add)) at (prev + 7, 9) to (start + 0, 75)
-    = (c0 + Zero)
-- Code(Expression(16, Add)) at (prev + 8, 9) to (start + 0, 72)
-    = (c0 + Zero)
-- Code(Expression(17, Add)) at (prev + 10, 9) to (start + 0, 71)
-    = (c0 + Zero)
-- Code(Expression(18, Add)) at (prev + 8, 9) to (start + 0, 68)
-    = (c0 + Zero)
-- Code(Expression(19, Add)) at (prev + 10, 8) to (start + 0, 16)
-    = (c0 + Zero)
+- Code(Counter(0)) at (prev + 22, 14) to (start + 6, 10)
+- Code(Counter(0)) at (prev + 16, 5) to (start + 19, 13)
+- Code(Counter(0)) at (prev + 26, 14) to (start + 6, 10)
+- Code(Counter(0)) at (prev + 16, 5) to (start + 12, 22)
+- Code(Counter(0)) at (prev + 22, 5) to (start + 13, 24)
+- Code(Counter(0)) at (prev + 25, 9) to (start + 1, 30)
+- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 41)
+- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 45)
+- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 36)
+- Code(Counter(0)) at (prev + 5, 9) to (start + 0, 36)
+- Code(Counter(0)) at (prev + 2, 9) to (start + 0, 33)
+- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 33)
+- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 40)
+- Code(Counter(0)) at (prev + 9, 9) to (start + 0, 50)
+- Code(Counter(0)) at (prev + 4, 9) to (start + 0, 51)
+- Code(Counter(0)) at (prev + 7, 9) to (start + 0, 75)
+- Code(Counter(0)) at (prev + 8, 9) to (start + 0, 72)
+- Code(Counter(0)) at (prev + 10, 9) to (start + 0, 71)
+- Code(Counter(0)) at (prev + 8, 9) to (start + 0, 68)
+- Code(Counter(0)) at (prev + 10, 8) to (start + 0, 16)
 - Code(Counter(1)) at (prev + 0, 17) to (start + 4, 6)
-- Code(Expression(22, Sub)) at (prev + 4, 6) to (start + 0, 7)
+- Code(Expression(0, Sub)) at (prev + 4, 6) to (start + 0, 7)
     = (c0 - c1)
-- Code(Expression(21, Add)) at (prev + 1, 5) to (start + 3, 2)
+- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 3, 2)
     = (c1 + (c0 - c1))
 
 Function name: closure::main::{closure#0}
@@ -90,46 +49,45 @@ Number of file 0 mappings: 4
     = (c1 + (c0 - c1))
 
 Function name: closure::main::{closure#10} (unused)
-Raw bytes (10): 0x[01, 01, 00, 01, 01, 9a, 01, 07, 00, 21]
+Raw bytes (10): 0x[01, 01, 00, 01, 00, 9a, 01, 07, 00, 21]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 154, 7) to (start + 0, 33)
+- Code(Zero) at (prev + 154, 7) to (start + 0, 33)
 
 Function name: closure::main::{closure#11} (unused)
-Raw bytes (10): 0x[01, 01, 00, 01, 01, 9e, 01, 07, 00, 21]
+Raw bytes (10): 0x[01, 01, 00, 01, 00, 9e, 01, 07, 00, 21]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 158, 7) to (start + 0, 33)
+- Code(Zero) at (prev + 158, 7) to (start + 0, 33)
 
 Function name: closure::main::{closure#12} (unused)
-Raw bytes (10): 0x[01, 01, 00, 01, 01, a6, 01, 01, 00, 17]
+Raw bytes (10): 0x[01, 01, 00, 01, 00, a6, 01, 01, 00, 17]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 166, 1) to (start + 0, 23)
+- Code(Zero) at (prev + 166, 1) to (start + 0, 23)
 
 Function name: closure::main::{closure#13} (unused)
-Raw bytes (10): 0x[01, 01, 00, 01, 01, ab, 01, 0d, 02, 0e]
+Raw bytes (10): 0x[01, 01, 00, 01, 00, ab, 01, 0d, 02, 0e]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 171, 13) to (start + 2, 14)
+- Code(Zero) at (prev + 171, 13) to (start + 2, 14)
 
 Function name: closure::main::{closure#14}
-Raw bytes (38): 0x[01, 01, 04, 05, 0a, 01, 05, 01, 05, 03, 00, 05, 03, b2, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 0f, 01, 0d, 00, 0e]
+Raw bytes (36): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 05, 03, b2, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 01, 0d, 00, 0e]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 4
+Number of expressions: 3
 - expression 0 operands: lhs = Counter(1), rhs = Expression(2, Sub)
 - expression 1 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 2 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 3 operands: lhs = Expression(0, Add), rhs = Zero
 Number of file 0 mappings: 5
 - Code(Expression(0, Add)) at (prev + 178, 13) to (start + 0, 21)
     = (c1 + (c0 - c1))
@@ -137,40 +95,36 @@ Number of file 0 mappings: 5
 - Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37)
 - Code(Expression(2, Sub)) at (prev + 0, 47) to (start + 0, 51)
     = (c0 - c1)
-- Code(Expression(3, Add)) at (prev + 1, 13) to (start + 0, 14)
-    = ((c1 + (c0 - c1)) + Zero)
+- Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 14)
+    = (c1 + (c0 - c1))
 
 Function name: closure::main::{closure#15}
-Raw bytes (45): 0x[01, 01, 05, 05, 0e, 01, 05, 01, 00, 01, 05, 03, 00, 06, 01, ba, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 0b, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0e, 00, 2f, 00, 33, 13, 02, 09, 00, 0a]
+Raw bytes (41): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 06, 01, ba, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 02, 09, 00, 0a]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 5
-- expression 0 operands: lhs = Counter(1), rhs = Expression(3, Sub)
+Number of expressions: 3
+- expression 0 operands: lhs = Counter(1), rhs = Expression(2, Sub)
 - expression 1 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 2 operands: lhs = Counter(0), rhs = Zero
-- expression 3 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 4 operands: lhs = Expression(0, Add), rhs = Zero
+- expression 2 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 6
 - Code(Counter(0)) at (prev + 186, 9) to (start + 0, 10)
 - Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 21)
     = (c1 + (c0 - c1))
-- Code(Expression(2, Add)) at (prev + 1, 17) to (start + 1, 27)
-    = (c0 + Zero)
+- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27)
 - Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37)
-- Code(Expression(3, Sub)) at (prev + 0, 47) to (start + 0, 51)
+- Code(Expression(2, Sub)) at (prev + 0, 47) to (start + 0, 51)
     = (c0 - c1)
-- Code(Expression(4, Add)) at (prev + 2, 9) to (start + 0, 10)
-    = ((c1 + (c0 - c1)) + Zero)
+- Code(Expression(0, Add)) at (prev + 2, 9) to (start + 0, 10)
+    = (c1 + (c0 - c1))
 
 Function name: closure::main::{closure#16}
-Raw bytes (38): 0x[01, 01, 04, 05, 0a, 01, 05, 01, 05, 03, 00, 05, 03, c4, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 0f, 01, 0d, 00, 0e]
+Raw bytes (36): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 05, 03, c4, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 01, 0d, 00, 0e]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 4
+Number of expressions: 3
 - expression 0 operands: lhs = Counter(1), rhs = Expression(2, Sub)
 - expression 1 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 2 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 3 operands: lhs = Expression(0, Add), rhs = Zero
 Number of file 0 mappings: 5
 - Code(Expression(0, Add)) at (prev + 196, 13) to (start + 0, 21)
     = (c1 + (c0 - c1))
@@ -178,30 +132,27 @@ Number of file 0 mappings: 5
 - Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37)
 - Code(Expression(2, Sub)) at (prev + 0, 47) to (start + 0, 51)
     = (c0 - c1)
-- Code(Expression(3, Add)) at (prev + 1, 13) to (start + 0, 14)
-    = ((c1 + (c0 - c1)) + Zero)
+- Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 14)
+    = (c1 + (c0 - c1))
 
 Function name: closure::main::{closure#17}
-Raw bytes (45): 0x[01, 01, 05, 05, 0e, 01, 05, 01, 00, 01, 05, 03, 00, 06, 01, cc, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 0b, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0e, 00, 2f, 00, 33, 13, 02, 09, 00, 0a]
+Raw bytes (41): 0x[01, 01, 03, 05, 0a, 01, 05, 01, 05, 06, 01, cc, 01, 09, 00, 0a, 03, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 0a, 00, 2f, 00, 33, 03, 02, 09, 00, 0a]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 5
-- expression 0 operands: lhs = Counter(1), rhs = Expression(3, Sub)
+Number of expressions: 3
+- expression 0 operands: lhs = Counter(1), rhs = Expression(2, Sub)
 - expression 1 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 2 operands: lhs = Counter(0), rhs = Zero
-- expression 3 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 4 operands: lhs = Expression(0, Add), rhs = Zero
+- expression 2 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 6
 - Code(Counter(0)) at (prev + 204, 9) to (start + 0, 10)
 - Code(Expression(0, Add)) at (prev + 1, 13) to (start + 0, 21)
     = (c1 + (c0 - c1))
-- Code(Expression(2, Add)) at (prev + 1, 17) to (start + 1, 27)
-    = (c0 + Zero)
+- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 27)
 - Code(Counter(1)) at (prev + 1, 30) to (start + 0, 37)
-- Code(Expression(3, Sub)) at (prev + 0, 47) to (start + 0, 51)
+- Code(Expression(2, Sub)) at (prev + 0, 47) to (start + 0, 51)
     = (c0 - c1)
-- Code(Expression(4, Add)) at (prev + 2, 9) to (start + 0, 10)
-    = ((c1 + (c0 - c1)) + Zero)
+- Code(Expression(0, Add)) at (prev + 2, 9) to (start + 0, 10)
+    = (c1 + (c0 - c1))
 
 Function name: closure::main::{closure#18}
 Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 18, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 07, 01, 11, 01, 0e]
@@ -264,23 +215,23 @@ Number of file 0 mappings: 4
     = (c1 + (c0 - c1))
 
 Function name: closure::main::{closure#3} (unused)
-Raw bytes (25): 0x[01, 01, 00, 04, 01, 80, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 0a, 00, 0b, 00, 01, 09, 01, 06]
+Raw bytes (25): 0x[01, 01, 00, 04, 00, 80, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 0a, 00, 0b, 00, 01, 09, 01, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 128, 5) to (start + 1, 20)
+- Code(Zero) at (prev + 128, 5) to (start + 1, 20)
 - Code(Zero) at (prev + 1, 21) to (start + 2, 10)
 - Code(Zero) at (prev + 2, 10) to (start + 0, 11)
 - Code(Zero) at (prev + 1, 9) to (start + 1, 6)
 
 Function name: closure::main::{closure#4} (unused)
-Raw bytes (10): 0x[01, 01, 00, 01, 01, 88, 01, 35, 00, 43]
+Raw bytes (10): 0x[01, 01, 00, 01, 00, 88, 01, 35, 00, 43]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 136, 53) to (start + 0, 67)
+- Code(Zero) at (prev + 136, 53) to (start + 0, 67)
 
 Function name: closure::main::{closure#5}
 Raw bytes (10): 0x[01, 01, 00, 01, 01, 8b, 01, 3d, 00, 4f]
@@ -299,26 +250,26 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 140, 65) to (start + 0, 87)
 
 Function name: closure::main::{closure#7} (unused)
-Raw bytes (10): 0x[01, 01, 00, 01, 01, 8d, 01, 3b, 00, 51]
+Raw bytes (10): 0x[01, 01, 00, 01, 00, 8d, 01, 3b, 00, 51]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 141, 59) to (start + 0, 81)
+- Code(Zero) at (prev + 141, 59) to (start + 0, 81)
 
 Function name: closure::main::{closure#8} (unused)
-Raw bytes (10): 0x[01, 01, 00, 01, 01, 92, 01, 3b, 00, 55]
+Raw bytes (10): 0x[01, 01, 00, 01, 00, 92, 01, 3b, 00, 55]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 146, 59) to (start + 0, 85)
+- Code(Zero) at (prev + 146, 59) to (start + 0, 85)
 
 Function name: closure::main::{closure#9} (unused)
-Raw bytes (10): 0x[01, 01, 00, 01, 01, 94, 01, 38, 02, 06]
+Raw bytes (10): 0x[01, 01, 00, 01, 00, 94, 01, 38, 02, 06]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 148, 56) to (start + 2, 6)
+- Code(Zero) at (prev + 148, 56) to (start + 2, 6)
 
diff --git a/tests/coverage-map/status-quo/closure_bug.cov-map b/tests/coverage-map/status-quo/closure_bug.cov-map
index 4fe2e5ad243..90eeb1a6686 100644
--- a/tests/coverage-map/status-quo/closure_bug.cov-map
+++ b/tests/coverage-map/status-quo/closure_bug.cov-map
@@ -1,89 +1,74 @@
 Function name: closure_bug::main
-Raw bytes (241): 0x[01, 01, 34, 01, 00, 01, 05, 05, ce, 01, 01, 05, cb, 01, 00, 05, ce, 01, 01, 05, cb, 01, 09, 05, ce, 01, 01, 05, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, c3, 01, 00, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, c3, 01, 0d, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, 0d, be, 01, c3, 01, 0d, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, bb, 01, 00, 0d, be, 01, c3, 01, 0d, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, bb, 01, 11, 0d, be, 01, c3, 01, 0d, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, 11, b6, 01, bb, 01, 11, 0d, be, 01, c3, 01, 0d, 09, c6, 01, cb, 01, 09, 05, ce, 01, 01, 05, 11, 01, 06, 01, 03, 0a, 03, 09, 05, 01, 0e, 05, 01, 0f, 00, 17, ce, 01, 00, 17, 00, 18, cb, 01, 02, 09, 00, 0a, 13, 06, 05, 01, 0e, 09, 01, 0f, 00, 17, c6, 01, 00, 17, 00, 18, c3, 01, 02, 09, 00, 0a, 3b, 06, 05, 01, 0e, 0d, 01, 0f, 00, 17, be, 01, 00, 17, 00, 18, bb, 01, 02, 09, 00, 0a, 7b, 06, 05, 01, 0e, 11, 01, 0f, 00, 17, b6, 01, 00, 17, 00, 18, b3, 01, 01, 01, 00, 02]
+Raw bytes (201): 0x[01, 01, 26, 01, 05, 05, 02, 05, 02, 97, 01, 09, 05, 02, 09, 92, 01, 97, 01, 09, 05, 02, 09, 92, 01, 97, 01, 09, 05, 02, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 87, 01, 11, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 11, 82, 01, 87, 01, 11, 0d, 8a, 01, 8f, 01, 0d, 09, 92, 01, 97, 01, 09, 05, 02, 11, 01, 06, 01, 03, 0a, 01, 09, 05, 01, 0e, 05, 01, 0f, 00, 17, 02, 00, 17, 00, 18, 97, 01, 02, 09, 00, 0a, 97, 01, 06, 05, 01, 0e, 09, 01, 0f, 00, 17, 92, 01, 00, 17, 00, 18, 8f, 01, 02, 09, 00, 0a, 8f, 01, 06, 05, 01, 0e, 0d, 01, 0f, 00, 17, 8a, 01, 00, 17, 00, 18, 87, 01, 02, 09, 00, 0a, 87, 01, 06, 05, 01, 0e, 11, 01, 0f, 00, 17, 82, 01, 00, 17, 00, 18, 7f, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 52
-- expression 0 operands: lhs = Counter(0), rhs = Zero
-- expression 1 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 2 operands: lhs = Counter(1), rhs = Expression(51, Sub)
-- expression 3 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 4 operands: lhs = Expression(50, Add), rhs = Zero
-- expression 5 operands: lhs = Counter(1), rhs = Expression(51, Sub)
-- expression 6 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 7 operands: lhs = Expression(50, Add), rhs = Counter(2)
-- expression 8 operands: lhs = Counter(1), rhs = Expression(51, Sub)
-- expression 9 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 10 operands: lhs = Counter(2), rhs = Expression(49, Sub)
-- expression 11 operands: lhs = Expression(50, Add), rhs = Counter(2)
-- expression 12 operands: lhs = Counter(1), rhs = Expression(51, Sub)
-- expression 13 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 14 operands: lhs = Expression(48, Add), rhs = Zero
-- expression 15 operands: lhs = Counter(2), rhs = Expression(49, Sub)
-- expression 16 operands: lhs = Expression(50, Add), rhs = Counter(2)
-- expression 17 operands: lhs = Counter(1), rhs = Expression(51, Sub)
-- expression 18 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 19 operands: lhs = Expression(48, Add), rhs = Counter(3)
-- expression 20 operands: lhs = Counter(2), rhs = Expression(49, Sub)
-- expression 21 operands: lhs = Expression(50, Add), rhs = Counter(2)
-- expression 22 operands: lhs = Counter(1), rhs = Expression(51, Sub)
-- expression 23 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 24 operands: lhs = Counter(3), rhs = Expression(47, Sub)
-- expression 25 operands: lhs = Expression(48, Add), rhs = Counter(3)
-- expression 26 operands: lhs = Counter(2), rhs = Expression(49, Sub)
-- expression 27 operands: lhs = Expression(50, Add), rhs = Counter(2)
-- expression 28 operands: lhs = Counter(1), rhs = Expression(51, Sub)
-- expression 29 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 30 operands: lhs = Expression(46, Add), rhs = Zero
-- expression 31 operands: lhs = Counter(3), rhs = Expression(47, Sub)
-- expression 32 operands: lhs = Expression(48, Add), rhs = Counter(3)
-- expression 33 operands: lhs = Counter(2), rhs = Expression(49, Sub)
-- expression 34 operands: lhs = Expression(50, Add), rhs = Counter(2)
-- expression 35 operands: lhs = Counter(1), rhs = Expression(51, Sub)
-- expression 36 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 37 operands: lhs = Expression(46, Add), rhs = Counter(4)
-- expression 38 operands: lhs = Counter(3), rhs = Expression(47, Sub)
-- expression 39 operands: lhs = Expression(48, Add), rhs = Counter(3)
-- expression 40 operands: lhs = Counter(2), rhs = Expression(49, Sub)
-- expression 41 operands: lhs = Expression(50, Add), rhs = Counter(2)
-- expression 42 operands: lhs = Counter(1), rhs = Expression(51, Sub)
-- expression 43 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 44 operands: lhs = Counter(4), rhs = Expression(45, Sub)
-- expression 45 operands: lhs = Expression(46, Add), rhs = Counter(4)
-- expression 46 operands: lhs = Counter(3), rhs = Expression(47, Sub)
-- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(3)
-- expression 48 operands: lhs = Counter(2), rhs = Expression(49, Sub)
-- expression 49 operands: lhs = Expression(50, Add), rhs = Counter(2)
-- expression 50 operands: lhs = Counter(1), rhs = Expression(51, Sub)
-- expression 51 operands: lhs = Counter(0), rhs = Counter(1)
+Number of expressions: 38
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 2 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 3 operands: lhs = Expression(37, Add), rhs = Counter(2)
+- expression 4 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 5 operands: lhs = Counter(2), rhs = Expression(36, Sub)
+- expression 6 operands: lhs = Expression(37, Add), rhs = Counter(2)
+- expression 7 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 8 operands: lhs = Counter(2), rhs = Expression(36, Sub)
+- expression 9 operands: lhs = Expression(37, Add), rhs = Counter(2)
+- expression 10 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 11 operands: lhs = Expression(35, Add), rhs = Counter(3)
+- expression 12 operands: lhs = Counter(2), rhs = Expression(36, Sub)
+- expression 13 operands: lhs = Expression(37, Add), rhs = Counter(2)
+- expression 14 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 15 operands: lhs = Counter(3), rhs = Expression(34, Sub)
+- expression 16 operands: lhs = Expression(35, Add), rhs = Counter(3)
+- expression 17 operands: lhs = Counter(2), rhs = Expression(36, Sub)
+- expression 18 operands: lhs = Expression(37, Add), rhs = Counter(2)
+- expression 19 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 20 operands: lhs = Counter(3), rhs = Expression(34, Sub)
+- expression 21 operands: lhs = Expression(35, Add), rhs = Counter(3)
+- expression 22 operands: lhs = Counter(2), rhs = Expression(36, Sub)
+- expression 23 operands: lhs = Expression(37, Add), rhs = Counter(2)
+- expression 24 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 25 operands: lhs = Expression(33, Add), rhs = Counter(4)
+- expression 26 operands: lhs = Counter(3), rhs = Expression(34, Sub)
+- expression 27 operands: lhs = Expression(35, Add), rhs = Counter(3)
+- expression 28 operands: lhs = Counter(2), rhs = Expression(36, Sub)
+- expression 29 operands: lhs = Expression(37, Add), rhs = Counter(2)
+- expression 30 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 31 operands: lhs = Counter(4), rhs = Expression(32, Sub)
+- expression 32 operands: lhs = Expression(33, Add), rhs = Counter(4)
+- expression 33 operands: lhs = Counter(3), rhs = Expression(34, Sub)
+- expression 34 operands: lhs = Expression(35, Add), rhs = Counter(3)
+- expression 35 operands: lhs = Counter(2), rhs = Expression(36, Sub)
+- expression 36 operands: lhs = Expression(37, Add), rhs = Counter(2)
+- expression 37 operands: lhs = Counter(1), rhs = Expression(0, Sub)
 Number of file 0 mappings: 17
 - Code(Counter(0)) at (prev + 6, 1) to (start + 3, 10)
-- Code(Expression(0, Add)) at (prev + 9, 5) to (start + 1, 14)
-    = (c0 + Zero)
+- Code(Counter(0)) at (prev + 9, 5) to (start + 1, 14)
 - Code(Counter(1)) at (prev + 1, 15) to (start + 0, 23)
-- Code(Expression(51, Sub)) at (prev + 0, 23) to (start + 0, 24)
+- Code(Expression(0, Sub)) at (prev + 0, 23) to (start + 0, 24)
     = (c0 - c1)
-- Code(Expression(50, Add)) at (prev + 2, 9) to (start + 0, 10)
+- Code(Expression(37, Add)) at (prev + 2, 9) to (start + 0, 10)
+    = (c1 + (c0 - c1))
+- Code(Expression(37, Add)) at (prev + 6, 5) to (start + 1, 14)
     = (c1 + (c0 - c1))
-- Code(Expression(4, Add)) at (prev + 6, 5) to (start + 1, 14)
-    = ((c1 + (c0 - c1)) + Zero)
 - Code(Counter(2)) at (prev + 1, 15) to (start + 0, 23)
-- Code(Expression(49, Sub)) at (prev + 0, 23) to (start + 0, 24)
+- Code(Expression(36, Sub)) at (prev + 0, 23) to (start + 0, 24)
     = ((c1 + (c0 - c1)) - c2)
-- Code(Expression(48, Add)) at (prev + 2, 9) to (start + 0, 10)
+- Code(Expression(35, Add)) at (prev + 2, 9) to (start + 0, 10)
+    = (c2 + ((c1 + (c0 - c1)) - c2))
+- Code(Expression(35, Add)) at (prev + 6, 5) to (start + 1, 14)
     = (c2 + ((c1 + (c0 - c1)) - c2))
-- Code(Expression(14, Add)) at (prev + 6, 5) to (start + 1, 14)
-    = ((c2 + ((c1 + (c0 - c1)) - c2)) + Zero)
 - Code(Counter(3)) at (prev + 1, 15) to (start + 0, 23)
-- Code(Expression(47, Sub)) at (prev + 0, 23) to (start + 0, 24)
+- Code(Expression(34, Sub)) at (prev + 0, 23) to (start + 0, 24)
     = ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)
-- Code(Expression(46, Add)) at (prev + 2, 9) to (start + 0, 10)
+- Code(Expression(33, Add)) at (prev + 2, 9) to (start + 0, 10)
+    = (c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3))
+- Code(Expression(33, Add)) at (prev + 6, 5) to (start + 1, 14)
     = (c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3))
-- Code(Expression(30, Add)) at (prev + 6, 5) to (start + 1, 14)
-    = ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) + Zero)
 - Code(Counter(4)) at (prev + 1, 15) to (start + 0, 23)
-- Code(Expression(45, Sub)) at (prev + 0, 23) to (start + 0, 24)
+- Code(Expression(32, Sub)) at (prev + 0, 23) to (start + 0, 24)
     = ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)
-- Code(Expression(44, Add)) at (prev + 1, 1) to (start + 0, 2)
+- Code(Expression(31, Add)) at (prev + 1, 1) to (start + 0, 2)
     = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4))
 
 Function name: closure_bug::main::{closure#0}
diff --git a/tests/coverage-map/status-quo/closure_macro.cov-map b/tests/coverage-map/status-quo/closure_macro.cov-map
index ac017eb4468..b02c7e2e4c6 100644
--- a/tests/coverage-map/status-quo/closure_macro.cov-map
+++ b/tests/coverage-map/status-quo/closure_macro.cov-map
@@ -7,27 +7,23 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2)
 
 Function name: closure_macro::main
-Raw bytes (49): 0x[01, 01, 05, 01, 05, 02, 00, 05, 00, 02, 00, 05, 02, 07, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 07, 00, 12, 00, 13, 0b, 00, 54, 00, 55, 0f, 02, 09, 02, 0b, 13, 03, 01, 00, 02]
+Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 5
+Number of expressions: 2
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Expression(0, Sub), rhs = Zero
-- expression 2 operands: lhs = Counter(1), rhs = Zero
-- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero
-- expression 4 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
 Number of file 0 mappings: 7
 - Code(Counter(0)) at (prev + 33, 1) to (start + 1, 33)
 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15)
     = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19)
-- Code(Expression(1, Add)) at (prev + 0, 18) to (start + 0, 19)
-    = ((c0 - c1) + Zero)
-- Code(Expression(2, Add)) at (prev + 0, 84) to (start + 0, 85)
-    = (c1 + Zero)
-- Code(Expression(3, Add)) at (prev + 2, 9) to (start + 2, 11)
-    = ((c0 - c1) + Zero)
-- Code(Expression(4, Add)) at (prev + 3, 1) to (start + 0, 2)
+- Code(Expression(0, Sub)) at (prev + 0, 18) to (start + 0, 19)
+    = (c0 - c1)
+- Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85)
+- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11)
+    = (c0 - c1)
+- Code(Expression(1, Add)) at (prev + 3, 1) to (start + 0, 2)
     = (c1 + (c0 - c1))
 
 Function name: closure_macro::main::{closure#0}
diff --git a/tests/coverage-map/status-quo/closure_macro_async.cov-map b/tests/coverage-map/status-quo/closure_macro_async.cov-map
index c9a142e5aeb..7f8666948d9 100644
--- a/tests/coverage-map/status-quo/closure_macro_async.cov-map
+++ b/tests/coverage-map/status-quo/closure_macro_async.cov-map
@@ -15,27 +15,23 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 33, 1) to (start + 0, 43)
 
 Function name: closure_macro_async::test::{closure#0}
-Raw bytes (49): 0x[01, 01, 05, 01, 05, 02, 00, 05, 00, 02, 00, 05, 02, 07, 01, 21, 2b, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 07, 00, 12, 00, 13, 0b, 00, 54, 00, 55, 0f, 02, 09, 02, 0b, 13, 03, 01, 00, 02]
+Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 21, 2b, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 5
+Number of expressions: 2
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Expression(0, Sub), rhs = Zero
-- expression 2 operands: lhs = Counter(1), rhs = Zero
-- expression 3 operands: lhs = Expression(0, Sub), rhs = Zero
-- expression 4 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
 Number of file 0 mappings: 7
 - Code(Counter(0)) at (prev + 33, 43) to (start + 1, 33)
 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15)
     = (c0 - c1)
 - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19)
-- Code(Expression(1, Add)) at (prev + 0, 18) to (start + 0, 19)
-    = ((c0 - c1) + Zero)
-- Code(Expression(2, Add)) at (prev + 0, 84) to (start + 0, 85)
-    = (c1 + Zero)
-- Code(Expression(3, Add)) at (prev + 2, 9) to (start + 2, 11)
-    = ((c0 - c1) + Zero)
-- Code(Expression(4, Add)) at (prev + 3, 1) to (start + 0, 2)
+- Code(Expression(0, Sub)) at (prev + 0, 18) to (start + 0, 19)
+    = (c0 - c1)
+- Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85)
+- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11)
+    = (c0 - c1)
+- Code(Expression(1, Add)) at (prev + 3, 1) to (start + 0, 2)
     = (c1 + (c0 - c1))
 
 Function name: closure_macro_async::test::{closure#0}::{closure#0}
diff --git a/tests/coverage-map/status-quo/conditions.cov-map b/tests/coverage-map/status-quo/conditions.cov-map
index d82b8389b4d..7600d2d96bd 100644
--- a/tests/coverage-map/status-quo/conditions.cov-map
+++ b/tests/coverage-map/status-quo/conditions.cov-map
@@ -1,14 +1,14 @@
 Function name: conditions::main
-Raw bytes (793): 0x[01, 01, 90, 01, 09, 33, 37, 41, 3b, 3d, 35, 39, 05, 00, bf, 04, 09, 05, 00, 0d, 35, 26, 39, 0d, 35, 3b, 3d, 35, 39, 37, 41, 3b, 3d, 35, 39, ba, 04, 0d, bf, 04, 09, 05, 00, 03, 00, 45, 00, 87, 01, 49, 45, 00, 82, 01, 31, 87, 01, 49, 45, 00, 7e, 4d, 82, 01, 31, 87, 01, 49, 45, 00, 7a, 51, 7e, 4d, 82, 01, 31, 87, 01, 49, 45, 00, ab, 01, 55, 4d, 51, a7, 01, 59, ab, 01, 55, 4d, 51, 49, a3, 01, a7, 01, 59, ab, 01, 55, 4d, 51, 61, 00, e7, 01, 65, 61, 00, e2, 01, 2d, e7, 01, 65, 61, 00, de, 01, 69, e2, 01, 2d, e7, 01, 65, 61, 00, da, 01, 6d, de, 01, 69, e2, 01, 2d, e7, 01, 65, 61, 00, 8f, 02, 71, 69, 6d, 8b, 02, 75, 8f, 02, 71, 69, 6d, 83, 02, 00, 65, 87, 02, 8b, 02, 75, 8f, 02, 71, 69, 6d, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, 79, 00, db, 02, 7d, 79, 00, d6, 02, 29, db, 02, 7d, 79, 00, d2, 02, 81, 01, d6, 02, 29, db, 02, 7d, 79, 00, ce, 02, 85, 01, d2, 02, 81, 01, d6, 02, 29, db, 02, 7d, 79, 00, fb, 03, 89, 01, 81, 01, 85, 01, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, 11, 9b, 04, 9f, 04, 21, a3, 04, 1d, 15, 19, ef, 03, 00, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, ef, 03, 11, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, ea, 03, 25, ef, 03, 11, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, e6, 03, 15, ea, 03, 25, ef, 03, 11, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, e2, 03, 19, e6, 03, 15, ea, 03, 25, ef, 03, 11, 7d, f3, 03, f7, 03, 8d, 01, fb, 03, 89, 01, 81, 01, 85, 01, a3, 04, 1d, 15, 19, 9f, 04, 21, a3, 04, 1d, 15, 19, 97, 04, a7, 04, 11, 9b, 04, 9f, 04, 21, a3, 04, 1d, 15, 19, ab, 04, b6, 04, af, 04, b3, 04, 25, 29, 2d, 31, ba, 04, 0d, bf, 04, 09, 05, 00, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, bf, 04, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, ba, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 26, 00, 1d, 00, 2a, 22, 00, 2e, 00, 3c, 37, 00, 3d, 02, 0a, 41, 02, 0a, 00, 0b, 33, 01, 09, 01, 12, b6, 04, 03, 09, 00, 0f, 4b, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 87, 01, 02, 08, 00, 15, 49, 00, 16, 02, 06, 82, 01, 02, 0f, 00, 1c, 7e, 01, 0c, 00, 19, 7a, 00, 1d, 00, 2a, 76, 00, 2e, 00, 3c, a7, 01, 00, 3d, 02, 0a, 59, 02, 0a, 00, 0b, a3, 01, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 9f, 01, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, e7, 01, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, e2, 01, 03, 11, 00, 1e, de, 01, 01, 10, 00, 1d, da, 01, 00, 21, 00, 2e, d6, 01, 00, 32, 00, 40, 8b, 02, 00, 41, 02, 0e, 75, 02, 0e, 00, 0f, 87, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 06, 00, 07, ff, 01, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 06, 00, 07, ef, 03, 02, 09, 00, 0a, db, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, d6, 02, 02, 0f, 00, 1c, d2, 02, 01, 0c, 00, 19, ce, 02, 00, 1d, 00, 2a, ca, 02, 00, 2e, 00, 3c, f7, 03, 00, 3d, 02, 0a, 8d, 01, 02, 0a, 00, 0b, f3, 03, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, 97, 04, 05, 09, 00, 0a, 83, 03, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, ea, 03, 02, 0f, 00, 1c, e6, 03, 01, 0c, 00, 19, e2, 03, 00, 1d, 00, 2a, de, 03, 00, 2e, 00, 3c, 9f, 04, 00, 3d, 02, 0a, 21, 02, 0a, 00, 0b, 9b, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, 93, 04, 02, 01, 00, 02]
+Raw bytes (784): 0x[01, 01, 8e, 01, 09, 33, 37, 41, 3b, 3d, 35, 39, 05, 00, b7, 04, 09, 05, 00, 0d, 35, 26, 39, 0d, 35, 3b, 3d, 35, 39, 37, 41, 3b, 3d, 35, 39, b2, 04, 0d, b7, 04, 09, 05, 00, 45, 00, 83, 01, 49, 45, 00, 7e, 31, 83, 01, 49, 45, 00, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, 76, 51, 7a, 4d, 7e, 31, 83, 01, 49, 45, 00, a7, 01, 55, 4d, 51, a3, 01, 59, a7, 01, 55, 4d, 51, 49, 9f, 01, a3, 01, 59, a7, 01, 55, 4d, 51, 61, 00, e3, 01, 65, 61, 00, de, 01, 2d, e3, 01, 65, 61, 00, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, d6, 01, 6d, da, 01, 69, de, 01, 2d, e3, 01, 65, 61, 00, 8b, 02, 71, 69, 6d, 87, 02, 75, 8b, 02, 71, 69, 6d, ff, 01, 00, 65, 83, 02, 87, 02, 75, 8b, 02, 71, 69, 6d, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 79, 00, d7, 02, 7d, 79, 00, d2, 02, 29, d7, 02, 7d, 79, 00, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, ca, 02, 85, 01, ce, 02, 81, 01, d2, 02, 29, d7, 02, 7d, 79, 00, f3, 03, 89, 01, 81, 01, 85, 01, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, da, 03, 19, de, 03, 15, e2, 03, 25, e7, 03, 11, 7d, eb, 03, ef, 03, 8d, 01, f3, 03, 89, 01, 81, 01, 85, 01, 9b, 04, 1d, 15, 19, 97, 04, 21, 9b, 04, 1d, 15, 19, 8f, 04, 9f, 04, 11, 93, 04, 97, 04, 21, 9b, 04, 1d, 15, 19, a3, 04, ae, 04, a7, 04, ab, 04, 25, 29, 2d, 31, b2, 04, 0d, b7, 04, 09, 05, 00, 44, 01, 03, 01, 02, 0c, 05, 02, 0d, 02, 06, 00, 02, 06, 00, 07, 03, 03, 09, 00, 0a, b7, 04, 00, 10, 00, 1d, 09, 01, 09, 01, 0a, b2, 04, 02, 0f, 00, 1c, 0d, 01, 0c, 00, 19, 26, 00, 1d, 00, 2a, 22, 00, 2e, 00, 3c, 37, 00, 3d, 02, 0a, 41, 02, 0a, 00, 0b, 33, 01, 09, 01, 12, ae, 04, 03, 09, 00, 0f, 03, 03, 09, 01, 0c, 45, 01, 0d, 02, 06, 00, 02, 06, 00, 07, 83, 01, 02, 08, 00, 15, 49, 00, 16, 02, 06, 7e, 02, 0f, 00, 1c, 7a, 01, 0c, 00, 19, 76, 00, 1d, 00, 2a, 72, 00, 2e, 00, 3c, a3, 01, 00, 3d, 02, 0a, 59, 02, 0a, 00, 0b, 9f, 01, 01, 09, 00, 17, 31, 02, 09, 00, 0f, 9b, 01, 03, 08, 00, 0c, 5d, 01, 0d, 01, 10, 61, 01, 11, 02, 0a, 00, 02, 0a, 00, 0b, e3, 01, 02, 0c, 00, 19, 65, 00, 1a, 02, 0a, de, 01, 03, 11, 00, 1e, da, 01, 01, 10, 00, 1d, d6, 01, 00, 21, 00, 2e, d2, 01, 00, 32, 00, 40, 87, 02, 00, 41, 02, 0e, 75, 02, 0e, 00, 0f, 83, 02, 01, 0d, 00, 1b, 2d, 02, 0d, 00, 13, 00, 02, 06, 00, 07, fb, 01, 02, 09, 01, 0c, 79, 01, 0d, 02, 06, 00, 02, 06, 00, 07, e7, 03, 02, 09, 00, 0a, d7, 02, 00, 10, 00, 1d, 7d, 00, 1e, 02, 06, d2, 02, 02, 0f, 00, 1c, ce, 02, 01, 0c, 00, 19, ca, 02, 00, 1d, 00, 2a, c6, 02, 00, 2e, 00, 3c, ef, 03, 00, 3d, 02, 0a, 8d, 01, 02, 0a, 00, 0b, eb, 03, 01, 09, 00, 17, 29, 02, 0d, 02, 0f, 8f, 04, 05, 09, 00, 0a, e7, 03, 00, 10, 00, 1d, 11, 00, 1e, 02, 06, e2, 03, 02, 0f, 00, 1c, de, 03, 01, 0c, 00, 19, da, 03, 00, 1d, 00, 2a, d6, 03, 00, 2e, 00, 3c, 97, 04, 00, 3d, 02, 0a, 21, 02, 0a, 00, 0b, 93, 04, 01, 09, 00, 17, 25, 02, 09, 00, 0f, 8b, 04, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 144
+Number of expressions: 142
 - expression 0 operands: lhs = Counter(2), rhs = Expression(12, Add)
 - expression 1 operands: lhs = Expression(13, Add), rhs = Counter(16)
 - expression 2 operands: lhs = Expression(14, Add), rhs = Counter(15)
 - expression 3 operands: lhs = Counter(13), rhs = Counter(14)
 - expression 4 operands: lhs = Counter(1), rhs = Zero
-- expression 5 operands: lhs = Expression(143, Add), rhs = Counter(2)
+- expression 5 operands: lhs = Expression(141, Add), rhs = Counter(2)
 - expression 6 operands: lhs = Counter(1), rhs = Zero
 - expression 7 operands: lhs = Counter(3), rhs = Counter(13)
 - expression 8 operands: lhs = Expression(9, Sub), rhs = Counter(14)
@@ -18,145 +18,143 @@ Number of expressions: 144
 - expression 12 operands: lhs = Expression(13, Add), rhs = Counter(16)
 - expression 13 operands: lhs = Expression(14, Add), rhs = Counter(15)
 - expression 14 operands: lhs = Counter(13), rhs = Counter(14)
-- expression 15 operands: lhs = Expression(142, Sub), rhs = Counter(3)
-- expression 16 operands: lhs = Expression(143, Add), rhs = Counter(2)
+- expression 15 operands: lhs = Expression(140, Sub), rhs = Counter(3)
+- expression 16 operands: lhs = Expression(141, Add), rhs = Counter(2)
 - expression 17 operands: lhs = Counter(1), rhs = Zero
-- expression 18 operands: lhs = Expression(0, Add), rhs = Zero
-- expression 19 operands: lhs = Counter(17), rhs = Zero
-- expression 20 operands: lhs = Expression(33, Add), rhs = Counter(18)
-- expression 21 operands: lhs = Counter(17), rhs = Zero
-- expression 22 operands: lhs = Expression(32, Sub), rhs = Counter(12)
-- expression 23 operands: lhs = Expression(33, Add), rhs = Counter(18)
-- expression 24 operands: lhs = Counter(17), rhs = Zero
-- expression 25 operands: lhs = Expression(31, Sub), rhs = Counter(19)
-- expression 26 operands: lhs = Expression(32, Sub), rhs = Counter(12)
-- expression 27 operands: lhs = Expression(33, Add), rhs = Counter(18)
-- expression 28 operands: lhs = Counter(17), rhs = Zero
-- expression 29 operands: lhs = Expression(30, Sub), rhs = Counter(20)
-- expression 30 operands: lhs = Expression(31, Sub), rhs = Counter(19)
-- expression 31 operands: lhs = Expression(32, Sub), rhs = Counter(12)
-- expression 32 operands: lhs = Expression(33, Add), rhs = Counter(18)
-- expression 33 operands: lhs = Counter(17), rhs = Zero
-- expression 34 operands: lhs = Expression(42, Add), rhs = Counter(21)
-- expression 35 operands: lhs = Counter(19), rhs = Counter(20)
-- expression 36 operands: lhs = Expression(41, Add), rhs = Counter(22)
-- expression 37 operands: lhs = Expression(42, Add), rhs = Counter(21)
-- expression 38 operands: lhs = Counter(19), rhs = Counter(20)
-- expression 39 operands: lhs = Counter(18), rhs = Expression(40, Add)
-- expression 40 operands: lhs = Expression(41, Add), rhs = Counter(22)
-- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(21)
-- expression 42 operands: lhs = Counter(19), rhs = Counter(20)
-- expression 43 operands: lhs = Counter(24), rhs = Zero
-- expression 44 operands: lhs = Expression(57, Add), rhs = Counter(25)
-- expression 45 operands: lhs = Counter(24), rhs = Zero
-- expression 46 operands: lhs = Expression(56, Sub), rhs = Counter(11)
-- expression 47 operands: lhs = Expression(57, Add), rhs = Counter(25)
-- expression 48 operands: lhs = Counter(24), rhs = Zero
-- expression 49 operands: lhs = Expression(55, Sub), rhs = Counter(26)
-- expression 50 operands: lhs = Expression(56, Sub), rhs = Counter(11)
-- expression 51 operands: lhs = Expression(57, Add), rhs = Counter(25)
-- expression 52 operands: lhs = Counter(24), rhs = Zero
-- expression 53 operands: lhs = Expression(54, Sub), rhs = Counter(27)
-- expression 54 operands: lhs = Expression(55, Sub), rhs = Counter(26)
-- expression 55 operands: lhs = Expression(56, Sub), rhs = Counter(11)
-- expression 56 operands: lhs = Expression(57, Add), rhs = Counter(25)
-- expression 57 operands: lhs = Counter(24), rhs = Zero
-- expression 58 operands: lhs = Expression(67, Add), rhs = Counter(28)
-- expression 59 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 60 operands: lhs = Expression(66, Add), rhs = Counter(29)
-- expression 61 operands: lhs = Expression(67, Add), rhs = Counter(28)
-- expression 62 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 63 operands: lhs = Expression(64, Add), rhs = Zero
-- expression 64 operands: lhs = Counter(25), rhs = Expression(65, Add)
-- expression 65 operands: lhs = Expression(66, Add), rhs = Counter(29)
-- expression 66 operands: lhs = Expression(67, Add), rhs = Counter(28)
-- expression 67 operands: lhs = Counter(26), rhs = Counter(27)
-- expression 68 operands: lhs = Counter(31), rhs = Expression(124, Add)
-- expression 69 operands: lhs = Expression(125, Add), rhs = Counter(35)
-- expression 70 operands: lhs = Expression(126, Add), rhs = Counter(34)
-- expression 71 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 72 operands: lhs = Counter(30), rhs = Zero
-- expression 73 operands: lhs = Expression(86, Add), rhs = Counter(31)
-- expression 74 operands: lhs = Counter(30), rhs = Zero
-- expression 75 operands: lhs = Expression(85, Sub), rhs = Counter(10)
-- expression 76 operands: lhs = Expression(86, Add), rhs = Counter(31)
-- expression 77 operands: lhs = Counter(30), rhs = Zero
-- expression 78 operands: lhs = Expression(84, Sub), rhs = Counter(32)
-- expression 79 operands: lhs = Expression(85, Sub), rhs = Counter(10)
-- expression 80 operands: lhs = Expression(86, Add), rhs = Counter(31)
-- expression 81 operands: lhs = Counter(30), rhs = Zero
-- expression 82 operands: lhs = Expression(83, Sub), rhs = Counter(33)
-- expression 83 operands: lhs = Expression(84, Sub), rhs = Counter(32)
-- expression 84 operands: lhs = Expression(85, Sub), rhs = Counter(10)
-- expression 85 operands: lhs = Expression(86, Add), rhs = Counter(31)
-- expression 86 operands: lhs = Counter(30), rhs = Zero
-- expression 87 operands: lhs = Expression(126, Add), rhs = Counter(34)
-- expression 88 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 89 operands: lhs = Expression(125, Add), rhs = Counter(35)
-- expression 90 operands: lhs = Expression(126, Add), rhs = Counter(34)
-- expression 91 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 92 operands: lhs = Counter(4), rhs = Expression(134, Add)
-- expression 93 operands: lhs = Expression(135, Add), rhs = Counter(8)
-- expression 94 operands: lhs = Expression(136, Add), rhs = Counter(7)
-- expression 95 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 96 operands: lhs = Expression(123, Add), rhs = Zero
-- expression 97 operands: lhs = Counter(31), rhs = Expression(124, Add)
-- expression 98 operands: lhs = Expression(125, Add), rhs = Counter(35)
-- expression 99 operands: lhs = Expression(126, Add), rhs = Counter(34)
-- expression 100 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 101 operands: lhs = Expression(123, Add), rhs = Counter(4)
-- expression 102 operands: lhs = Counter(31), rhs = Expression(124, Add)
-- expression 103 operands: lhs = Expression(125, Add), rhs = Counter(35)
-- expression 104 operands: lhs = Expression(126, Add), rhs = Counter(34)
-- expression 105 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 106 operands: lhs = Expression(122, Sub), rhs = Counter(9)
-- expression 107 operands: lhs = Expression(123, Add), rhs = Counter(4)
-- expression 108 operands: lhs = Counter(31), rhs = Expression(124, Add)
-- expression 109 operands: lhs = Expression(125, Add), rhs = Counter(35)
-- expression 110 operands: lhs = Expression(126, Add), rhs = Counter(34)
-- expression 111 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 112 operands: lhs = Expression(121, Sub), rhs = Counter(5)
-- expression 113 operands: lhs = Expression(122, Sub), rhs = Counter(9)
-- expression 114 operands: lhs = Expression(123, Add), rhs = Counter(4)
-- expression 115 operands: lhs = Counter(31), rhs = Expression(124, Add)
-- expression 116 operands: lhs = Expression(125, Add), rhs = Counter(35)
-- expression 117 operands: lhs = Expression(126, Add), rhs = Counter(34)
-- expression 118 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 119 operands: lhs = Expression(120, Sub), rhs = Counter(6)
-- expression 120 operands: lhs = Expression(121, Sub), rhs = Counter(5)
-- expression 121 operands: lhs = Expression(122, Sub), rhs = Counter(9)
-- expression 122 operands: lhs = Expression(123, Add), rhs = Counter(4)
-- expression 123 operands: lhs = Counter(31), rhs = Expression(124, Add)
-- expression 124 operands: lhs = Expression(125, Add), rhs = Counter(35)
-- expression 125 operands: lhs = Expression(126, Add), rhs = Counter(34)
-- expression 126 operands: lhs = Counter(32), rhs = Counter(33)
-- expression 127 operands: lhs = Expression(136, Add), rhs = Counter(7)
-- expression 128 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 129 operands: lhs = Expression(135, Add), rhs = Counter(8)
-- expression 130 operands: lhs = Expression(136, Add), rhs = Counter(7)
-- expression 131 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 132 operands: lhs = Expression(133, Add), rhs = Expression(137, Add)
-- expression 133 operands: lhs = Counter(4), rhs = Expression(134, Add)
-- expression 134 operands: lhs = Expression(135, Add), rhs = Counter(8)
-- expression 135 operands: lhs = Expression(136, Add), rhs = Counter(7)
-- expression 136 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 137 operands: lhs = Expression(138, Add), rhs = Expression(141, Sub)
-- expression 138 operands: lhs = Expression(139, Add), rhs = Expression(140, Add)
-- expression 139 operands: lhs = Counter(9), rhs = Counter(10)
-- expression 140 operands: lhs = Counter(11), rhs = Counter(12)
-- expression 141 operands: lhs = Expression(142, Sub), rhs = Counter(3)
-- expression 142 operands: lhs = Expression(143, Add), rhs = Counter(2)
-- expression 143 operands: lhs = Counter(1), rhs = Zero
+- expression 18 operands: lhs = Counter(17), rhs = Zero
+- expression 19 operands: lhs = Expression(32, Add), rhs = Counter(18)
+- expression 20 operands: lhs = Counter(17), rhs = Zero
+- expression 21 operands: lhs = Expression(31, Sub), rhs = Counter(12)
+- expression 22 operands: lhs = Expression(32, Add), rhs = Counter(18)
+- expression 23 operands: lhs = Counter(17), rhs = Zero
+- expression 24 operands: lhs = Expression(30, Sub), rhs = Counter(19)
+- expression 25 operands: lhs = Expression(31, Sub), rhs = Counter(12)
+- expression 26 operands: lhs = Expression(32, Add), rhs = Counter(18)
+- expression 27 operands: lhs = Counter(17), rhs = Zero
+- expression 28 operands: lhs = Expression(29, Sub), rhs = Counter(20)
+- expression 29 operands: lhs = Expression(30, Sub), rhs = Counter(19)
+- expression 30 operands: lhs = Expression(31, Sub), rhs = Counter(12)
+- expression 31 operands: lhs = Expression(32, Add), rhs = Counter(18)
+- expression 32 operands: lhs = Counter(17), rhs = Zero
+- expression 33 operands: lhs = Expression(41, Add), rhs = Counter(21)
+- expression 34 operands: lhs = Counter(19), rhs = Counter(20)
+- expression 35 operands: lhs = Expression(40, Add), rhs = Counter(22)
+- expression 36 operands: lhs = Expression(41, Add), rhs = Counter(21)
+- expression 37 operands: lhs = Counter(19), rhs = Counter(20)
+- expression 38 operands: lhs = Counter(18), rhs = Expression(39, Add)
+- expression 39 operands: lhs = Expression(40, Add), rhs = Counter(22)
+- expression 40 operands: lhs = Expression(41, Add), rhs = Counter(21)
+- expression 41 operands: lhs = Counter(19), rhs = Counter(20)
+- expression 42 operands: lhs = Counter(24), rhs = Zero
+- expression 43 operands: lhs = Expression(56, Add), rhs = Counter(25)
+- expression 44 operands: lhs = Counter(24), rhs = Zero
+- expression 45 operands: lhs = Expression(55, Sub), rhs = Counter(11)
+- expression 46 operands: lhs = Expression(56, Add), rhs = Counter(25)
+- expression 47 operands: lhs = Counter(24), rhs = Zero
+- expression 48 operands: lhs = Expression(54, Sub), rhs = Counter(26)
+- expression 49 operands: lhs = Expression(55, Sub), rhs = Counter(11)
+- expression 50 operands: lhs = Expression(56, Add), rhs = Counter(25)
+- expression 51 operands: lhs = Counter(24), rhs = Zero
+- expression 52 operands: lhs = Expression(53, Sub), rhs = Counter(27)
+- expression 53 operands: lhs = Expression(54, Sub), rhs = Counter(26)
+- expression 54 operands: lhs = Expression(55, Sub), rhs = Counter(11)
+- expression 55 operands: lhs = Expression(56, Add), rhs = Counter(25)
+- expression 56 operands: lhs = Counter(24), rhs = Zero
+- expression 57 operands: lhs = Expression(66, Add), rhs = Counter(28)
+- expression 58 operands: lhs = Counter(26), rhs = Counter(27)
+- expression 59 operands: lhs = Expression(65, Add), rhs = Counter(29)
+- expression 60 operands: lhs = Expression(66, Add), rhs = Counter(28)
+- expression 61 operands: lhs = Counter(26), rhs = Counter(27)
+- expression 62 operands: lhs = Expression(63, Add), rhs = Zero
+- expression 63 operands: lhs = Counter(25), rhs = Expression(64, Add)
+- expression 64 operands: lhs = Expression(65, Add), rhs = Counter(29)
+- expression 65 operands: lhs = Expression(66, Add), rhs = Counter(28)
+- expression 66 operands: lhs = Counter(26), rhs = Counter(27)
+- expression 67 operands: lhs = Counter(31), rhs = Expression(122, Add)
+- expression 68 operands: lhs = Expression(123, Add), rhs = Counter(35)
+- expression 69 operands: lhs = Expression(124, Add), rhs = Counter(34)
+- expression 70 operands: lhs = Counter(32), rhs = Counter(33)
+- expression 71 operands: lhs = Counter(30), rhs = Zero
+- expression 72 operands: lhs = Expression(85, Add), rhs = Counter(31)
+- expression 73 operands: lhs = Counter(30), rhs = Zero
+- expression 74 operands: lhs = Expression(84, Sub), rhs = Counter(10)
+- expression 75 operands: lhs = Expression(85, Add), rhs = Counter(31)
+- expression 76 operands: lhs = Counter(30), rhs = Zero
+- expression 77 operands: lhs = Expression(83, Sub), rhs = Counter(32)
+- expression 78 operands: lhs = Expression(84, Sub), rhs = Counter(10)
+- expression 79 operands: lhs = Expression(85, Add), rhs = Counter(31)
+- expression 80 operands: lhs = Counter(30), rhs = Zero
+- expression 81 operands: lhs = Expression(82, Sub), rhs = Counter(33)
+- expression 82 operands: lhs = Expression(83, Sub), rhs = Counter(32)
+- expression 83 operands: lhs = Expression(84, Sub), rhs = Counter(10)
+- expression 84 operands: lhs = Expression(85, Add), rhs = Counter(31)
+- expression 85 operands: lhs = Counter(30), rhs = Zero
+- expression 86 operands: lhs = Expression(124, Add), rhs = Counter(34)
+- expression 87 operands: lhs = Counter(32), rhs = Counter(33)
+- expression 88 operands: lhs = Expression(123, Add), rhs = Counter(35)
+- expression 89 operands: lhs = Expression(124, Add), rhs = Counter(34)
+- expression 90 operands: lhs = Counter(32), rhs = Counter(33)
+- expression 91 operands: lhs = Counter(4), rhs = Expression(132, Add)
+- expression 92 operands: lhs = Expression(133, Add), rhs = Counter(8)
+- expression 93 operands: lhs = Expression(134, Add), rhs = Counter(7)
+- expression 94 operands: lhs = Counter(5), rhs = Counter(6)
+- expression 95 operands: lhs = Counter(31), rhs = Expression(122, Add)
+- expression 96 operands: lhs = Expression(123, Add), rhs = Counter(35)
+- expression 97 operands: lhs = Expression(124, Add), rhs = Counter(34)
+- expression 98 operands: lhs = Counter(32), rhs = Counter(33)
+- expression 99 operands: lhs = Expression(121, Add), rhs = Counter(4)
+- expression 100 operands: lhs = Counter(31), rhs = Expression(122, Add)
+- expression 101 operands: lhs = Expression(123, Add), rhs = Counter(35)
+- expression 102 operands: lhs = Expression(124, Add), rhs = Counter(34)
+- expression 103 operands: lhs = Counter(32), rhs = Counter(33)
+- expression 104 operands: lhs = Expression(120, Sub), rhs = Counter(9)
+- expression 105 operands: lhs = Expression(121, Add), rhs = Counter(4)
+- expression 106 operands: lhs = Counter(31), rhs = Expression(122, Add)
+- expression 107 operands: lhs = Expression(123, Add), rhs = Counter(35)
+- expression 108 operands: lhs = Expression(124, Add), rhs = Counter(34)
+- expression 109 operands: lhs = Counter(32), rhs = Counter(33)
+- expression 110 operands: lhs = Expression(119, Sub), rhs = Counter(5)
+- expression 111 operands: lhs = Expression(120, Sub), rhs = Counter(9)
+- expression 112 operands: lhs = Expression(121, Add), rhs = Counter(4)
+- expression 113 operands: lhs = Counter(31), rhs = Expression(122, Add)
+- expression 114 operands: lhs = Expression(123, Add), rhs = Counter(35)
+- expression 115 operands: lhs = Expression(124, Add), rhs = Counter(34)
+- expression 116 operands: lhs = Counter(32), rhs = Counter(33)
+- expression 117 operands: lhs = Expression(118, Sub), rhs = Counter(6)
+- expression 118 operands: lhs = Expression(119, Sub), rhs = Counter(5)
+- expression 119 operands: lhs = Expression(120, Sub), rhs = Counter(9)
+- expression 120 operands: lhs = Expression(121, Add), rhs = Counter(4)
+- expression 121 operands: lhs = Counter(31), rhs = Expression(122, Add)
+- expression 122 operands: lhs = Expression(123, Add), rhs = Counter(35)
+- expression 123 operands: lhs = Expression(124, Add), rhs = Counter(34)
+- expression 124 operands: lhs = Counter(32), rhs = Counter(33)
+- expression 125 operands: lhs = Expression(134, Add), rhs = Counter(7)
+- expression 126 operands: lhs = Counter(5), rhs = Counter(6)
+- expression 127 operands: lhs = Expression(133, Add), rhs = Counter(8)
+- expression 128 operands: lhs = Expression(134, Add), rhs = Counter(7)
+- expression 129 operands: lhs = Counter(5), rhs = Counter(6)
+- expression 130 operands: lhs = Expression(131, Add), rhs = Expression(135, Add)
+- expression 131 operands: lhs = Counter(4), rhs = Expression(132, Add)
+- expression 132 operands: lhs = Expression(133, Add), rhs = Counter(8)
+- expression 133 operands: lhs = Expression(134, Add), rhs = Counter(7)
+- expression 134 operands: lhs = Counter(5), rhs = Counter(6)
+- expression 135 operands: lhs = Expression(136, Add), rhs = Expression(139, Sub)
+- expression 136 operands: lhs = Expression(137, Add), rhs = Expression(138, Add)
+- expression 137 operands: lhs = Counter(9), rhs = Counter(10)
+- expression 138 operands: lhs = Counter(11), rhs = Counter(12)
+- expression 139 operands: lhs = Expression(140, Sub), rhs = Counter(3)
+- expression 140 operands: lhs = Expression(141, Add), rhs = Counter(2)
+- expression 141 operands: lhs = Counter(1), rhs = Zero
 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, 6) to (start + 0, 7)
 - Code(Expression(0, Add)) at (prev + 3, 9) to (start + 0, 10)
     = (c2 + (((c13 + c14) + c15) + c16))
-- Code(Expression(143, Add)) at (prev + 0, 16) to (start + 0, 29)
+- Code(Expression(141, Add)) at (prev + 0, 16) to (start + 0, 29)
     = (c1 + Zero)
 - Code(Counter(2)) at (prev + 1, 9) to (start + 1, 10)
-- Code(Expression(142, Sub)) at (prev + 2, 15) to (start + 0, 28)
+- Code(Expression(140, Sub)) at (prev + 2, 15) to (start + 0, 28)
     = ((c1 + Zero) - c2)
 - Code(Counter(3)) at (prev + 1, 12) to (start + 0, 25)
 - Code(Expression(9, Sub)) at (prev + 0, 29) to (start + 0, 42)
@@ -168,94 +166,94 @@ Number of file 0 mappings: 68
 - Code(Counter(16)) at (prev + 2, 10) to (start + 0, 11)
 - Code(Expression(12, Add)) at (prev + 1, 9) to (start + 1, 18)
     = (((c13 + c14) + c15) + c16)
-- Code(Expression(141, Sub)) at (prev + 3, 9) to (start + 0, 15)
+- Code(Expression(139, Sub)) at (prev + 3, 9) to (start + 0, 15)
     = (((c1 + Zero) - c2) - c3)
-- Code(Expression(18, Add)) at (prev + 3, 9) to (start + 1, 12)
-    = ((c2 + (((c13 + c14) + c15) + c16)) + Zero)
+- 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)
 - Code(Zero) at (prev + 2, 6) to (start + 0, 7)
-- Code(Expression(33, Add)) at (prev + 2, 8) to (start + 0, 21)
+- Code(Expression(32, Add)) at (prev + 2, 8) to (start + 0, 21)
     = (c17 + Zero)
 - Code(Counter(18)) at (prev + 0, 22) to (start + 2, 6)
-- Code(Expression(32, Sub)) at (prev + 2, 15) to (start + 0, 28)
+- Code(Expression(31, Sub)) at (prev + 2, 15) to (start + 0, 28)
     = ((c17 + Zero) - c18)
-- Code(Expression(31, Sub)) at (prev + 1, 12) to (start + 0, 25)
+- Code(Expression(30, Sub)) at (prev + 1, 12) to (start + 0, 25)
     = (((c17 + Zero) - c18) - c12)
-- Code(Expression(30, Sub)) at (prev + 0, 29) to (start + 0, 42)
+- Code(Expression(29, Sub)) at (prev + 0, 29) to (start + 0, 42)
     = ((((c17 + Zero) - c18) - c12) - c19)
-- Code(Expression(29, Sub)) at (prev + 0, 46) to (start + 0, 60)
+- Code(Expression(28, Sub)) at (prev + 0, 46) to (start + 0, 60)
     = (((((c17 + Zero) - c18) - c12) - c19) - c20)
-- Code(Expression(41, Add)) at (prev + 0, 61) to (start + 2, 10)
+- Code(Expression(40, Add)) at (prev + 0, 61) to (start + 2, 10)
     = ((c19 + c20) + c21)
 - Code(Counter(22)) at (prev + 2, 10) to (start + 0, 11)
-- Code(Expression(40, Add)) at (prev + 1, 9) to (start + 0, 23)
+- Code(Expression(39, 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(39, Add)) at (prev + 3, 8) to (start + 0, 12)
+- Code(Expression(38, 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)
 - Code(Zero) at (prev + 2, 10) to (start + 0, 11)
-- Code(Expression(57, Add)) at (prev + 2, 12) to (start + 0, 25)
+- Code(Expression(56, Add)) at (prev + 2, 12) to (start + 0, 25)
     = (c24 + Zero)
 - Code(Counter(25)) at (prev + 0, 26) to (start + 2, 10)
-- Code(Expression(56, Sub)) at (prev + 3, 17) to (start + 0, 30)
+- Code(Expression(55, Sub)) at (prev + 3, 17) to (start + 0, 30)
     = ((c24 + Zero) - c25)
-- Code(Expression(55, Sub)) at (prev + 1, 16) to (start + 0, 29)
+- Code(Expression(54, Sub)) at (prev + 1, 16) to (start + 0, 29)
     = (((c24 + Zero) - c25) - c11)
-- Code(Expression(54, Sub)) at (prev + 0, 33) to (start + 0, 46)
+- Code(Expression(53, Sub)) at (prev + 0, 33) to (start + 0, 46)
     = ((((c24 + Zero) - c25) - c11) - c26)
-- Code(Expression(53, Sub)) at (prev + 0, 50) to (start + 0, 64)
+- Code(Expression(52, Sub)) at (prev + 0, 50) to (start + 0, 64)
     = (((((c24 + Zero) - c25) - c11) - c26) - c27)
-- Code(Expression(66, Add)) at (prev + 0, 65) to (start + 2, 14)
+- Code(Expression(65, Add)) at (prev + 0, 65) to (start + 2, 14)
     = ((c26 + c27) + c28)
 - Code(Counter(29)) at (prev + 2, 14) to (start + 0, 15)
-- Code(Expression(65, Add)) at (prev + 1, 13) to (start + 0, 27)
+- Code(Expression(64, Add)) at (prev + 1, 13) to (start + 0, 27)
     = (((c26 + c27) + c28) + c29)
 - Code(Counter(11)) at (prev + 2, 13) to (start + 0, 19)
 - Code(Zero) at (prev + 2, 6) to (start + 0, 7)
-- Code(Expression(63, Add)) at (prev + 2, 9) to (start + 1, 12)
+- Code(Expression(62, 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(Zero) at (prev + 2, 6) to (start + 0, 7)
-- Code(Expression(123, Add)) at (prev + 2, 9) to (start + 0, 10)
+- Code(Expression(121, Add)) at (prev + 2, 9) to (start + 0, 10)
     = (c31 + (((c32 + c33) + c34) + c35))
-- Code(Expression(86, Add)) at (prev + 0, 16) to (start + 0, 29)
+- Code(Expression(85, Add)) at (prev + 0, 16) to (start + 0, 29)
     = (c30 + Zero)
 - Code(Counter(31)) at (prev + 0, 30) to (start + 2, 6)
-- Code(Expression(85, Sub)) at (prev + 2, 15) to (start + 0, 28)
+- Code(Expression(84, Sub)) at (prev + 2, 15) to (start + 0, 28)
     = ((c30 + Zero) - c31)
-- Code(Expression(84, Sub)) at (prev + 1, 12) to (start + 0, 25)
+- Code(Expression(83, Sub)) at (prev + 1, 12) to (start + 0, 25)
     = (((c30 + Zero) - c31) - c10)
-- Code(Expression(83, Sub)) at (prev + 0, 29) to (start + 0, 42)
+- Code(Expression(82, Sub)) at (prev + 0, 29) to (start + 0, 42)
     = ((((c30 + Zero) - c31) - c10) - c32)
-- Code(Expression(82, Sub)) at (prev + 0, 46) to (start + 0, 60)
+- Code(Expression(81, Sub)) at (prev + 0, 46) to (start + 0, 60)
     = (((((c30 + Zero) - c31) - c10) - c32) - c33)
-- Code(Expression(125, Add)) at (prev + 0, 61) to (start + 2, 10)
+- Code(Expression(123, Add)) at (prev + 0, 61) to (start + 2, 10)
     = ((c32 + c33) + c34)
 - Code(Counter(35)) at (prev + 2, 10) to (start + 0, 11)
-- Code(Expression(124, Add)) at (prev + 1, 9) to (start + 0, 23)
+- Code(Expression(122, 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(133, Add)) at (prev + 5, 9) to (start + 0, 10)
+- Code(Expression(131, Add)) at (prev + 5, 9) to (start + 0, 10)
     = (c4 + (((c5 + c6) + c7) + c8))
-- Code(Expression(96, Add)) at (prev + 0, 16) to (start + 0, 29)
-    = ((c31 + (((c32 + c33) + c34) + c35)) + Zero)
+- Code(Expression(121, 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(122, Sub)) at (prev + 2, 15) to (start + 0, 28)
+- Code(Expression(120, Sub)) at (prev + 2, 15) to (start + 0, 28)
     = ((c31 + (((c32 + c33) + c34) + c35)) - c4)
-- Code(Expression(121, Sub)) at (prev + 1, 12) to (start + 0, 25)
+- Code(Expression(119, Sub)) at (prev + 1, 12) to (start + 0, 25)
     = (((c31 + (((c32 + c33) + c34) + c35)) - c4) - c9)
-- Code(Expression(120, Sub)) at (prev + 0, 29) to (start + 0, 42)
+- Code(Expression(118, Sub)) at (prev + 0, 29) to (start + 0, 42)
     = ((((c31 + (((c32 + c33) + c34) + c35)) - c4) - c9) - c5)
-- Code(Expression(119, Sub)) at (prev + 0, 46) to (start + 0, 60)
+- Code(Expression(117, Sub)) at (prev + 0, 46) to (start + 0, 60)
     = (((((c31 + (((c32 + c33) + c34) + c35)) - c4) - c9) - c5) - c6)
-- Code(Expression(135, Add)) at (prev + 0, 61) to (start + 2, 10)
+- Code(Expression(133, Add)) at (prev + 0, 61) to (start + 2, 10)
     = ((c5 + c6) + c7)
 - Code(Counter(8)) at (prev + 2, 10) to (start + 0, 11)
-- Code(Expression(134, Add)) at (prev + 1, 9) to (start + 0, 23)
+- Code(Expression(132, 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(132, Add)) at (prev + 2, 1) to (start + 0, 2)
+- Code(Expression(130, Add)) at (prev + 2, 1) to (start + 0, 2)
     = ((c4 + (((c5 + c6) + c7) + c8)) + (((c9 + c10) + (c11 + c12)) + (((c1 + Zero) - c2) - c3)))
 
diff --git a/tests/coverage-map/status-quo/continue.cov-map b/tests/coverage-map/status-quo/continue.cov-map
index c78cf293079..82f3d7c6095 100644
--- a/tests/coverage-map/status-quo/continue.cov-map
+++ b/tests/coverage-map/status-quo/continue.cov-map
@@ -1,8 +1,8 @@
 Function name: continue::main
-Raw bytes (216): 0x[01, 01, 1f, 01, 07, 05, 09, 03, 0d, 0d, 1f, 11, 15, 1b, 19, 0d, 1f, 11, 15, 15, 00, 19, 37, 1d, 21, 33, 25, 19, 37, 1d, 21, 1d, 00, 25, 4f, 29, 2d, 4b, 31, 25, 4f, 29, 2d, 31, 67, 35, 39, 5f, 3d, 31, 67, 35, 39, 35, 39, 3d, 41, 73, 45, 3d, 41, 41, 00, 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, 23, 03, 09, 00, 0e, 33, 02, 0e, 00, 13, 2e, 01, 0f, 00, 16, 1d, 01, 15, 02, 0e, 21, 04, 11, 00, 19, 3b, 03, 09, 00, 0e, 4b, 02, 0e, 00, 13, 46, 01, 0c, 00, 13, 29, 01, 0d, 00, 15, 2d, 01, 0a, 01, 0e, 5f, 03, 0e, 00, 13, 5a, 01, 0f, 00, 16, 39, 01, 16, 02, 0e, 35, 03, 12, 02, 0e, 67, 04, 09, 00, 0e, 73, 02, 0e, 00, 13, 6e, 01, 0f, 00, 16, 41, 01, 16, 02, 0e, 49, 04, 11, 00, 16, 77, 03, 09, 00, 0e, 7b, 02, 0d, 01, 02]
+Raw bytes (210): 0x[01, 01, 1c, 01, 07, 05, 09, 03, 0d, 0d, 1f, 11, 15, 1b, 19, 0d, 1f, 11, 15, 19, 33, 1d, 21, 2f, 25, 19, 33, 1d, 21, 25, 47, 29, 2d, 43, 31, 25, 47, 29, 2d, 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]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 31
+Number of expressions: 28
 - expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add)
 - expression 1 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3)
@@ -11,29 +11,26 @@ Number of expressions: 31
 - expression 5 operands: lhs = Expression(6, Add), rhs = Counter(6)
 - expression 6 operands: lhs = Counter(3), rhs = Expression(7, Add)
 - expression 7 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 8 operands: lhs = Counter(5), rhs = Zero
-- expression 9 operands: lhs = Counter(6), rhs = Expression(13, Add)
-- expression 10 operands: lhs = Counter(7), rhs = Counter(8)
-- expression 11 operands: lhs = Expression(12, Add), rhs = Counter(9)
-- expression 12 operands: lhs = Counter(6), rhs = Expression(13, Add)
-- expression 13 operands: lhs = Counter(7), rhs = Counter(8)
-- expression 14 operands: lhs = Counter(7), rhs = Zero
-- expression 15 operands: lhs = Counter(9), rhs = Expression(19, Add)
-- expression 16 operands: lhs = Counter(10), rhs = Counter(11)
-- expression 17 operands: lhs = Expression(18, Add), rhs = Counter(12)
-- expression 18 operands: lhs = Counter(9), rhs = Expression(19, Add)
-- expression 19 operands: lhs = Counter(10), rhs = Counter(11)
-- expression 20 operands: lhs = Counter(12), rhs = Expression(25, Add)
-- expression 21 operands: lhs = Counter(13), rhs = Counter(14)
-- expression 22 operands: lhs = Expression(23, Add), rhs = Counter(15)
-- expression 23 operands: lhs = Counter(12), rhs = Expression(25, Add)
-- expression 24 operands: lhs = Counter(13), rhs = Counter(14)
-- expression 25 operands: lhs = Counter(13), rhs = Counter(14)
+- expression 8 operands: lhs = Counter(6), rhs = Expression(12, Add)
+- expression 9 operands: lhs = Counter(7), rhs = Counter(8)
+- expression 10 operands: lhs = Expression(11, Add), rhs = Counter(9)
+- expression 11 operands: lhs = Counter(6), rhs = Expression(12, Add)
+- expression 12 operands: lhs = Counter(7), rhs = Counter(8)
+- expression 13 operands: lhs = Counter(9), rhs = Expression(17, Add)
+- expression 14 operands: lhs = Counter(10), rhs = Counter(11)
+- expression 15 operands: lhs = Expression(16, Add), rhs = Counter(12)
+- expression 16 operands: lhs = Counter(9), rhs = Expression(17, Add)
+- expression 17 operands: lhs = Counter(10), rhs = Counter(11)
+- expression 18 operands: lhs = Counter(12), rhs = Expression(23, Add)
+- expression 19 operands: lhs = Counter(13), rhs = Counter(14)
+- 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 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 = Expression(28, Add), rhs = Counter(17)
-- expression 28 operands: lhs = Counter(15), rhs = Counter(16)
-- expression 29 operands: lhs = Counter(16), rhs = Zero
-- expression 30 operands: lhs = Counter(18), rhs = Counter(17)
+- expression 27 operands: lhs = Counter(18), rhs = Counter(17)
 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)
@@ -48,38 +45,35 @@ Number of file 0 mappings: 30
     = ((c3 + (c4 + c5)) - c6)
 - Code(Counter(5)) at (prev + 1, 22) to (start + 2, 14)
 - Code(Counter(4)) at (prev + 4, 17) to (start + 0, 25)
-- Code(Expression(8, Add)) at (prev + 3, 9) to (start + 0, 14)
-    = (c5 + Zero)
-- Code(Expression(12, Add)) at (prev + 2, 14) to (start + 0, 19)
+- Code(Counter(5)) at (prev + 3, 9) to (start + 0, 14)
+- Code(Expression(11, Add)) at (prev + 2, 14) to (start + 0, 19)
     = (c6 + (c7 + c8))
-- Code(Expression(11, Sub)) at (prev + 1, 15) to (start + 0, 22)
+- Code(Expression(10, Sub)) at (prev + 1, 15) to (start + 0, 22)
     = ((c6 + (c7 + c8)) - c9)
 - Code(Counter(7)) at (prev + 1, 21) to (start + 2, 14)
 - Code(Counter(8)) at (prev + 4, 17) to (start + 0, 25)
-- Code(Expression(14, Add)) at (prev + 3, 9) to (start + 0, 14)
-    = (c7 + Zero)
-- Code(Expression(18, Add)) at (prev + 2, 14) to (start + 0, 19)
+- Code(Counter(7)) at (prev + 3, 9) to (start + 0, 14)
+- Code(Expression(16, Add)) at (prev + 2, 14) to (start + 0, 19)
     = (c9 + (c10 + c11))
-- Code(Expression(17, Sub)) at (prev + 1, 12) to (start + 0, 19)
+- Code(Expression(15, Sub)) at (prev + 1, 12) to (start + 0, 19)
     = ((c9 + (c10 + c11)) - c12)
 - Code(Counter(10)) at (prev + 1, 13) to (start + 0, 21)
 - Code(Counter(11)) at (prev + 1, 10) to (start + 1, 14)
-- Code(Expression(23, Add)) at (prev + 3, 14) to (start + 0, 19)
+- Code(Expression(21, Add)) at (prev + 3, 14) to (start + 0, 19)
     = (c12 + (c13 + c14))
-- Code(Expression(22, Sub)) at (prev + 1, 15) to (start + 0, 22)
+- Code(Expression(20, Sub)) at (prev + 1, 15) to (start + 0, 22)
     = ((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(25, Add)) at (prev + 4, 9) to (start + 0, 14)
+- Code(Expression(23, Add)) at (prev + 4, 9) to (start + 0, 14)
     = (c13 + c14)
-- Code(Expression(28, Add)) at (prev + 2, 14) to (start + 0, 19)
+- Code(Expression(26, Add)) at (prev + 2, 14) to (start + 0, 19)
     = (c15 + c16)
-- Code(Expression(27, Sub)) at (prev + 1, 15) to (start + 0, 22)
+- Code(Expression(25, Sub)) at (prev + 1, 15) to (start + 0, 22)
     = ((c15 + c16) - c17)
 - Code(Counter(16)) at (prev + 1, 22) to (start + 2, 14)
 - Code(Counter(18)) at (prev + 4, 17) to (start + 0, 22)
-- Code(Expression(29, Add)) at (prev + 3, 9) to (start + 0, 14)
-    = (c16 + Zero)
-- Code(Expression(30, Add)) at (prev + 2, 13) to (start + 1, 2)
+- 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)
 
diff --git a/tests/coverage-map/status-quo/dead_code.cov-map b/tests/coverage-map/status-quo/dead_code.cov-map
index 8d5f88e63ef..0b8a40a8cde 100644
--- a/tests/coverage-map/status-quo/dead_code.cov-map
+++ b/tests/coverage-map/status-quo/dead_code.cov-map
@@ -14,23 +14,23 @@ Number of file 0 mappings: 4
     = (c1 + (c0 - c1))
 
 Function name: dead_code::unused_fn (unused)
-Raw bytes (24): 0x[01, 01, 00, 04, 01, 0f, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02]
+Raw bytes (24): 0x[01, 01, 00, 04, 00, 0f, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 15, 1) to (start + 7, 15)
+- Code(Zero) at (prev + 15, 1) to (start + 7, 15)
 - Code(Zero) at (prev + 7, 16) to (start + 2, 6)
 - Code(Zero) at (prev + 2, 6) to (start + 0, 7)
 - Code(Zero) at (prev + 1, 1) to (start + 0, 2)
 
 Function name: dead_code::unused_pub_fn_not_in_library (unused)
-Raw bytes (24): 0x[01, 01, 00, 04, 01, 03, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02]
+Raw bytes (24): 0x[01, 01, 00, 04, 00, 03, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15)
+- Code(Zero) at (prev + 3, 1) to (start + 7, 15)
 - Code(Zero) at (prev + 7, 16) to (start + 2, 6)
 - Code(Zero) at (prev + 2, 6) to (start + 0, 7)
 - Code(Zero) at (prev + 1, 1) to (start + 0, 2)
diff --git a/tests/coverage-map/status-quo/generator.cov-map b/tests/coverage-map/status-quo/generator.cov-map
index a66c1af30f9..75704bcc223 100644
--- a/tests/coverage-map/status-quo/generator.cov-map
+++ b/tests/coverage-map/status-quo/generator.cov-map
@@ -14,38 +14,33 @@ Number of file 0 mappings: 4
     = (c1 + (c0 - c1))
 
 Function name: generator::main
-Raw bytes (71): 0x[01, 01, 0b, 01, 00, 05, 0b, 09, 0d, 11, 00, 11, 15, 2a, 19, 11, 15, 15, 19, 26, 00, 2a, 19, 11, 15, 09, 01, 0f, 01, 02, 16, 03, 07, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 07, 01, 0e, 00, 35, 0f, 02, 0b, 00, 2e, 2a, 01, 22, 00, 27, 26, 00, 2c, 00, 2e, 1f, 01, 0e, 00, 35, 23, 02, 01, 00, 02]
+Raw bytes (65): 0x[01, 01, 08, 05, 07, 09, 0d, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 0f, 01, 02, 16, 01, 07, 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]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 11
-- expression 0 operands: lhs = Counter(0), rhs = Zero
-- expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add)
-- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 3 operands: lhs = Counter(4), rhs = Zero
+Number of expressions: 8
+- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add)
+- expression 1 operands: lhs = Counter(2), rhs = Counter(3)
+- 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 5 operands: lhs = Expression(10, Sub), rhs = Counter(6)
-- expression 6 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 7 operands: lhs = Counter(5), rhs = Counter(6)
-- expression 8 operands: lhs = Expression(9, Sub), rhs = Zero
-- expression 9 operands: lhs = Expression(10, Sub), rhs = Counter(6)
-- expression 10 operands: lhs = Counter(4), rhs = Counter(5)
+- 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)
 Number of file 0 mappings: 9
 - Code(Counter(0)) at (prev + 15, 1) to (start + 2, 22)
-- Code(Expression(0, Add)) at (prev + 7, 11) to (start + 0, 46)
-    = (c0 + Zero)
+- Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46)
 - Code(Counter(4)) at (prev + 1, 43) to (start + 0, 45)
-- Code(Expression(1, Add)) at (prev + 1, 14) to (start + 0, 53)
+- Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 53)
     = (c1 + (c2 + c3))
-- Code(Expression(3, Add)) at (prev + 2, 11) to (start + 0, 46)
-    = (c4 + Zero)
-- Code(Expression(10, Sub)) at (prev + 1, 34) to (start + 0, 39)
+- Code(Counter(4)) at (prev + 2, 11) to (start + 0, 46)
+- Code(Expression(7, Sub)) at (prev + 1, 34) to (start + 0, 39)
     = (c4 - c5)
-- Code(Expression(9, Sub)) at (prev + 0, 44) to (start + 0, 46)
+- Code(Expression(6, Sub)) at (prev + 0, 44) to (start + 0, 46)
     = ((c4 - c5) - c6)
-- Code(Expression(7, Add)) at (prev + 1, 14) to (start + 0, 53)
+- Code(Expression(5, Add)) at (prev + 1, 14) to (start + 0, 53)
     = (c5 + c6)
-- Code(Expression(8, Add)) at (prev + 2, 1) to (start + 0, 2)
-    = (((c4 - c5) - c6) + Zero)
+- Code(Expression(6, Sub)) at (prev + 2, 1) to (start + 0, 2)
+    = ((c4 - c5) - c6)
 
 Function name: generator::main::{closure#0}
 Raw bytes (14): 0x[01, 01, 00, 02, 01, 11, 1c, 01, 1f, 05, 02, 10, 01, 06]
diff --git a/tests/coverage-map/status-quo/inline-dead.cov-map b/tests/coverage-map/status-quo/inline-dead.cov-map
index dec43d3e8bb..483f7ef79c6 100644
--- a/tests/coverage-map/status-quo/inline-dead.cov-map
+++ b/tests/coverage-map/status-quo/inline-dead.cov-map
@@ -1,10 +1,10 @@
 Function name: inline_dead::dead (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 19, 01, 02, 02]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 02, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 25, 1) to (start + 2, 2)
+- Code(Zero) at (prev + 25, 1) to (start + 2, 2)
 
 Function name: inline_dead::live::<false>
 Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 10, 01, 01, 09, 00, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 07, 02, 01, 00, 02]
@@ -22,15 +22,13 @@ Number of file 0 mappings: 4
     = (c1 + (c0 - c1))
 
 Function name: inline_dead::main
-Raw bytes (16): 0x[01, 01, 01, 01, 00, 02, 01, 04, 01, 03, 0d, 03, 07, 06, 02, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0d, 01, 07, 06, 02, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 1
-- expression 0 operands: lhs = Counter(0), rhs = Zero
+Number of expressions: 0
 Number of file 0 mappings: 2
 - Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13)
-- Code(Expression(0, Add)) at (prev + 7, 6) to (start + 2, 2)
-    = (c0 + Zero)
+- Code(Counter(0)) at (prev + 7, 6) to (start + 2, 2)
 
 Function name: inline_dead::main::{closure#0}
 Raw bytes (16): 0x[01, 01, 01, 01, 05, 02, 00, 09, 0d, 00, 0e, 03, 02, 05, 00, 06]
diff --git a/tests/coverage-map/status-quo/inline.cov-map b/tests/coverage-map/status-quo/inline.cov-map
index 57ae85623fb..72b10fd0cc2 100644
--- a/tests/coverage-map/status-quo/inline.cov-map
+++ b/tests/coverage-map/status-quo/inline.cov-map
@@ -1,19 +1,17 @@
 Function name: inline::display::<char>
-Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 00, 03, 05, 05, 01, 29, 01, 00, 22, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 10, 07, 00, 11, 02, 06, 0a, 03, 05, 01, 02]
+Raw bytes (33): 0x[01, 01, 02, 01, 05, 03, 05, 05, 01, 29, 01, 00, 22, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 10, 05, 00, 11, 02, 06, 06, 03, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 3
+Number of expressions: 2
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(1), rhs = Zero
-- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(1)
+- expression 1 operands: lhs = Expression(0, Add), rhs = Counter(1)
 Number of file 0 mappings: 5
 - Code(Counter(0)) at (prev + 41, 1) to (start + 0, 34)
 - Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10)
 - Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 16)
     = (c0 + c1)
-- Code(Expression(1, Add)) at (prev + 0, 17) to (start + 2, 6)
-    = (c1 + Zero)
-- Code(Expression(2, Sub)) at (prev + 3, 5) to (start + 1, 2)
+- Code(Counter(1)) at (prev + 0, 17) to (start + 2, 6)
+- Code(Expression(1, Sub)) at (prev + 3, 5) to (start + 1, 2)
     = ((c0 + c1) - c1)
 
 Function name: inline::error
@@ -41,15 +39,14 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 5, 1) to (start + 2, 2)
 
 Function name: inline::permutate::<char>
-Raw bytes (54): 0x[01, 01, 05, 01, 05, 02, 0d, 11, 00, 05, 13, 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, 0b, 00, 17, 04, 0a, 0d, 05, 0c, 02, 06, 0f, 03, 01, 00, 02]
+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]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 5
+Number of expressions: 4
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(3)
-- expression 2 operands: lhs = Counter(4), rhs = Zero
-- expression 3 operands: lhs = Counter(1), rhs = Expression(4, Add)
-- expression 4 operands: lhs = Counter(2), rhs = Counter(3)
+- expression 2 operands: lhs = Counter(1), rhs = Expression(3, Add)
+- expression 3 operands: lhs = Counter(2), rhs = Counter(3)
 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)
@@ -58,10 +55,9 @@ Number of file 0 mappings: 8
 - 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)
-- Code(Expression(2, Add)) at (prev + 0, 23) to (start + 4, 10)
-    = (c4 + Zero)
+- Code(Counter(4)) at (prev + 0, 23) to (start + 4, 10)
 - Code(Counter(3)) at (prev + 5, 12) to (start + 2, 6)
-- Code(Expression(3, Add)) at (prev + 3, 1) to (start + 0, 2)
+- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2)
     = (c1 + (c2 + c3))
 
 Function name: inline::permutations::<char>
diff --git a/tests/coverage-map/status-quo/issue-93054.cov-map b/tests/coverage-map/status-quo/issue-93054.cov-map
index 52fe7f58d15..c2c6e9a6516 100644
--- a/tests/coverage-map/status-quo/issue-93054.cov-map
+++ b/tests/coverage-map/status-quo/issue-93054.cov-map
@@ -1,10 +1,10 @@
 Function name: issue_93054::foo2 (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 01, 00, 1d]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 00, 1d]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 29)
+- Code(Zero) at (prev + 22, 1) to (start + 0, 29)
 
 Function name: issue_93054::main
 Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 00, 0d]
@@ -15,10 +15,10 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 30, 1) to (start + 0, 13)
 
 Function name: issue_93054::make (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 1a, 01, 02, 02]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 01, 02, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 2)
+- Code(Zero) at (prev + 26, 1) to (start + 2, 2)
 
diff --git a/tests/coverage-map/status-quo/lazy_boolean.cov-map b/tests/coverage-map/status-quo/lazy_boolean.cov-map
index b18a9640433..0ad393c40fa 100644
--- a/tests/coverage-map/status-quo/lazy_boolean.cov-map
+++ b/tests/coverage-map/status-quo/lazy_boolean.cov-map
@@ -1,223 +1,219 @@
 Function name: lazy_boolean::main
-Raw bytes (646): 0x[01, 01, a8, 01, 01, 05, 09, 9a, 05, 9f, 05, 09, 05, 02, 05, 02, 9f, 05, 09, 05, 02, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 97, 05, 00, 09, 9a, 05, 9f, 05, 09, 05, 02, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 8f, 05, 00, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 87, 05, 00, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, ff, 04, 00, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, ef, 04, 21, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 21, ea, 04, ef, 04, 21, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, e7, 04, 25, 21, ea, 04, ef, 04, 21, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 25, e2, 04, e7, 04, 25, 21, ea, 04, ef, 04, 21, 1d, f2, 04, f7, 04, 1d, 19, fa, 04, ff, 04, 19, 15, 82, 05, 87, 05, 15, 11, 8a, 05, 8f, 05, 11, 0d, 92, 05, 97, 05, 0d, 09, 9a, 05, 9f, 05, 09, 05, 02, 1c, 01, 03, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 97, 05, 02, 09, 00, 11, 9f, 05, 02, 0d, 00, 12, 9a, 05, 02, 0d, 00, 12, 8f, 05, 03, 09, 00, 11, 33, 02, 0d, 00, 12, 92, 05, 02, 0d, 00, 12, 87, 05, 02, 09, 00, 11, 6f, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ff, 04, 01, 09, 00, 11, ab, 01, 00, 14, 00, 19, 15, 00, 1d, 00, 22, cb, 01, 04, 09, 00, 10, fa, 04, 01, 05, 03, 06, 19, 03, 06, 00, 07, f7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, f2, 04, 05, 05, 03, 06, ef, 04, 05, 09, 00, 10, ea, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, e7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, e2, 04, 02, 0c, 02, 06, df, 04, 03, 01, 00, 02]
+Raw bytes (636): 0x[01, 01, a4, 01, 01, 05, 09, 8a, 05, 8f, 05, 09, 05, 02, 05, 02, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 09, 8a, 05, 8f, 05, 09, 05, 02, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 25, d2, 04, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1c, 01, 03, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 87, 05, 02, 09, 00, 11, 8f, 05, 02, 0d, 00, 12, 8a, 05, 02, 0d, 00, 12, ff, 04, 03, 09, 00, 11, 87, 05, 02, 0d, 00, 12, 82, 05, 02, 0d, 00, 12, f7, 04, 02, 09, 00, 11, ff, 04, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ef, 04, 01, 09, 00, 11, f7, 04, 00, 14, 00, 19, 15, 00, 1d, 00, 22, ef, 04, 04, 09, 00, 10, ea, 04, 01, 05, 03, 06, 19, 03, 06, 00, 07, e7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, e2, 04, 05, 05, 03, 06, df, 04, 05, 09, 00, 10, da, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, d7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, d2, 04, 02, 0c, 02, 06, cf, 04, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 168
+Number of expressions: 164
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 2 operands: lhs = Expression(167, Add), rhs = Counter(2)
+- expression 1 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 2 operands: lhs = Expression(163, Add), rhs = Counter(2)
 - expression 3 operands: lhs = Counter(1), rhs = Expression(0, Sub)
 - expression 4 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 5 operands: lhs = Expression(167, Add), rhs = Counter(2)
+- expression 5 operands: lhs = Expression(163, Add), rhs = Counter(2)
 - expression 6 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 7 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 8 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 9 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 10 operands: lhs = Expression(167, Add), rhs = Counter(2)
+- expression 7 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 8 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 9 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 10 operands: lhs = Expression(163, Add), rhs = Counter(2)
 - expression 11 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 12 operands: lhs = Expression(165, Add), rhs = Zero
-- expression 13 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 14 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 15 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 16 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 17 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 18 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 19 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 20 operands: lhs = Counter(4), rhs = Expression(162, Sub)
-- expression 21 operands: lhs = Expression(163, Add), rhs = Counter(4)
-- expression 22 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 23 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 24 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 25 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 26 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 27 operands: lhs = Expression(163, Add), rhs = Zero
-- expression 28 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 29 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 30 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 31 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 32 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 33 operands: lhs = Counter(5), rhs = Expression(160, Sub)
-- expression 34 operands: lhs = Expression(161, Add), rhs = Counter(5)
-- expression 35 operands: lhs = Counter(4), rhs = Expression(162, Sub)
-- expression 36 operands: lhs = Expression(163, Add), rhs = Counter(4)
-- expression 37 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 38 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 39 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 40 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 41 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 42 operands: lhs = Expression(161, Add), rhs = Zero
-- expression 43 operands: lhs = Counter(4), rhs = Expression(162, Sub)
-- expression 44 operands: lhs = Expression(163, Add), rhs = Counter(4)
-- expression 45 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 46 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 47 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 48 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 49 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 50 operands: lhs = Expression(159, Add), rhs = Zero
-- expression 51 operands: lhs = Counter(5), rhs = Expression(160, Sub)
-- expression 52 operands: lhs = Expression(161, Add), rhs = Counter(5)
-- expression 53 operands: lhs = Counter(4), rhs = Expression(162, Sub)
-- expression 54 operands: lhs = Expression(163, Add), rhs = Counter(4)
-- expression 55 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 56 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 57 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 58 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 59 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 60 operands: lhs = Expression(159, Add), rhs = Counter(6)
-- expression 61 operands: lhs = Counter(5), rhs = Expression(160, Sub)
-- expression 62 operands: lhs = Expression(161, Add), rhs = Counter(5)
-- expression 63 operands: lhs = Counter(4), rhs = Expression(162, Sub)
-- expression 64 operands: lhs = Expression(163, Add), rhs = Counter(4)
-- expression 65 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 66 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 67 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 68 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 69 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 70 operands: lhs = Counter(6), rhs = Expression(158, Sub)
-- expression 71 operands: lhs = Expression(159, Add), rhs = Counter(6)
-- expression 72 operands: lhs = Counter(5), rhs = Expression(160, Sub)
-- expression 73 operands: lhs = Expression(161, Add), rhs = Counter(5)
-- expression 74 operands: lhs = Counter(4), rhs = Expression(162, Sub)
-- expression 75 operands: lhs = Expression(163, Add), rhs = Counter(4)
-- expression 76 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 77 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 78 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 79 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 80 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 81 operands: lhs = Expression(157, Add), rhs = Counter(7)
-- expression 82 operands: lhs = Counter(6), rhs = Expression(158, Sub)
-- expression 83 operands: lhs = Expression(159, Add), rhs = Counter(6)
-- expression 84 operands: lhs = Counter(5), rhs = Expression(160, Sub)
-- expression 85 operands: lhs = Expression(161, Add), rhs = Counter(5)
-- expression 86 operands: lhs = Counter(4), rhs = Expression(162, Sub)
-- expression 87 operands: lhs = Expression(163, Add), rhs = Counter(4)
-- expression 88 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 89 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 90 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 91 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 92 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 93 operands: lhs = Counter(7), rhs = Expression(156, Sub)
-- expression 94 operands: lhs = Expression(157, Add), rhs = Counter(7)
-- expression 95 operands: lhs = Counter(6), rhs = Expression(158, Sub)
-- expression 96 operands: lhs = Expression(159, Add), rhs = Counter(6)
-- expression 97 operands: lhs = Counter(5), rhs = Expression(160, Sub)
-- expression 98 operands: lhs = Expression(161, Add), rhs = Counter(5)
-- expression 99 operands: lhs = Counter(4), rhs = Expression(162, Sub)
-- expression 100 operands: lhs = Expression(163, Add), rhs = Counter(4)
-- expression 101 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 102 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 103 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 104 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 105 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 106 operands: lhs = Expression(155, Add), rhs = Counter(8)
-- expression 107 operands: lhs = Counter(7), rhs = Expression(156, Sub)
-- expression 108 operands: lhs = Expression(157, Add), rhs = Counter(7)
-- expression 109 operands: lhs = Counter(6), rhs = Expression(158, Sub)
-- expression 110 operands: lhs = Expression(159, Add), rhs = Counter(6)
-- expression 111 operands: lhs = Counter(5), rhs = Expression(160, Sub)
-- expression 112 operands: lhs = Expression(161, Add), rhs = Counter(5)
-- expression 113 operands: lhs = Counter(4), rhs = Expression(162, Sub)
-- expression 114 operands: lhs = Expression(163, Add), rhs = Counter(4)
-- expression 115 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 116 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 117 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 118 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 119 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 120 operands: lhs = Counter(8), rhs = Expression(154, Sub)
-- expression 121 operands: lhs = Expression(155, Add), rhs = Counter(8)
-- expression 122 operands: lhs = Counter(7), rhs = Expression(156, Sub)
-- expression 123 operands: lhs = Expression(157, Add), rhs = Counter(7)
-- expression 124 operands: lhs = Counter(6), rhs = Expression(158, Sub)
-- expression 125 operands: lhs = Expression(159, Add), rhs = Counter(6)
-- expression 126 operands: lhs = Counter(5), rhs = Expression(160, Sub)
-- expression 127 operands: lhs = Expression(161, Add), rhs = Counter(5)
-- expression 128 operands: lhs = Counter(4), rhs = Expression(162, Sub)
-- expression 129 operands: lhs = Expression(163, Add), rhs = Counter(4)
-- expression 130 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 131 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 132 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 133 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 134 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 135 operands: lhs = Expression(153, Add), rhs = Counter(9)
-- expression 136 operands: lhs = Counter(8), rhs = Expression(154, Sub)
-- expression 137 operands: lhs = Expression(155, Add), rhs = Counter(8)
-- expression 138 operands: lhs = Counter(7), rhs = Expression(156, Sub)
-- expression 139 operands: lhs = Expression(157, Add), rhs = Counter(7)
-- expression 140 operands: lhs = Counter(6), rhs = Expression(158, Sub)
-- expression 141 operands: lhs = Expression(159, Add), rhs = Counter(6)
-- expression 142 operands: lhs = Counter(5), rhs = Expression(160, Sub)
-- expression 143 operands: lhs = Expression(161, Add), rhs = Counter(5)
-- expression 144 operands: lhs = Counter(4), rhs = Expression(162, Sub)
-- expression 145 operands: lhs = Expression(163, Add), rhs = Counter(4)
-- expression 146 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 147 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 148 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 149 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 150 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 151 operands: lhs = Counter(9), rhs = Expression(152, Sub)
-- expression 152 operands: lhs = Expression(153, Add), rhs = Counter(9)
-- expression 153 operands: lhs = Counter(8), rhs = Expression(154, Sub)
-- expression 154 operands: lhs = Expression(155, Add), rhs = Counter(8)
-- expression 155 operands: lhs = Counter(7), rhs = Expression(156, Sub)
-- expression 156 operands: lhs = Expression(157, Add), rhs = Counter(7)
-- expression 157 operands: lhs = Counter(6), rhs = Expression(158, Sub)
-- expression 158 operands: lhs = Expression(159, Add), rhs = Counter(6)
-- expression 159 operands: lhs = Counter(5), rhs = Expression(160, Sub)
-- expression 160 operands: lhs = Expression(161, Add), rhs = Counter(5)
-- expression 161 operands: lhs = Counter(4), rhs = Expression(162, Sub)
-- expression 162 operands: lhs = Expression(163, Add), rhs = Counter(4)
-- expression 163 operands: lhs = Counter(3), rhs = Expression(164, Sub)
-- expression 164 operands: lhs = Expression(165, Add), rhs = Counter(3)
-- expression 165 operands: lhs = Counter(2), rhs = Expression(166, Sub)
-- expression 166 operands: lhs = Expression(167, Add), rhs = Counter(2)
-- expression 167 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 12 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 13 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 14 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 15 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 16 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 17 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 18 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 19 operands: lhs = Counter(4), rhs = Expression(158, Sub)
+- expression 20 operands: lhs = Expression(159, Add), rhs = Counter(4)
+- expression 21 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 22 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 23 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 24 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 25 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 26 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 27 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 28 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 29 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 30 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 31 operands: lhs = Counter(5), rhs = Expression(156, Sub)
+- expression 32 operands: lhs = Expression(157, Add), rhs = Counter(5)
+- expression 33 operands: lhs = Counter(4), rhs = Expression(158, Sub)
+- expression 34 operands: lhs = Expression(159, Add), rhs = Counter(4)
+- expression 35 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 36 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 37 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 38 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 39 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 40 operands: lhs = Counter(4), rhs = Expression(158, Sub)
+- expression 41 operands: lhs = Expression(159, Add), rhs = Counter(4)
+- expression 42 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 43 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 44 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 45 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 46 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 47 operands: lhs = Counter(5), rhs = Expression(156, Sub)
+- expression 48 operands: lhs = Expression(157, Add), rhs = Counter(5)
+- expression 49 operands: lhs = Counter(4), rhs = Expression(158, Sub)
+- expression 50 operands: lhs = Expression(159, Add), rhs = Counter(4)
+- expression 51 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 52 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 53 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 54 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 55 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 56 operands: lhs = Expression(155, Add), rhs = Counter(6)
+- expression 57 operands: lhs = Counter(5), rhs = Expression(156, Sub)
+- expression 58 operands: lhs = Expression(157, Add), rhs = Counter(5)
+- expression 59 operands: lhs = Counter(4), rhs = Expression(158, Sub)
+- expression 60 operands: lhs = Expression(159, Add), rhs = Counter(4)
+- expression 61 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 62 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 63 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 64 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 65 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 66 operands: lhs = Counter(6), rhs = Expression(154, Sub)
+- expression 67 operands: lhs = Expression(155, Add), rhs = Counter(6)
+- expression 68 operands: lhs = Counter(5), rhs = Expression(156, Sub)
+- expression 69 operands: lhs = Expression(157, Add), rhs = Counter(5)
+- expression 70 operands: lhs = Counter(4), rhs = Expression(158, Sub)
+- expression 71 operands: lhs = Expression(159, Add), rhs = Counter(4)
+- expression 72 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 73 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 74 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 75 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 76 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 77 operands: lhs = Expression(153, Add), rhs = Counter(7)
+- expression 78 operands: lhs = Counter(6), rhs = Expression(154, Sub)
+- expression 79 operands: lhs = Expression(155, Add), rhs = Counter(6)
+- expression 80 operands: lhs = Counter(5), rhs = Expression(156, Sub)
+- expression 81 operands: lhs = Expression(157, Add), rhs = Counter(5)
+- expression 82 operands: lhs = Counter(4), rhs = Expression(158, Sub)
+- expression 83 operands: lhs = Expression(159, Add), rhs = Counter(4)
+- expression 84 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 85 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 86 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 87 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 88 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 89 operands: lhs = Counter(7), rhs = Expression(152, Sub)
+- expression 90 operands: lhs = Expression(153, Add), rhs = Counter(7)
+- expression 91 operands: lhs = Counter(6), rhs = Expression(154, Sub)
+- expression 92 operands: lhs = Expression(155, Add), rhs = Counter(6)
+- expression 93 operands: lhs = Counter(5), rhs = Expression(156, Sub)
+- expression 94 operands: lhs = Expression(157, Add), rhs = Counter(5)
+- expression 95 operands: lhs = Counter(4), rhs = Expression(158, Sub)
+- expression 96 operands: lhs = Expression(159, Add), rhs = Counter(4)
+- expression 97 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 98 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 99 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 100 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 101 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 102 operands: lhs = Expression(151, Add), rhs = Counter(8)
+- expression 103 operands: lhs = Counter(7), rhs = Expression(152, Sub)
+- expression 104 operands: lhs = Expression(153, Add), rhs = Counter(7)
+- expression 105 operands: lhs = Counter(6), rhs = Expression(154, Sub)
+- expression 106 operands: lhs = Expression(155, Add), rhs = Counter(6)
+- expression 107 operands: lhs = Counter(5), rhs = Expression(156, Sub)
+- expression 108 operands: lhs = Expression(157, Add), rhs = Counter(5)
+- expression 109 operands: lhs = Counter(4), rhs = Expression(158, Sub)
+- expression 110 operands: lhs = Expression(159, Add), rhs = Counter(4)
+- expression 111 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 112 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 113 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 114 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 115 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 116 operands: lhs = Counter(8), rhs = Expression(150, Sub)
+- expression 117 operands: lhs = Expression(151, Add), rhs = Counter(8)
+- expression 118 operands: lhs = Counter(7), rhs = Expression(152, Sub)
+- expression 119 operands: lhs = Expression(153, Add), rhs = Counter(7)
+- expression 120 operands: lhs = Counter(6), rhs = Expression(154, Sub)
+- expression 121 operands: lhs = Expression(155, Add), rhs = Counter(6)
+- expression 122 operands: lhs = Counter(5), rhs = Expression(156, Sub)
+- expression 123 operands: lhs = Expression(157, Add), rhs = Counter(5)
+- expression 124 operands: lhs = Counter(4), rhs = Expression(158, Sub)
+- expression 125 operands: lhs = Expression(159, Add), rhs = Counter(4)
+- expression 126 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 127 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 128 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 129 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 130 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 131 operands: lhs = Expression(149, Add), rhs = Counter(9)
+- expression 132 operands: lhs = Counter(8), rhs = Expression(150, Sub)
+- expression 133 operands: lhs = Expression(151, Add), rhs = Counter(8)
+- expression 134 operands: lhs = Counter(7), rhs = Expression(152, Sub)
+- expression 135 operands: lhs = Expression(153, Add), rhs = Counter(7)
+- expression 136 operands: lhs = Counter(6), rhs = Expression(154, Sub)
+- expression 137 operands: lhs = Expression(155, Add), rhs = Counter(6)
+- expression 138 operands: lhs = Counter(5), rhs = Expression(156, Sub)
+- expression 139 operands: lhs = Expression(157, Add), rhs = Counter(5)
+- expression 140 operands: lhs = Counter(4), rhs = Expression(158, Sub)
+- expression 141 operands: lhs = Expression(159, Add), rhs = Counter(4)
+- expression 142 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 143 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 144 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 145 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 146 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 147 operands: lhs = Counter(9), rhs = Expression(148, Sub)
+- expression 148 operands: lhs = Expression(149, Add), rhs = Counter(9)
+- expression 149 operands: lhs = Counter(8), rhs = Expression(150, Sub)
+- expression 150 operands: lhs = Expression(151, Add), rhs = Counter(8)
+- expression 151 operands: lhs = Counter(7), rhs = Expression(152, Sub)
+- expression 152 operands: lhs = Expression(153, Add), rhs = Counter(7)
+- expression 153 operands: lhs = Counter(6), rhs = Expression(154, Sub)
+- expression 154 operands: lhs = Expression(155, Add), rhs = Counter(6)
+- expression 155 operands: lhs = Counter(5), rhs = Expression(156, Sub)
+- expression 156 operands: lhs = Expression(157, Add), rhs = Counter(5)
+- expression 157 operands: lhs = Counter(4), rhs = Expression(158, Sub)
+- expression 158 operands: lhs = Expression(159, Add), rhs = Counter(4)
+- expression 159 operands: lhs = Counter(3), rhs = Expression(160, Sub)
+- expression 160 operands: lhs = Expression(161, Add), rhs = Counter(3)
+- expression 161 operands: lhs = Counter(2), rhs = Expression(162, Sub)
+- expression 162 operands: lhs = Expression(163, Add), rhs = Counter(2)
+- expression 163 operands: lhs = Counter(1), rhs = Expression(0, Sub)
 Number of file 0 mappings: 28
 - Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15)
 - Code(Counter(1)) at (prev + 7, 16) to (start + 4, 6)
 - Code(Expression(0, Sub)) at (prev + 4, 6) to (start + 0, 7)
     = (c0 - c1)
-- Code(Expression(165, Add)) at (prev + 2, 9) to (start + 0, 17)
+- Code(Expression(161, Add)) at (prev + 2, 9) to (start + 0, 17)
     = (c2 + ((c1 + (c0 - c1)) - c2))
-- Code(Expression(167, Add)) at (prev + 2, 13) to (start + 0, 18)
+- Code(Expression(163, Add)) at (prev + 2, 13) to (start + 0, 18)
     = (c1 + (c0 - c1))
-- Code(Expression(166, Sub)) at (prev + 2, 13) to (start + 0, 18)
+- Code(Expression(162, Sub)) at (prev + 2, 13) to (start + 0, 18)
     = ((c1 + (c0 - c1)) - c2)
-- Code(Expression(163, Add)) at (prev + 3, 9) to (start + 0, 17)
+- Code(Expression(159, Add)) at (prev + 3, 9) to (start + 0, 17)
     = (c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3))
-- Code(Expression(12, Add)) at (prev + 2, 13) to (start + 0, 18)
-    = ((c2 + ((c1 + (c0 - c1)) - c2)) + Zero)
-- Code(Expression(164, Sub)) at (prev + 2, 13) to (start + 0, 18)
+- Code(Expression(161, Add)) at (prev + 2, 13) to (start + 0, 18)
+    = (c2 + ((c1 + (c0 - c1)) - c2))
+- Code(Expression(160, Sub)) at (prev + 2, 13) to (start + 0, 18)
     = ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)
-- Code(Expression(161, Add)) at (prev + 2, 9) to (start + 0, 17)
+- Code(Expression(157, Add)) at (prev + 2, 9) to (start + 0, 17)
     = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4))
-- Code(Expression(27, Add)) at (prev + 0, 20) to (start + 0, 25)
-    = ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) + Zero)
+- Code(Expression(159, Add)) at (prev + 0, 20) to (start + 0, 25)
+    = (c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3))
 - Code(Counter(4)) at (prev + 0, 29) to (start + 0, 34)
-- Code(Expression(159, Add)) at (prev + 1, 9) to (start + 0, 17)
+- Code(Expression(155, Add)) at (prev + 1, 9) to (start + 0, 17)
     = (c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5))
-- Code(Expression(42, Add)) at (prev + 0, 20) to (start + 0, 25)
-    = ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) + Zero)
+- Code(Expression(157, Add)) at (prev + 0, 20) to (start + 0, 25)
+    = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4))
 - Code(Counter(5)) at (prev + 0, 29) to (start + 0, 34)
-- Code(Expression(50, Add)) at (prev + 4, 9) to (start + 0, 16)
-    = ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) + Zero)
-- Code(Expression(158, Sub)) at (prev + 1, 5) to (start + 3, 6)
+- Code(Expression(155, Add)) at (prev + 4, 9) to (start + 0, 16)
+    = (c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5))
+- Code(Expression(154, Sub)) at (prev + 1, 5) to (start + 3, 6)
     = ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)
 - Code(Counter(6)) at (prev + 3, 6) to (start + 0, 7)
-- Code(Expression(157, Add)) at (prev + 3, 9) to (start + 0, 16)
+- Code(Expression(153, Add)) at (prev + 3, 9) to (start + 0, 16)
     = (c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6))
 - Code(Counter(7)) at (prev + 1, 5) to (start + 3, 6)
-- Code(Expression(156, Sub)) at (prev + 5, 5) to (start + 3, 6)
+- Code(Expression(152, Sub)) at (prev + 5, 5) to (start + 3, 6)
     = ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)
-- Code(Expression(155, Add)) at (prev + 5, 9) to (start + 0, 16)
+- Code(Expression(151, Add)) at (prev + 5, 9) to (start + 0, 16)
     = (c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7))
-- Code(Expression(154, Sub)) at (prev + 0, 17) to (start + 2, 6)
+- Code(Expression(150, Sub)) at (prev + 0, 17) to (start + 2, 6)
     = ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8)
 - Code(Counter(8)) at (prev + 2, 6) to (start + 0, 7)
-- Code(Expression(153, Add)) at (prev + 2, 8) to (start + 0, 15)
+- Code(Expression(149, Add)) at (prev + 2, 8) to (start + 0, 15)
     = (c8 + ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8))
 - Code(Counter(9)) at (prev + 0, 16) to (start + 2, 6)
-- Code(Expression(152, Sub)) at (prev + 2, 12) to (start + 2, 6)
+- Code(Expression(148, Sub)) at (prev + 2, 12) to (start + 2, 6)
     = ((c8 + ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8)) - c9)
-- Code(Expression(151, Add)) at (prev + 3, 1) to (start + 0, 2)
+- Code(Expression(147, Add)) at (prev + 3, 1) to (start + 0, 2)
     = (c9 + ((c8 + ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8)) - c9))
 
diff --git a/tests/coverage-map/status-quo/loops_branches.cov-map b/tests/coverage-map/status-quo/loops_branches.cov-map
index 480bbfd9795..ebace8cbd71 100644
--- a/tests/coverage-map/status-quo/loops_branches.cov-map
+++ b/tests/coverage-map/status-quo/loops_branches.cov-map
@@ -1,58 +1,57 @@
 Function name: <loops_branches::DebugTest as core::fmt::Debug>::fmt
-Raw bytes (251): 0x[01, 01, 32, 05, 09, 00, 02, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, c3, 01, c7, 01, 0d, 00, 11, 15, ba, 01, 00, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, b6, 01, 1d, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, 00, b2, 01, b6, 01, 1d, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, af, 01, 11, 00, b2, 01, b6, 01, 1d, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, 25, a7, 01, aa, 01, 19, af, 01, 11, 00, b2, 01, b6, 01, 1d, ba, 01, 15, bf, 01, 19, c3, 01, c7, 01, 0d, 00, 11, 15, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 02, 01, 0e, 00, 0f, 07, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, ba, 01, 03, 0d, 00, 0e, bf, 01, 00, 12, 00, 17, 27, 01, 10, 00, 14, b6, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, b2, 01, 01, 12, 00, 13, af, 01, 01, 11, 00, 22, aa, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, a3, 01, 01, 05, 00, 06]
+Raw bytes (249): 0x[01, 01, 31, 05, 09, 00, 02, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, bf, 01, c3, 01, 0d, 00, 11, 15, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, b6, 01, 15, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, b2, 01, 1d, b6, 01, 15, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, 00, ae, 01, b2, 01, 1d, b6, 01, 15, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, ab, 01, 11, 00, ae, 01, b2, 01, 1d, b6, 01, 15, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, 25, a3, 01, a6, 01, 19, ab, 01, 11, 00, ae, 01, b2, 01, 1d, b6, 01, 15, bb, 01, 19, bf, 01, c3, 01, 0d, 00, 11, 15, 14, 01, 09, 05, 01, 10, 05, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 02, 01, 0e, 00, 0f, 07, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, b6, 01, 03, 0d, 00, 0e, bb, 01, 00, 12, 00, 17, b6, 01, 01, 10, 00, 14, b2, 01, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, ae, 01, 01, 12, 00, 13, ab, 01, 01, 11, 00, 22, a6, 01, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 19, 03, 09, 00, 0f, 9f, 01, 01, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 50
+Number of expressions: 49
 - expression 0 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 1 operands: lhs = Zero, rhs = Expression(0, Sub)
-- expression 2 operands: lhs = Expression(47, Add), rhs = Counter(6)
-- expression 3 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
+- expression 2 operands: lhs = Expression(46, Add), rhs = Counter(6)
+- expression 3 operands: lhs = Expression(47, Add), rhs = Expression(48, Add)
 - expression 4 operands: lhs = Counter(3), rhs = Zero
 - expression 5 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 6 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
+- expression 6 operands: lhs = Expression(47, Add), rhs = Expression(48, Add)
 - expression 7 operands: lhs = Counter(3), rhs = Zero
 - expression 8 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 9 operands: lhs = Expression(46, Sub), rhs = Zero
-- expression 10 operands: lhs = Expression(47, Add), rhs = Counter(6)
-- expression 11 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
-- expression 12 operands: lhs = Counter(3), rhs = Zero
-- expression 13 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 14 operands: lhs = Expression(46, Sub), rhs = Counter(5)
-- expression 15 operands: lhs = Expression(47, Add), rhs = Counter(6)
-- expression 16 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
-- expression 17 operands: lhs = Counter(3), rhs = Zero
-- expression 18 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 19 operands: lhs = Expression(45, Sub), rhs = Counter(7)
-- expression 20 operands: lhs = Expression(46, Sub), rhs = Counter(5)
-- expression 21 operands: lhs = Expression(47, Add), rhs = Counter(6)
-- expression 22 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
-- expression 23 operands: lhs = Counter(3), rhs = Zero
-- expression 24 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 25 operands: lhs = Zero, rhs = Expression(44, Sub)
-- expression 26 operands: lhs = Expression(45, Sub), rhs = Counter(7)
-- expression 27 operands: lhs = Expression(46, Sub), rhs = Counter(5)
-- expression 28 operands: lhs = Expression(47, Add), rhs = Counter(6)
-- expression 29 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
-- expression 30 operands: lhs = Counter(3), rhs = Zero
-- expression 31 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 32 operands: lhs = Expression(43, Add), rhs = Counter(4)
-- expression 33 operands: lhs = Zero, rhs = Expression(44, Sub)
-- expression 34 operands: lhs = Expression(45, Sub), rhs = Counter(7)
-- expression 35 operands: lhs = Expression(46, Sub), rhs = Counter(5)
-- expression 36 operands: lhs = Expression(47, Add), rhs = Counter(6)
-- expression 37 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
-- expression 38 operands: lhs = Counter(3), rhs = Zero
-- expression 39 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 40 operands: lhs = Counter(9), rhs = Expression(41, Add)
-- expression 41 operands: lhs = Expression(42, Sub), rhs = Counter(6)
-- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(4)
-- expression 43 operands: lhs = Zero, rhs = Expression(44, Sub)
-- expression 44 operands: lhs = Expression(45, Sub), rhs = Counter(7)
-- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(5)
-- expression 46 operands: lhs = Expression(47, Add), rhs = Counter(6)
-- expression 47 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
-- expression 48 operands: lhs = Counter(3), rhs = Zero
-- expression 49 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 9 operands: lhs = Expression(46, Add), rhs = Counter(6)
+- expression 10 operands: lhs = Expression(47, Add), rhs = Expression(48, Add)
+- expression 11 operands: lhs = Counter(3), rhs = Zero
+- expression 12 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 13 operands: lhs = Expression(45, Sub), rhs = Counter(5)
+- expression 14 operands: lhs = Expression(46, Add), rhs = Counter(6)
+- expression 15 operands: lhs = Expression(47, Add), rhs = Expression(48, Add)
+- expression 16 operands: lhs = Counter(3), rhs = Zero
+- expression 17 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 18 operands: lhs = Expression(44, Sub), rhs = Counter(7)
+- expression 19 operands: lhs = Expression(45, Sub), rhs = Counter(5)
+- expression 20 operands: lhs = Expression(46, Add), rhs = Counter(6)
+- expression 21 operands: lhs = Expression(47, Add), rhs = Expression(48, Add)
+- expression 22 operands: lhs = Counter(3), rhs = Zero
+- expression 23 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 24 operands: lhs = Zero, rhs = Expression(43, Sub)
+- expression 25 operands: lhs = Expression(44, Sub), rhs = Counter(7)
+- expression 26 operands: lhs = Expression(45, Sub), rhs = Counter(5)
+- expression 27 operands: lhs = Expression(46, Add), rhs = Counter(6)
+- expression 28 operands: lhs = Expression(47, Add), rhs = Expression(48, Add)
+- expression 29 operands: lhs = Counter(3), rhs = Zero
+- expression 30 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 31 operands: lhs = Expression(42, Add), rhs = Counter(4)
+- expression 32 operands: lhs = Zero, rhs = Expression(43, Sub)
+- expression 33 operands: lhs = Expression(44, Sub), rhs = Counter(7)
+- expression 34 operands: lhs = Expression(45, Sub), rhs = Counter(5)
+- expression 35 operands: lhs = Expression(46, Add), rhs = Counter(6)
+- expression 36 operands: lhs = Expression(47, Add), rhs = Expression(48, Add)
+- expression 37 operands: lhs = Counter(3), rhs = Zero
+- expression 38 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 39 operands: lhs = Counter(9), rhs = Expression(40, Add)
+- expression 40 operands: lhs = Expression(41, Sub), rhs = Counter(6)
+- expression 41 operands: lhs = Expression(42, Add), rhs = Counter(4)
+- expression 42 operands: lhs = Zero, rhs = Expression(43, Sub)
+- expression 43 operands: lhs = Expression(44, Sub), rhs = Counter(7)
+- expression 44 operands: lhs = Expression(45, Sub), rhs = Counter(5)
+- expression 45 operands: lhs = Expression(46, Add), rhs = Counter(6)
+- expression 46 operands: lhs = Expression(47, Add), rhs = Expression(48, Add)
+- expression 47 operands: lhs = Counter(3), rhs = Zero
+- expression 48 operands: lhs = Counter(4), rhs = Counter(5)
 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)
@@ -64,84 +63,83 @@ Number of file 0 mappings: 20
     = (Zero + (c1 - c2))
 - Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31)
 - Code(Zero) at (prev + 1, 16) to (start + 1, 10)
-- Code(Expression(46, Sub)) at (prev + 3, 13) to (start + 0, 14)
+- Code(Expression(45, Sub)) at (prev + 3, 13) to (start + 0, 14)
     = (((c3 + Zero) + (c4 + c5)) - c6)
-- Code(Expression(47, Add)) at (prev + 0, 18) to (start + 0, 23)
+- Code(Expression(46, Add)) at (prev + 0, 18) to (start + 0, 23)
     = ((c3 + Zero) + (c4 + c5))
-- Code(Expression(9, Add)) at (prev + 1, 16) to (start + 0, 20)
-    = ((((c3 + Zero) + (c4 + c5)) - c6) + Zero)
-- Code(Expression(45, Sub)) at (prev + 1, 20) to (start + 0, 25)
+- Code(Expression(45, Sub)) at (prev + 1, 16) to (start + 0, 20)
+    = (((c3 + Zero) + (c4 + c5)) - c6)
+- Code(Expression(44, Sub)) at (prev + 1, 20) to (start + 0, 25)
     = ((((c3 + Zero) + (c4 + c5)) - c6) - c5)
 - Code(Zero) at (prev + 1, 27) to (start + 0, 31)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 34)
-- Code(Expression(44, Sub)) at (prev + 1, 18) to (start + 0, 19)
+- Code(Expression(43, Sub)) at (prev + 1, 18) to (start + 0, 19)
     = (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)
-- Code(Expression(43, Add)) at (prev + 1, 17) to (start + 0, 34)
+- Code(Expression(42, Add)) at (prev + 1, 17) to (start + 0, 34)
     = (Zero + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7))
-- Code(Expression(42, Sub)) at (prev + 0, 34) to (start + 0, 35)
+- Code(Expression(41, Sub)) at (prev + 0, 34) to (start + 0, 35)
     = ((Zero + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4)
 - Code(Zero) at (prev + 1, 20) to (start + 1, 14)
 - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15)
-- Code(Expression(40, Add)) at (prev + 1, 5) to (start + 0, 6)
+- Code(Expression(39, Add)) at (prev + 1, 5) to (start + 0, 6)
     = (c9 + (((Zero + (((((c3 + Zero) + (c4 + c5)) - c6) - c5) - c7)) - c4) + c6))
 
 Function name: <loops_branches::DisplayTest as core::fmt::Display>::fmt
-Raw bytes (255): 0x[01, 01, 34, 01, 05, 02, 09, 00, 0e, 02, 09, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, c7, 01, cb, 01, 05, 0d, 11, 15, be, 01, 00, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, ba, 01, 1d, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, 00, b6, 01, ba, 01, 1d, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, b3, 01, 15, 00, b6, 01, ba, 01, 1d, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, ae, 01, cf, 01, b3, 01, 15, 00, b6, 01, ba, 01, 1d, be, 01, 11, c3, 01, 19, c7, 01, cb, 01, 05, 0d, 11, 15, 19, 25, 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, 0e, 01, 0e, 00, 0f, 0b, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, be, 01, 02, 0d, 00, 0e, c3, 01, 00, 12, 00, 17, 2f, 01, 10, 00, 15, 00, 00, 16, 01, 0e, ba, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, b6, 01, 01, 12, 00, 13, b3, 01, 01, 11, 00, 22, ae, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, ab, 01, 01, 05, 00, 06]
+Raw bytes (253): 0x[01, 01, 33, 01, 05, 02, 09, 00, 0e, 02, 09, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, c3, 01, c7, 01, 05, 0d, 11, 15, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, ba, 01, 11, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, b6, 01, 1d, ba, 01, 11, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, 00, b2, 01, b6, 01, 1d, ba, 01, 11, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, af, 01, 15, 00, b2, 01, b6, 01, 1d, ba, 01, 11, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, aa, 01, cb, 01, af, 01, 15, 00, b2, 01, b6, 01, 1d, ba, 01, 11, bf, 01, 19, c3, 01, c7, 01, 05, 0d, 11, 15, 19, 25, 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, 0e, 01, 0e, 00, 0f, 0b, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, ba, 01, 02, 0d, 00, 0e, bf, 01, 00, 12, 00, 17, ba, 01, 01, 10, 00, 15, 00, 00, 16, 01, 0e, b6, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, b2, 01, 01, 12, 00, 13, af, 01, 01, 11, 00, 22, aa, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, a7, 01, 01, 05, 00, 06]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 52
+Number of expressions: 51
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 1 operands: lhs = Expression(0, Sub), rhs = Counter(2)
 - expression 2 operands: lhs = Zero, rhs = Expression(3, Sub)
 - expression 3 operands: lhs = Expression(0, Sub), rhs = Counter(2)
-- expression 4 operands: lhs = Expression(48, Add), rhs = Counter(6)
-- expression 5 operands: lhs = Expression(49, Add), rhs = Expression(50, Add)
+- expression 4 operands: lhs = Expression(47, Add), rhs = Counter(6)
+- expression 5 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
 - expression 6 operands: lhs = Counter(1), rhs = Counter(3)
 - expression 7 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 8 operands: lhs = Expression(49, Add), rhs = Expression(50, Add)
+- expression 8 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
 - expression 9 operands: lhs = Counter(1), rhs = Counter(3)
 - expression 10 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 11 operands: lhs = Expression(47, Sub), rhs = Zero
-- expression 12 operands: lhs = Expression(48, Add), rhs = Counter(6)
-- expression 13 operands: lhs = Expression(49, Add), rhs = Expression(50, Add)
-- expression 14 operands: lhs = Counter(1), rhs = Counter(3)
-- expression 15 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 16 operands: lhs = Expression(47, Sub), rhs = Counter(4)
-- expression 17 operands: lhs = Expression(48, Add), rhs = Counter(6)
-- expression 18 operands: lhs = Expression(49, Add), rhs = Expression(50, Add)
-- expression 19 operands: lhs = Counter(1), rhs = Counter(3)
-- expression 20 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 21 operands: lhs = Expression(46, Sub), rhs = Counter(7)
-- expression 22 operands: lhs = Expression(47, Sub), rhs = Counter(4)
-- expression 23 operands: lhs = Expression(48, Add), rhs = Counter(6)
-- expression 24 operands: lhs = Expression(49, Add), rhs = Expression(50, Add)
-- expression 25 operands: lhs = Counter(1), rhs = Counter(3)
-- expression 26 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 27 operands: lhs = Zero, rhs = Expression(45, Sub)
-- expression 28 operands: lhs = Expression(46, Sub), rhs = Counter(7)
-- expression 29 operands: lhs = Expression(47, Sub), rhs = Counter(4)
-- expression 30 operands: lhs = Expression(48, Add), rhs = Counter(6)
-- expression 31 operands: lhs = Expression(49, Add), rhs = Expression(50, Add)
-- expression 32 operands: lhs = Counter(1), rhs = Counter(3)
-- expression 33 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 34 operands: lhs = Expression(44, Add), rhs = Counter(5)
-- expression 35 operands: lhs = Zero, rhs = Expression(45, Sub)
-- expression 36 operands: lhs = Expression(46, Sub), rhs = Counter(7)
-- expression 37 operands: lhs = Expression(47, Sub), rhs = Counter(4)
-- expression 38 operands: lhs = Expression(48, Add), rhs = Counter(6)
-- expression 39 operands: lhs = Expression(49, Add), rhs = Expression(50, Add)
-- expression 40 operands: lhs = Counter(1), rhs = Counter(3)
-- expression 41 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 42 operands: lhs = Expression(43, Sub), rhs = Expression(51, Add)
-- expression 43 operands: lhs = Expression(44, Add), rhs = Counter(5)
-- expression 44 operands: lhs = Zero, rhs = Expression(45, Sub)
-- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(7)
-- expression 46 operands: lhs = Expression(47, Sub), rhs = Counter(4)
-- expression 47 operands: lhs = Expression(48, Add), rhs = Counter(6)
-- expression 48 operands: lhs = Expression(49, Add), rhs = Expression(50, Add)
-- expression 49 operands: lhs = Counter(1), rhs = Counter(3)
-- expression 50 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 51 operands: lhs = Counter(6), rhs = Counter(9)
+- expression 11 operands: lhs = Expression(47, Add), rhs = Counter(6)
+- expression 12 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
+- expression 13 operands: lhs = Counter(1), rhs = Counter(3)
+- expression 14 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 15 operands: lhs = Expression(46, Sub), rhs = Counter(4)
+- expression 16 operands: lhs = Expression(47, Add), rhs = Counter(6)
+- expression 17 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
+- expression 18 operands: lhs = Counter(1), rhs = Counter(3)
+- expression 19 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 20 operands: lhs = Expression(45, Sub), rhs = Counter(7)
+- expression 21 operands: lhs = Expression(46, Sub), rhs = Counter(4)
+- expression 22 operands: lhs = Expression(47, Add), rhs = Counter(6)
+- expression 23 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
+- expression 24 operands: lhs = Counter(1), rhs = Counter(3)
+- expression 25 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 26 operands: lhs = Zero, rhs = Expression(44, Sub)
+- expression 27 operands: lhs = Expression(45, Sub), rhs = Counter(7)
+- expression 28 operands: lhs = Expression(46, Sub), rhs = Counter(4)
+- expression 29 operands: lhs = Expression(47, Add), rhs = Counter(6)
+- expression 30 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
+- expression 31 operands: lhs = Counter(1), rhs = Counter(3)
+- expression 32 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 33 operands: lhs = Expression(43, Add), rhs = Counter(5)
+- expression 34 operands: lhs = Zero, rhs = Expression(44, Sub)
+- expression 35 operands: lhs = Expression(45, Sub), rhs = Counter(7)
+- expression 36 operands: lhs = Expression(46, Sub), rhs = Counter(4)
+- expression 37 operands: lhs = Expression(47, Add), rhs = Counter(6)
+- expression 38 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
+- expression 39 operands: lhs = Counter(1), rhs = Counter(3)
+- expression 40 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 41 operands: lhs = Expression(42, Sub), rhs = Expression(50, Add)
+- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(5)
+- expression 43 operands: lhs = Zero, rhs = Expression(44, Sub)
+- expression 44 operands: lhs = Expression(45, Sub), rhs = Counter(7)
+- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(4)
+- expression 46 operands: lhs = Expression(47, Add), rhs = Counter(6)
+- expression 47 operands: lhs = Expression(48, Add), rhs = Expression(49, Add)
+- expression 48 operands: lhs = Counter(1), rhs = Counter(3)
+- expression 49 operands: lhs = Counter(4), rhs = Counter(5)
+- expression 50 operands: lhs = Counter(6), rhs = Counter(9)
 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)
@@ -154,25 +152,25 @@ Number of file 0 mappings: 20
 - Code(Expression(2, Add)) at (prev + 1, 13) to (start + 0, 30)
     = (Zero + ((c0 - c1) - c2))
 - Code(Counter(9)) at (prev + 0, 30) to (start + 0, 31)
-- Code(Expression(47, Sub)) at (prev + 2, 13) to (start + 0, 14)
+- Code(Expression(46, Sub)) at (prev + 2, 13) to (start + 0, 14)
     = (((c1 + c3) + (c4 + c5)) - c6)
-- Code(Expression(48, Add)) at (prev + 0, 18) to (start + 0, 23)
+- Code(Expression(47, Add)) at (prev + 0, 18) to (start + 0, 23)
     = ((c1 + c3) + (c4 + c5))
-- Code(Expression(11, Add)) at (prev + 1, 16) to (start + 0, 21)
-    = ((((c1 + c3) + (c4 + c5)) - c6) + Zero)
+- Code(Expression(46, Sub)) at (prev + 1, 16) to (start + 0, 21)
+    = (((c1 + c3) + (c4 + c5)) - c6)
 - Code(Zero) at (prev + 0, 22) to (start + 1, 14)
-- Code(Expression(46, Sub)) at (prev + 2, 20) to (start + 0, 25)
+- Code(Expression(45, Sub)) at (prev + 2, 20) to (start + 0, 25)
     = ((((c1 + c3) + (c4 + c5)) - c6) - c4)
 - Code(Zero) at (prev + 1, 27) to (start + 0, 31)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 34)
-- Code(Expression(45, Sub)) at (prev + 1, 18) to (start + 0, 19)
+- Code(Expression(44, Sub)) at (prev + 1, 18) to (start + 0, 19)
     = (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)
-- Code(Expression(44, Add)) at (prev + 1, 17) to (start + 0, 34)
+- Code(Expression(43, Add)) at (prev + 1, 17) to (start + 0, 34)
     = (Zero + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7))
-- Code(Expression(43, Sub)) at (prev + 0, 34) to (start + 0, 35)
+- Code(Expression(42, Sub)) at (prev + 0, 34) to (start + 0, 35)
     = ((Zero + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5)
 - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15)
-- Code(Expression(42, Add)) at (prev + 1, 5) to (start + 0, 6)
+- Code(Expression(41, Add)) at (prev + 1, 5) to (start + 0, 6)
     = (((Zero + (((((c1 + c3) + (c4 + c5)) - c6) - c4) - c7)) - c5) + (c6 + c9))
 
 Function name: loops_branches::main
diff --git a/tests/coverage-map/status-quo/no_cov_crate.cov-map b/tests/coverage-map/status-quo/no_cov_crate.cov-map
index 7ab5995dc28..05b6448bbd2 100644
--- a/tests/coverage-map/status-quo/no_cov_crate.cov-map
+++ b/tests/coverage-map/status-quo/no_cov_crate.cov-map
@@ -15,12 +15,12 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 24, 1) to (start + 2, 2)
 
 Function name: no_cov_crate::add_coverage_not_called (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 02, 02]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 1d, 01, 02, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2)
+- Code(Zero) at (prev + 29, 1) to (start + 2, 2)
 
 Function name: no_cov_crate::main
 Raw bytes (9): 0x[01, 01, 00, 01, 01, 4d, 01, 0b, 02]
diff --git a/tests/coverage-map/status-quo/partial_eq.cov-map b/tests/coverage-map/status-quo/partial_eq.cov-map
index dd61cd77ab6..3549116db7a 100644
--- a/tests/coverage-map/status-quo/partial_eq.cov-map
+++ b/tests/coverage-map/status-quo/partial_eq.cov-map
@@ -1,27 +1,27 @@
 Function name: <partial_eq::Version as core::clone::Clone>::clone (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 0a, 00, 0f]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 04, 0a, 00, 0f]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 4, 10) to (start + 0, 15)
+- Code(Zero) at (prev + 4, 10) to (start + 0, 15)
 
 Function name: <partial_eq::Version as core::cmp::Ord>::cmp (unused)
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 33, 00, 34, 00, 00, 35, 00, 36]
+Raw bytes (14): 0x[01, 01, 00, 02, 00, 04, 33, 00, 34, 00, 00, 35, 00, 36]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 4, 51) to (start + 0, 52)
+- Code(Zero) at (prev + 4, 51) to (start + 0, 52)
 - Code(Zero) at (prev + 0, 53) to (start + 0, 54)
 
 Function name: <partial_eq::Version as core::cmp::PartialEq>::eq (unused)
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 18, 00, 19, 00, 00, 20, 00, 21]
+Raw bytes (14): 0x[01, 01, 00, 02, 00, 04, 18, 00, 19, 00, 00, 20, 00, 21]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 4, 24) to (start + 0, 25)
+- Code(Zero) at (prev + 4, 24) to (start + 0, 25)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 33)
 
 Function name: <partial_eq::Version as core::cmp::PartialOrd>::partial_cmp
diff --git a/tests/coverage-map/status-quo/simple_loop.cov-map b/tests/coverage-map/status-quo/simple_loop.cov-map
index eb49c2324cc..f1691ffc5e6 100644
--- a/tests/coverage-map/status-quo/simple_loop.cov-map
+++ b/tests/coverage-map/status-quo/simple_loop.cov-map
@@ -1,28 +1,27 @@
 Function name: simple_loop::main
-Raw bytes (59): 0x[01, 01, 0a, 01, 05, 27, 09, 05, 02, 23, 09, 27, 09, 05, 02, 1e, 00, 23, 09, 27, 09, 05, 02, 07, 01, 03, 01, 09, 10, 05, 0a, 05, 05, 06, 02, 05, 06, 00, 07, 23, 05, 0d, 02, 0e, 1e, 04, 0d, 00, 12, 09, 02, 0a, 03, 0a, 1b, 06, 01, 00, 02]
+Raw bytes (57): 0x[01, 01, 09, 01, 05, 23, 09, 05, 02, 1f, 09, 23, 09, 05, 02, 1f, 09, 23, 09, 05, 02, 07, 01, 03, 01, 09, 10, 05, 0a, 05, 05, 06, 02, 05, 06, 00, 07, 1f, 05, 0d, 02, 0e, 1a, 04, 0d, 00, 12, 09, 02, 0a, 03, 0a, 1a, 06, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 10
+Number of expressions: 9
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Expression(9, Add), rhs = Counter(2)
+- expression 1 operands: lhs = Expression(8, Add), rhs = Counter(2)
 - expression 2 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 3 operands: lhs = Expression(8, Add), rhs = Counter(2)
-- expression 4 operands: lhs = Expression(9, Add), rhs = Counter(2)
+- expression 3 operands: lhs = Expression(7, Add), rhs = Counter(2)
+- expression 4 operands: lhs = Expression(8, Add), rhs = Counter(2)
 - expression 5 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 6 operands: lhs = Expression(7, Sub), rhs = Zero
+- expression 6 operands: lhs = Expression(7, Add), rhs = Counter(2)
 - expression 7 operands: lhs = Expression(8, Add), rhs = Counter(2)
-- expression 8 operands: lhs = Expression(9, Add), rhs = Counter(2)
-- expression 9 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 8 operands: lhs = Counter(1), rhs = Expression(0, Sub)
 Number of file 0 mappings: 7
 - Code(Counter(0)) at (prev + 3, 1) to (start + 9, 16)
 - Code(Counter(1)) at (prev + 10, 5) to (start + 5, 6)
 - Code(Expression(0, Sub)) at (prev + 5, 6) to (start + 0, 7)
     = (c0 - c1)
-- Code(Expression(8, Add)) at (prev + 5, 13) to (start + 2, 14)
+- Code(Expression(7, Add)) at (prev + 5, 13) to (start + 2, 14)
     = ((c1 + (c0 - c1)) + c2)
-- Code(Expression(7, Sub)) at (prev + 4, 13) to (start + 0, 18)
+- Code(Expression(6, Sub)) at (prev + 4, 13) to (start + 0, 18)
     = (((c1 + (c0 - c1)) + c2) - c2)
 - Code(Counter(2)) at (prev + 2, 10) to (start + 3, 10)
-- Code(Expression(6, Add)) at (prev + 6, 1) to (start + 0, 2)
-    = ((((c1 + (c0 - c1)) + c2) - c2) + Zero)
+- Code(Expression(6, Sub)) at (prev + 6, 1) to (start + 0, 2)
+    = (((c1 + (c0 - c1)) + c2) - c2)
 
diff --git a/tests/coverage-map/status-quo/simple_match.cov-map b/tests/coverage-map/status-quo/simple_match.cov-map
index d5389f04b26..4a32745d292 100644
--- a/tests/coverage-map/status-quo/simple_match.cov-map
+++ b/tests/coverage-map/status-quo/simple_match.cov-map
@@ -1,36 +1,33 @@
 Function name: simple_match::main
-Raw bytes (82): 0x[01, 01, 0e, 01, 05, 2f, 33, 05, 02, 09, 0d, 2b, 11, 2f, 33, 05, 02, 09, 0d, 26, 00, 2b, 11, 2f, 33, 05, 02, 09, 0d, 09, 00, 0a, 01, 03, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 2b, 05, 09, 00, 0d, 26, 05, 0d, 00, 16, 09, 02, 0d, 00, 0e, 23, 02, 11, 02, 12, 37, 04, 0d, 07, 0e, 0d, 0a, 0d, 00, 0f, 11, 03, 01, 00, 02]
+Raw bytes (78): 0x[01, 01, 0c, 01, 05, 2b, 2f, 05, 02, 09, 0d, 27, 11, 2b, 2f, 05, 02, 09, 0d, 27, 11, 2b, 2f, 05, 02, 09, 0d, 0a, 01, 03, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 27, 05, 09, 00, 0d, 22, 05, 0d, 00, 16, 09, 02, 0d, 00, 0e, 22, 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: 14
+Number of expressions: 12
 - expression 0 operands: lhs = Counter(0), rhs = Counter(1)
-- expression 1 operands: lhs = Expression(11, Add), rhs = Expression(12, Add)
+- expression 1 operands: lhs = Expression(10, Add), rhs = Expression(11, Add)
 - expression 2 operands: lhs = Counter(1), rhs = Expression(0, Sub)
 - expression 3 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 4 operands: lhs = Expression(10, Add), rhs = Counter(4)
-- expression 5 operands: lhs = Expression(11, Add), rhs = Expression(12, Add)
+- expression 4 operands: lhs = Expression(9, Add), rhs = Counter(4)
+- expression 5 operands: lhs = Expression(10, Add), rhs = Expression(11, Add)
 - expression 6 operands: lhs = Counter(1), rhs = Expression(0, Sub)
 - expression 7 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 8 operands: lhs = Expression(9, Sub), rhs = Zero
-- expression 9 operands: lhs = Expression(10, Add), rhs = Counter(4)
-- expression 10 operands: lhs = Expression(11, Add), rhs = Expression(12, Add)
-- expression 11 operands: lhs = Counter(1), rhs = Expression(0, Sub)
-- expression 12 operands: lhs = Counter(2), rhs = Counter(3)
-- expression 13 operands: lhs = Counter(2), rhs = Zero
+- expression 8 operands: lhs = Expression(9, Add), rhs = Counter(4)
+- expression 9 operands: lhs = Expression(10, Add), rhs = Expression(11, Add)
+- expression 10 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 11 operands: lhs = Counter(2), rhs = Counter(3)
 Number of file 0 mappings: 10
 - Code(Counter(0)) at (prev + 3, 1) to (start + 7, 15)
 - Code(Counter(1)) at (prev + 7, 16) to (start + 2, 6)
 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7)
     = (c0 - c1)
-- Code(Expression(10, Add)) at (prev + 5, 9) to (start + 0, 13)
+- Code(Expression(9, Add)) at (prev + 5, 9) to (start + 0, 13)
     = ((c1 + (c0 - c1)) + (c2 + c3))
-- Code(Expression(9, Sub)) at (prev + 5, 13) to (start + 0, 22)
+- Code(Expression(8, Sub)) at (prev + 5, 13) to (start + 0, 22)
     = (((c1 + (c0 - c1)) + (c2 + c3)) - c4)
 - Code(Counter(2)) at (prev + 2, 13) to (start + 0, 14)
-- Code(Expression(8, Add)) at (prev + 2, 17) to (start + 2, 18)
-    = ((((c1 + (c0 - c1)) + (c2 + c3)) - c4) + Zero)
-- Code(Expression(13, Add)) at (prev + 4, 13) to (start + 7, 14)
-    = (c2 + Zero)
+- Code(Expression(8, Sub)) at (prev + 2, 17) to (start + 2, 18)
+    = (((c1 + (c0 - c1)) + (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-map/status-quo/test_harness.cov-map b/tests/coverage-map/status-quo/test_harness.cov-map
index b0e955dd142..6940d2e2824 100644
--- a/tests/coverage-map/status-quo/test_harness.cov-map
+++ b/tests/coverage-map/status-quo/test_harness.cov-map
@@ -15,10 +15,10 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 9, 1) to (start + 0, 8)
 
 Function name: test_harness::unused (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 0f]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 07, 01, 00, 0f]
 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, 15)
+- Code(Zero) at (prev + 7, 1) to (start + 0, 15)
 
diff --git a/tests/coverage-map/status-quo/try_error_result.cov-map b/tests/coverage-map/status-quo/try_error_result.cov-map
index b52e78d1195..8367103a21a 100644
--- a/tests/coverage-map/status-quo/try_error_result.cov-map
+++ b/tests/coverage-map/status-quo/try_error_result.cov-map
@@ -91,136 +91,130 @@ Number of file 0 mappings: 11
     = ((c4 + (c5 + c6)) + c3)
 
 Function name: try_error_result::test2
-Raw bytes (373): 0x[01, 01, 41, 01, 07, 05, 09, 03, 0d, 41, 11, 52, 15, 41, 11, 4a, 1d, 4e, 19, 52, 15, 41, 11, 4e, 00, 52, 15, 41, 11, 4e, 19, 52, 15, 41, 11, 46, 00, 4a, 1d, 4e, 19, 52, 15, 41, 11, 6a, 25, 49, 21, 49, 21, 66, 00, 6a, 25, 49, 21, 9a, 01, 2d, 9e, 01, 29, a2, 01, 41, 03, 0d, a2, 01, 41, 03, 0d, 9e, 01, 29, a2, 01, 41, 03, 0d, 96, 01, 00, 9a, 01, 2d, 9e, 01, 29, a2, 01, 41, 03, 0d, ba, 01, 35, 45, 31, 45, 31, b6, 01, 00, ba, 01, 35, 45, 31, d2, 01, 3d, 4d, 39, 4d, 39, ce, 01, 00, d2, 01, 3d, 4d, 39, db, 01, 0d, 11, df, 01, e3, 01, f3, 01, 15, e7, 01, eb, 01, ef, 01, 19, 1d, 21, 25, f7, 01, fb, 01, 29, 2d, ff, 01, 83, 02, 31, 35, 39, 3d, 28, 01, 3c, 01, 03, 17, 03, 08, 09, 00, 0e, a2, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 52, 00, 31, 03, 35, 15, 04, 11, 00, 12, 4e, 02, 11, 04, 12, 46, 05, 11, 00, 14, 2b, 00, 17, 00, 41, 19, 00, 41, 00, 42, 4a, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 43, 01, 0d, 00, 20, 66, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 6a, 00, 43, 00, 60, 25, 00, 60, 00, 61, 63, 01, 0d, 00, 20, 96, 01, 04, 11, 00, 14, 9e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 9a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 93, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, ba, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, b3, 01, 01, 0d, 00, 20, ce, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, d2, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, cb, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, d7, 01, 01, 01, 00, 02]
+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, 11, c7, 01, cb, 01, db, 01, 15, cf, 01, d3, 01, d7, 01, 19, 1d, 21, 25, df, 01, e3, 01, 29, 2d, e7, 01, eb, 01, 31, 35, 39, 3d, 28, 01, 3c, 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]
 Number of files: 1
 - file 0 => global file 1
-Number of expressions: 65
+Number of expressions: 59
 - expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add)
 - expression 1 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3)
 - expression 3 operands: lhs = Counter(16), rhs = Counter(4)
-- expression 4 operands: lhs = Expression(20, Sub), rhs = Counter(5)
+- expression 4 operands: lhs = Expression(18, Sub), rhs = Counter(5)
 - expression 5 operands: lhs = Counter(16), rhs = Counter(4)
-- expression 6 operands: lhs = Expression(18, Sub), rhs = Counter(7)
-- expression 7 operands: lhs = Expression(19, Sub), rhs = Counter(6)
-- expression 8 operands: lhs = Expression(20, Sub), rhs = Counter(5)
+- 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(19, Sub), rhs = Zero
-- expression 11 operands: lhs = Expression(20, Sub), rhs = Counter(5)
-- expression 12 operands: lhs = Counter(16), rhs = Counter(4)
-- expression 13 operands: lhs = Expression(19, Sub), rhs = Counter(6)
-- expression 14 operands: lhs = Expression(20, Sub), rhs = Counter(5)
-- expression 15 operands: lhs = Counter(16), rhs = Counter(4)
-- expression 16 operands: lhs = Expression(17, Sub), rhs = Zero
-- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(7)
-- expression 18 operands: lhs = Expression(19, Sub), rhs = Counter(6)
-- expression 19 operands: lhs = Expression(20, Sub), rhs = Counter(5)
-- expression 20 operands: lhs = Counter(16), rhs = Counter(4)
-- expression 21 operands: lhs = Expression(26, Sub), rhs = Counter(9)
-- expression 22 operands: lhs = Counter(18), rhs = Counter(8)
+- 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(25, Sub), rhs = Zero
-- expression 25 operands: lhs = Expression(26, Sub), rhs = Counter(9)
-- expression 26 operands: lhs = Counter(18), rhs = Counter(8)
-- expression 27 operands: lhs = Expression(38, Sub), rhs = Counter(11)
-- expression 28 operands: lhs = Expression(39, Sub), rhs = Counter(10)
-- expression 29 operands: lhs = Expression(40, Sub), rhs = Counter(16)
-- expression 30 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 31 operands: lhs = Expression(40, Sub), rhs = Counter(16)
+- 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(39, Sub), rhs = Counter(10)
-- expression 34 operands: lhs = Expression(40, Sub), rhs = Counter(16)
-- expression 35 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 36 operands: lhs = Expression(37, Sub), rhs = Zero
-- expression 37 operands: lhs = Expression(38, Sub), rhs = Counter(11)
-- expression 38 operands: lhs = Expression(39, Sub), rhs = Counter(10)
-- expression 39 operands: lhs = Expression(40, Sub), rhs = Counter(16)
-- expression 40 operands: lhs = Expression(0, Add), rhs = Counter(3)
-- expression 41 operands: lhs = Expression(46, Sub), rhs = Counter(13)
-- expression 42 operands: lhs = Counter(17), rhs = Counter(12)
-- expression 43 operands: lhs = Counter(17), rhs = Counter(12)
-- expression 44 operands: lhs = Expression(45, Sub), rhs = Zero
-- expression 45 operands: lhs = Expression(46, Sub), rhs = Counter(13)
-- expression 46 operands: lhs = Counter(17), rhs = Counter(12)
-- expression 47 operands: lhs = Expression(52, Sub), rhs = Counter(15)
-- expression 48 operands: lhs = Counter(19), rhs = Counter(14)
-- expression 49 operands: lhs = Counter(19), rhs = Counter(14)
-- expression 50 operands: lhs = Expression(51, Sub), rhs = Zero
-- expression 51 operands: lhs = Expression(52, Sub), rhs = Counter(15)
-- expression 52 operands: lhs = Counter(19), rhs = Counter(14)
-- expression 53 operands: lhs = Expression(54, Add), rhs = Counter(3)
-- expression 54 operands: lhs = Counter(4), rhs = Expression(55, Add)
-- expression 55 operands: lhs = Expression(56, Add), rhs = Expression(60, Add)
-- expression 56 operands: lhs = Counter(5), rhs = Expression(57, Add)
-- expression 57 operands: lhs = Expression(58, Add), rhs = Expression(59, Add)
-- expression 58 operands: lhs = Counter(6), rhs = Counter(7)
-- expression 59 operands: lhs = Counter(8), rhs = Counter(9)
-- expression 60 operands: lhs = Expression(61, Add), rhs = Expression(62, Add)
-- expression 61 operands: lhs = Counter(10), rhs = Counter(11)
-- expression 62 operands: lhs = Expression(63, Add), rhs = Expression(64, Add)
-- expression 63 operands: lhs = Counter(12), rhs = Counter(13)
-- expression 64 operands: lhs = Counter(14), rhs = Counter(15)
+- 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 = Counter(4), rhs = Expression(49, Add)
+- expression 49 operands: lhs = Expression(50, Add), rhs = Expression(54, Add)
+- expression 50 operands: lhs = Counter(5), rhs = Expression(51, Add)
+- 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)
 Number of file 0 mappings: 40
 - Code(Counter(0)) at (prev + 60, 1) to (start + 3, 23)
 - Code(Expression(0, Add)) at (prev + 8, 9) to (start + 0, 14)
     = (c0 + (c1 + c2))
-- Code(Expression(40, Sub)) at (prev + 2, 9) to (start + 4, 26)
+- 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(20, Sub)) at (prev + 0, 49) to (start + 3, 53)
+- 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(19, Sub)) at (prev + 2, 17) to (start + 4, 18)
+- Code(Expression(17, Sub)) at (prev + 2, 17) to (start + 4, 18)
     = ((c16 - c4) - c5)
-- Code(Expression(17, Sub)) at (prev + 5, 17) to (start + 0, 20)
+- Code(Expression(15, Sub)) at (prev + 5, 17) to (start + 0, 20)
     = ((((c16 - c4) - c5) - c6) - c7)
-- Code(Expression(10, Add)) at (prev + 0, 23) to (start + 0, 65)
-    = (((c16 - c4) - c5) + Zero)
+- 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(18, Sub)) at (prev + 0, 67) to (start + 0, 95)
+- 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)
-- Code(Expression(16, Add)) at (prev + 1, 13) to (start + 0, 32)
-    = (((((c16 - c4) - c5) - c6) - c7) + Zero)
-- Code(Expression(25, Sub)) at (prev + 1, 17) to (start + 0, 20)
+- Code(Expression(15, Sub)) at (prev + 1, 13) to (start + 0, 32)
+    = ((((c16 - c4) - c5) - c6) - c7)
+- 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(26, Sub)) at (prev + 0, 67) to (start + 0, 96)
+- 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)
-- Code(Expression(24, Add)) at (prev + 1, 13) to (start + 0, 32)
-    = (((c18 - c8) - c9) + Zero)
-- Code(Expression(37, Sub)) at (prev + 4, 17) to (start + 0, 20)
+- Code(Expression(22, Sub)) at (prev + 1, 13) to (start + 0, 32)
+    = ((c18 - c8) - c9)
+- Code(Expression(33, Sub)) at (prev + 4, 17) to (start + 0, 20)
     = (((((c0 + (c1 + c2)) - c3) - c16) - c10) - c11)
-- Code(Expression(39, Sub)) at (prev + 0, 23) to (start + 0, 66)
+- 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(38, Sub)) at (prev + 0, 68) to (start + 0, 97)
+- 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)
-- Code(Expression(36, Add)) at (prev + 1, 13) to (start + 0, 32)
-    = ((((((c0 + (c1 + c2)) - c3) - c16) - c10) - c11) + Zero)
-- Code(Expression(45, Sub)) at (prev + 1, 17) to (start + 0, 20)
+- Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 32)
+    = (((((c0 + (c1 + c2)) - c3) - c16) - c10) - c11)
+- 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(46, Sub)) at (prev + 1, 18) to (start + 0, 47)
+- 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)
-- Code(Expression(44, Add)) at (prev + 1, 13) to (start + 0, 32)
-    = (((c17 - c12) - c13) + Zero)
-- Code(Expression(51, Sub)) at (prev + 1, 17) to (start + 0, 20)
+- Code(Expression(40, Sub)) at (prev + 1, 13) to (start + 0, 32)
+    = ((c17 - c12) - c13)
+- Code(Expression(45, Sub)) at (prev + 1, 17) to (start + 0, 20)
     = ((c19 - c14) - c15)
 - Code(Counter(19)) at (prev + 0, 23) to (start + 1, 54)
 - Code(Counter(14)) at (prev + 2, 17) to (start + 0, 18)
-- Code(Expression(52, Sub)) at (prev + 1, 18) to (start + 0, 47)
+- 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(Expression(50, Add)) at (prev + 2, 13) to (start + 0, 32)
-    = (((c19 - c14) - c15) + Zero)
+- Code(Expression(45, Sub)) at (prev + 2, 13) to (start + 0, 32)
+    = ((c19 - c14) - c15)
 - Code(Counter(3)) at (prev + 3, 5) to (start + 0, 11)
-- Code(Expression(53, Add)) at (prev + 1, 1) to (start + 0, 2)
+- 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)
 
diff --git a/tests/coverage-map/status-quo/unused.cov-map b/tests/coverage-map/status-quo/unused.cov-map
index c8b8f195fbd..9383d1e90ac 100644
--- a/tests/coverage-map/status-quo/unused.cov-map
+++ b/tests/coverage-map/status-quo/unused.cov-map
@@ -47,45 +47,45 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 37, 1) to (start + 4, 2)
 
 Function name: unused::unused_func (unused)
-Raw bytes (24): 0x[01, 01, 00, 04, 01, 13, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02]
+Raw bytes (24): 0x[01, 01, 00, 04, 00, 13, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 19, 1) to (start + 1, 14)
+- Code(Zero) at (prev + 19, 1) to (start + 1, 14)
 - Code(Zero) at (prev + 1, 15) to (start + 2, 6)
 - Code(Zero) at (prev + 2, 6) to (start + 0, 7)
 - Code(Zero) at (prev + 1, 1) to (start + 0, 2)
 
 Function name: unused::unused_func2 (unused)
-Raw bytes (24): 0x[01, 01, 00, 04, 01, 19, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02]
+Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 25, 1) to (start + 1, 14)
+- Code(Zero) at (prev + 25, 1) to (start + 1, 14)
 - Code(Zero) at (prev + 1, 15) to (start + 2, 6)
 - Code(Zero) at (prev + 2, 6) to (start + 0, 7)
 - Code(Zero) at (prev + 1, 1) to (start + 0, 2)
 
 Function name: unused::unused_func3 (unused)
-Raw bytes (24): 0x[01, 01, 00, 04, 01, 1f, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02]
+Raw bytes (24): 0x[01, 01, 00, 04, 00, 1f, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 4
-- Code(Counter(0)) at (prev + 31, 1) to (start + 1, 14)
+- Code(Zero) at (prev + 31, 1) to (start + 1, 14)
 - Code(Zero) at (prev + 1, 15) to (start + 2, 6)
 - Code(Zero) at (prev + 2, 6) to (start + 0, 7)
 - Code(Zero) at (prev + 1, 1) to (start + 0, 2)
 
 Function name: unused::unused_template_func::<_> (unused)
-Raw bytes (34): 0x[01, 01, 00, 06, 01, 0b, 01, 01, 12, 00, 02, 0b, 00, 11, 00, 01, 09, 00, 0f, 00, 00, 13, 00, 19, 00, 01, 09, 00, 0f, 00, 02, 01, 00, 02]
+Raw bytes (34): 0x[01, 01, 00, 06, 00, 0b, 01, 01, 12, 00, 02, 0b, 00, 11, 00, 01, 09, 00, 0f, 00, 00, 13, 00, 19, 00, 01, 09, 00, 0f, 00, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 11, 1) to (start + 1, 18)
+- Code(Zero) at (prev + 11, 1) to (start + 1, 18)
 - Code(Zero) at (prev + 2, 11) to (start + 0, 17)
 - Code(Zero) at (prev + 1, 9) to (start + 0, 15)
 - Code(Zero) at (prev + 0, 19) to (start + 0, 25)
diff --git a/tests/coverage-map/status-quo/yield.cov-map b/tests/coverage-map/status-quo/yield.cov-map
index 16caa2db343..c9c9709fa4f 100644
--- a/tests/coverage-map/status-quo/yield.cov-map
+++ b/tests/coverage-map/status-quo/yield.cov-map
@@ -1,54 +1,44 @@
 Function name: yield::main
-Raw bytes (118): 0x[01, 01, 11, 01, 00, 05, 09, 0d, 00, 0d, 11, 32, 15, 0d, 11, 11, 15, 2e, 00, 32, 15, 0d, 11, 2e, 00, 32, 15, 0d, 11, 19, 1d, 21, 00, 25, 29, 2d, 00, 10, 01, 07, 01, 01, 16, 03, 06, 0b, 00, 2e, 0d, 01, 27, 00, 29, 07, 01, 0e, 00, 34, 0b, 02, 0b, 00, 2e, 32, 01, 22, 00, 27, 2e, 00, 2c, 00, 2e, 1b, 01, 0e, 00, 34, 1f, 03, 09, 00, 16, 2b, 07, 0b, 00, 2e, 21, 01, 27, 00, 29, 37, 01, 0e, 00, 34, 3b, 02, 0b, 00, 2e, 2d, 01, 27, 00, 29, 3f, 01, 0e, 00, 34, 43, 02, 01, 00, 02]
+Raw bytes (106): 0x[01, 01, 0b, 05, 09, 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, 06, 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, 07, 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: 17
-- expression 0 operands: lhs = Counter(0), rhs = Zero
-- expression 1 operands: lhs = Counter(1), rhs = Counter(2)
-- expression 2 operands: lhs = Counter(3), rhs = Zero
+Number of expressions: 11
+- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
+- 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 4 operands: lhs = Expression(12, Sub), rhs = Counter(5)
-- expression 5 operands: lhs = Counter(3), rhs = Counter(4)
-- expression 6 operands: lhs = Counter(4), rhs = Counter(5)
-- expression 7 operands: lhs = Expression(11, Sub), rhs = Zero
-- expression 8 operands: lhs = Expression(12, Sub), rhs = Counter(5)
-- expression 9 operands: lhs = Counter(3), rhs = Counter(4)
-- expression 10 operands: lhs = Expression(11, Sub), rhs = Zero
-- expression 11 operands: lhs = Expression(12, Sub), rhs = Counter(5)
-- expression 12 operands: lhs = Counter(3), rhs = Counter(4)
-- expression 13 operands: lhs = Counter(6), rhs = Counter(7)
-- expression 14 operands: lhs = Counter(8), rhs = Zero
-- expression 15 operands: lhs = Counter(9), rhs = Counter(10)
-- expression 16 operands: lhs = Counter(11), rhs = Zero
+- 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 9 operands: lhs = Counter(6), rhs = Counter(7)
+- expression 10 operands: lhs = Counter(9), rhs = Counter(10)
 Number of file 0 mappings: 16
 - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 22)
-- Code(Expression(0, Add)) at (prev + 6, 11) to (start + 0, 46)
-    = (c0 + Zero)
+- Code(Counter(0)) at (prev + 6, 11) to (start + 0, 46)
 - Code(Counter(3)) at (prev + 1, 39) to (start + 0, 41)
-- Code(Expression(1, Add)) at (prev + 1, 14) to (start + 0, 52)
+- Code(Expression(0, Add)) at (prev + 1, 14) to (start + 0, 52)
     = (c1 + c2)
-- Code(Expression(2, Add)) at (prev + 2, 11) to (start + 0, 46)
-    = (c3 + Zero)
-- Code(Expression(12, Sub)) at (prev + 1, 34) to (start + 0, 39)
+- Code(Counter(3)) at (prev + 2, 11) to (start + 0, 46)
+- Code(Expression(8, Sub)) at (prev + 1, 34) to (start + 0, 39)
     = (c3 - c4)
-- Code(Expression(11, Sub)) at (prev + 0, 44) to (start + 0, 46)
+- Code(Expression(7, Sub)) at (prev + 0, 44) to (start + 0, 46)
     = ((c3 - c4) - c5)
-- Code(Expression(6, Add)) at (prev + 1, 14) to (start + 0, 52)
+- Code(Expression(4, Add)) at (prev + 1, 14) to (start + 0, 52)
     = (c4 + c5)
-- Code(Expression(7, Add)) at (prev + 3, 9) to (start + 0, 22)
-    = (((c3 - c4) - c5) + Zero)
-- Code(Expression(10, Add)) at (prev + 7, 11) to (start + 0, 46)
-    = (((c3 - c4) - c5) + Zero)
+- Code(Expression(7, Sub)) at (prev + 3, 9) to (start + 0, 22)
+    = ((c3 - c4) - c5)
+- Code(Expression(7, Sub)) at (prev + 7, 11) to (start + 0, 46)
+    = ((c3 - c4) - c5)
 - Code(Counter(8)) at (prev + 1, 39) to (start + 0, 41)
-- Code(Expression(13, Add)) at (prev + 1, 14) to (start + 0, 52)
+- Code(Expression(9, Add)) at (prev + 1, 14) to (start + 0, 52)
     = (c6 + c7)
-- Code(Expression(14, Add)) at (prev + 2, 11) to (start + 0, 46)
-    = (c8 + Zero)
+- Code(Counter(8)) at (prev + 2, 11) to (start + 0, 46)
 - Code(Counter(11)) at (prev + 1, 39) to (start + 0, 41)
-- Code(Expression(15, Add)) at (prev + 1, 14) to (start + 0, 52)
+- Code(Expression(10, Add)) at (prev + 1, 14) to (start + 0, 52)
     = (c9 + c10)
-- Code(Expression(16, Add)) at (prev + 2, 1) to (start + 0, 2)
-    = (c11 + Zero)
+- Code(Counter(11)) at (prev + 2, 1) to (start + 0, 2)
 
 Function name: yield::main::{closure#0}
 Raw bytes (14): 0x[01, 01, 00, 02, 01, 08, 1c, 01, 10, 05, 02, 10, 01, 06]
diff --git a/tests/coverage-map/unreachable.cov-map b/tests/coverage-map/unreachable.cov-map
new file mode 100644
index 00000000000..495419820c1
--- /dev/null
+++ b/tests/coverage-map/unreachable.cov-map
@@ -0,0 +1,24 @@
+Function name: unreachable::UNREACHABLE_CLOSURE::{closure#0}
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 27, 00, 49]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 15, 39) to (start + 0, 73)
+
+Function name: unreachable::unreachable_function
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 02, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 17, 1) to (start + 2, 2)
+
+Function name: unreachable::unreachable_intrinsic
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 01, 02, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 22, 1) to (start + 2, 2)
+
diff --git a/tests/coverage-map/unreachable.rs b/tests/coverage-map/unreachable.rs
new file mode 100644
index 00000000000..6385bfa160d
--- /dev/null
+++ b/tests/coverage-map/unreachable.rs
@@ -0,0 +1,37 @@
+#![feature(core_intrinsics)]
+#![feature(coverage_attribute)]
+// compile-flags: --edition=2021
+
+// <https://github.com/rust-lang/rust/issues/116171>
+// If we instrument a function for coverage, but all of its counter-increment
+// statements are removed by MIR optimizations, LLVM will think it isn't
+// instrumented and it will disappear from coverage maps and coverage reports.
+// Most MIR opts won't cause this because they tend not to remove statements
+// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends
+// with `TerminatorKind::Unreachable`.
+
+use std::hint::{black_box, unreachable_unchecked};
+
+static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() };
+
+fn unreachable_function() {
+    unsafe { unreachable_unchecked() }
+}
+
+// Use an intrinsic to more reliably trigger unreachable-propagation.
+fn unreachable_intrinsic() {
+    unsafe { std::intrinsics::unreachable() }
+}
+
+#[coverage(off)]
+fn main() {
+    if black_box(false) {
+        UNREACHABLE_CLOSURE();
+    }
+    if black_box(false) {
+        unreachable_function();
+    }
+    if black_box(false) {
+        unreachable_intrinsic();
+    }
+}
diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff
index 7ba51ccdbf6..d585ae89e82 100644
--- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff
+++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-abort.diff
@@ -20,6 +20,7 @@
           _2 = const u8::MAX;
           StorageLive(_3);
           _3 = const 1_u8;
+          StorageLive(_4);
 -         _4 = CheckedAdd(_2, _3);
 -         assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable];
 +         _4 = const (0_u8, true);
@@ -29,6 +30,7 @@
       bb1: {
 -         _1 = move (_4.0: u8);
 +         _1 = const 0_u8;
+          StorageDead(_4);
           StorageDead(_3);
           StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff
index 545b7f22f6e..9fe39090638 100644
--- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.panic-unwind.diff
@@ -20,6 +20,7 @@
           _2 = const u8::MAX;
           StorageLive(_3);
           _3 = const 1_u8;
+          StorageLive(_4);
 -         _4 = CheckedAdd(_2, _3);
 -         assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue];
 +         _4 = const (0_u8, true);
@@ -29,6 +30,7 @@
       bb1: {
 -         _1 = move (_4.0: u8);
 +         _1 = const 0_u8;
+          StorageDead(_4);
           StorageDead(_3);
           StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff
index 9a68d3b51b5..87bb1454c96 100644
--- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff
@@ -20,6 +20,7 @@
           _2 = const u8::MAX;
           StorageLive(_3);
           _3 = const 1_u8;
+          StorageLive(_4);
 -         _4 = CheckedAdd(_2, _3);
 -         assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable];
 +         _4 = CheckedAdd(const u8::MAX, const 1_u8);
@@ -29,6 +30,7 @@
       bb1: {
 -         _1 = move (_4.0: u8);
 +         _1 = const 0_u8;
+          StorageDead(_4);
           StorageDead(_3);
           StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff
index c1d281ab788..b2f13640a4c 100644
--- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff
@@ -20,6 +20,7 @@
           _2 = const u8::MAX;
           StorageLive(_3);
           _3 = const 1_u8;
+          StorageLive(_4);
 -         _4 = CheckedAdd(_2, _3);
 -         assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue];
 +         _4 = CheckedAdd(const u8::MAX, const 1_u8);
@@ -29,6 +30,7 @@
       bb1: {
 -         _1 = move (_4.0: u8);
 +         _1 = const 0_u8;
+          StorageDead(_4);
           StorageDead(_3);
           StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
index 721fac27d88..10b81e59b5f 100644
--- a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
@@ -41,6 +41,8 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
         _7 = (move _8,);
         StorageLive(_9);
         _9 = move (_7.0: i32);
+        StorageLive(_10);
+        StorageLive(_12);
         StorageLive(_11);
         _10 = ((*_6).0: &i32);
         _11 = (*_10);
@@ -50,6 +52,8 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
         _0 = (move _11, move _13);
         StorageDead(_13);
         StorageDead(_11);
+        StorageDead(_12);
+        StorageDead(_10);
         StorageDead(_9);
         StorageDead(_8);
         StorageDead(_7);
diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff
index 6779003b693..06ee8c464d5 100644
--- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff
@@ -40,6 +40,8 @@
 +         StorageDead(_3);
 +         StorageLive(_5);
 +         _5 = const false;
++         StorageLive(_6);
++         StorageLive(_7);
 +         _6 = (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8});
 +         _7 = discriminant((*_6));
 +         switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9];
@@ -48,6 +50,8 @@
       bb1: {
 -         _3 = &mut _4;
 -         _2 = Pin::<&mut {generator@$DIR/inline_generator.rs:16:5: 16:8}>::new(move _3) -> [return: bb2, unwind unreachable];
++         StorageDead(_7);
++         StorageDead(_6);
 +         StorageDead(_5);
 +         StorageDead(_2);
 +         drop(_4) -> [return: bb2, unwind unreachable];
diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff
index 31744be99ec..da29ba5f50d 100644
--- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff
@@ -48,6 +48,8 @@
 -         _1 = <{generator@$DIR/inline_generator.rs:16:5: 16:8} as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb5];
 +         StorageLive(_5);
 +         _5 = const false;
++         StorageLive(_6);
++         StorageLive(_7);
 +         _6 = (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8});
 +         _7 = discriminant((*_6));
 +         switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11];
@@ -55,6 +57,8 @@
   
 -     bb3: {
 +     bb1: {
++         StorageDead(_7);
++         StorageDead(_6);
 +         StorageDead(_5);
           StorageDead(_2);
 -         drop(_4) -> [return: bb4, unwind: bb6];
diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff
index dc0ab255afd..b90e0505c54 100644
--- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff
@@ -122,9 +122,14 @@
 +         _3 = const _;
 +         _2 = Vec::<u32> { buf: move _3, len: const 0_usize };
 +         StorageDead(_3);
++         StorageLive(_4);
++         StorageLive(_5);
++         StorageLive(_6);
++         StorageLive(_7);
 +         _4 = SizeOf(std::vec::Vec<u32>);
 +         _5 = AlignOf(std::vec::Vec<u32>);
 +         StorageLive(_8);
++         StorageLive(_10);
 +         StorageLive(_11);
 +         StorageLive(_12);
 +         StorageLive(_13);
@@ -178,10 +183,15 @@
 +         StorageDead(_13);
 +         StorageDead(_12);
 +         StorageDead(_11);
++         StorageDead(_10);
 +         StorageDead(_8);
 +         _1 = ShallowInitBox(move _6, std::vec::Vec<u32>);
 +         _7 = (((_1.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>);
 +         (*_7) = move _2;
++         StorageDead(_7);
++         StorageDead(_6);
++         StorageDead(_5);
++         StorageDead(_4);
           StorageDead(_2);
           _0 = const ();
 -         drop(_1) -> [return: bb3, unwind unreachable];
diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff
index 675292f06d6..f9c637caa18 100644
--- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff
@@ -122,9 +122,14 @@
 +         _3 = const _;
 +         _2 = Vec::<u32> { buf: move _3, len: const 0_usize };
 +         StorageDead(_3);
++         StorageLive(_4);
++         StorageLive(_5);
++         StorageLive(_6);
++         StorageLive(_7);
 +         _4 = SizeOf(std::vec::Vec<u32>);
 +         _5 = AlignOf(std::vec::Vec<u32>);
 +         StorageLive(_8);
++         StorageLive(_10);
 +         StorageLive(_11);
 +         StorageLive(_12);
 +         StorageLive(_13);
@@ -195,10 +200,15 @@
 +         StorageDead(_13);
 +         StorageDead(_12);
 +         StorageDead(_11);
++         StorageDead(_10);
 +         StorageDead(_8);
 +         _1 = ShallowInitBox(move _6, std::vec::Vec<u32>);
 +         _7 = (((_1.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>);
 +         (*_7) = move _2;
++         StorageDead(_7);
++         StorageDead(_6);
++         StorageDead(_5);
++         StorageDead(_4);
 +         StorageDead(_2);
 +         _0 = const ();
 +         drop(_1) -> [return: bb1, unwind: bb2];
diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff
index 3d0c1072527..688ab9c563a 100644
--- a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff
@@ -18,6 +18,7 @@
       bb0: {
 -         _0 = inner() -> [return: bb1, unwind unreachable];
 +         StorageLive(_1);
++         StorageLive(_2);
 +         _1 = const _;
 +         _0 = index() -> [return: bb1, unwind unreachable];
       }
@@ -40,6 +41,7 @@
 + 
 +     bb4: {
 +         StorageDead(_3);
++         StorageDead(_2);
 +         StorageDead(_1);
           return;
       }
diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff
index 16a19f4a356..e4d2b1a7ffb 100644
--- a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff
@@ -18,6 +18,7 @@
       bb0: {
 -         _0 = inner() -> [return: bb1, unwind continue];
 +         StorageLive(_1);
++         StorageLive(_2);
 +         _1 = const _;
 +         _0 = index() -> [return: bb1, unwind continue];
       }
@@ -40,6 +41,7 @@
 + 
 +     bb4: {
 +         StorageDead(_3);
++         StorageDead(_2);
 +         StorageDead(_1);
           return;
       }
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
index 6837da27a96..62d7e839f5a 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
@@ -17,9 +17,13 @@ fn b(_1: &mut Box<T>) -> &mut T {
         StorageLive(_3);
         StorageLive(_4);
         _4 = &mut (*_1);
+        StorageLive(_5);
+        StorageLive(_6);
         _5 = deref_copy (*_4);
         _6 = (((_5.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T);
         _3 = &mut (*_6);
+        StorageDead(_6);
+        StorageDead(_5);
         _2 = &mut (*_3);
         StorageDead(_4);
         _0 = &mut (*_2);
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
index d09bfc33ff1..bc0aa06a752 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
@@ -15,9 +15,13 @@ fn d(_1: &Box<T>) -> &T {
         StorageLive(_2);
         StorageLive(_3);
         _3 = &(*_1);
+        StorageLive(_4);
+        StorageLive(_5);
         _4 = deref_copy (*_3);
         _5 = (((_4.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T);
         _2 = &(*_5);
+        StorageDead(_5);
+        StorageDead(_4);
         _0 = &(*_2);
         StorageDead(_3);
         StorageDead(_2);
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
index e3c57347392..018b6c1ee95 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
@@ -30,6 +30,7 @@
           _2 = move _1;
 -         _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable];
 +         StorageLive(_3);
++         StorageLive(_4);
 +         _4 = discriminant(_2);
 +         switchInt(move _4) -> [1: bb2, otherwise: bb1];
       }
@@ -40,6 +41,7 @@
 + 
 +     bb2: {
 +         _0 = move ((_2 as Some).0: T);
++         StorageDead(_4);
 +         StorageDead(_3);
           StorageDead(_2);
           return;
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
index fc638cb3ace..47845758a3f 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
@@ -30,6 +30,7 @@
           _2 = move _1;
 -         _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2];
 +         StorageLive(_3);
++         StorageLive(_4);
 +         _4 = discriminant(_2);
 +         switchInt(move _4) -> [1: bb2, otherwise: bb1];
       }
@@ -44,6 +45,7 @@
 -         resume;
 +     bb2: {
 +         _0 = move ((_2 as Some).0: T);
++         StorageDead(_4);
 +         StorageDead(_3);
 +         StorageDead(_2);
 +         return;
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
index fcc4d43ced6..392f085bd4d 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
@@ -25,12 +25,14 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
 
     bb0: {
         StorageLive(_3);
+        StorageLive(_2);
         _2 = discriminant(_1);
         switchInt(move _2) -> [1: bb1, otherwise: bb2];
     }
 
     bb1: {
         _0 = move ((_1 as Some).0: T);
+        StorageDead(_2);
         StorageDead(_3);
         return;
     }
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
index fcc4d43ced6..392f085bd4d 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
@@ -25,12 +25,14 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
 
     bb0: {
         StorageLive(_3);
+        StorageLive(_2);
         _2 = discriminant(_1);
         switchInt(move _2) -> [1: bb1, otherwise: bb2];
     }
 
     bb1: {
         _0 = move ((_1 as Some).0: T);
+        StorageDead(_2);
         StorageDead(_3);
         return;
     }
diff --git a/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff
index afcfde09c02..28a7ffda371 100644
--- a/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff
+++ b/tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff
@@ -5,7 +5,7 @@
       let mut _0: bool;
   
       bb0: {
-+         Coverage::Counter(0) for /the/src/instrument_coverage.rs:20:1 - 22:2;
++         Coverage::Counter(0) for [/the/src/instrument_coverage.rs:20:1 - 22:2];
           _0 = const true;
           return;
       }
diff --git a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
index e17c6ddc56e..9a8caa26307 100644
--- a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
@@ -8,12 +8,12 @@
       let mut _3: !;
   
       bb0: {
-+         Coverage::Counter(0) for /the/src/instrument_coverage.rs:11:1 - 11:11;
++         Coverage::Counter(0) for [/the/src/instrument_coverage.rs:11:1 - 11:11];
           goto -> bb1;
       }
   
       bb1: {
-+         Coverage::Expression(0) = Counter(0) + Counter(1) for /the/src/instrument_coverage.rs:12:5 - 13:17;
++         Coverage::Expression(0) = Counter(0) + Counter(1) for [/the/src/instrument_coverage.rs:12:5 - 13:17];
           falseUnwind -> [real: bb2, unwind: bb6];
       }
   
@@ -27,15 +27,14 @@
       }
   
       bb4: {
-+         Coverage::Expression(2) = Expression(1) + Zero for /the/src/instrument_coverage.rs:17:1 - 17:2;
-+         Coverage::Expression(1) = Expression(0) - Counter(1) for /the/src/instrument_coverage.rs:14:13 - 14:18;
++         Coverage::Expression(1) = Expression(0) - Counter(1) for [/the/src/instrument_coverage.rs:14:13 - 14:18, /the/src/instrument_coverage.rs:17:1 - 17:2];
           _0 = const ();
           StorageDead(_2);
           return;
       }
   
       bb5: {
-+         Coverage::Counter(1) for /the/src/instrument_coverage.rs:15:10 - 15:11;
++         Coverage::Counter(1) for [/the/src/instrument_coverage.rs:15:10 - 15:11];
           _1 = const ();
           StorageDead(_2);
           goto -> bb1;
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
index f8c85941813..55ccf6a8b45 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
@@ -30,6 +30,7 @@ fn num_to_digit(_1: char) -> u32 {
     }
 
     bb1: {
+        StorageLive(_3);
         _3 = discriminant(_2);
         StorageDead(_7);
         StorageDead(_2);
@@ -37,11 +38,13 @@ fn num_to_digit(_1: char) -> u32 {
     }
 
     bb2: {
+        StorageDead(_3);
         StorageLive(_4);
         _4 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind unreachable];
     }
 
     bb3: {
+        StorageLive(_5);
         _5 = discriminant(_4);
         switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb6];
     }
@@ -52,6 +55,7 @@ fn num_to_digit(_1: char) -> u32 {
 
     bb5: {
         _0 = move ((_4 as Some).0: u32);
+        StorageDead(_5);
         StorageDead(_4);
         goto -> bb8;
     }
@@ -61,6 +65,7 @@ fn num_to_digit(_1: char) -> u32 {
     }
 
     bb7: {
+        StorageDead(_3);
         _0 = const 0_u32;
         goto -> bb8;
     }
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
index df7392edc50..cb70a83e7f8 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
@@ -30,6 +30,7 @@ fn num_to_digit(_1: char) -> u32 {
     }
 
     bb1: {
+        StorageLive(_3);
         _3 = discriminant(_2);
         StorageDead(_7);
         StorageDead(_2);
@@ -37,11 +38,13 @@ fn num_to_digit(_1: char) -> u32 {
     }
 
     bb2: {
+        StorageDead(_3);
         StorageLive(_4);
         _4 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind continue];
     }
 
     bb3: {
+        StorageLive(_5);
         _5 = discriminant(_4);
         switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb6];
     }
@@ -52,6 +55,7 @@ fn num_to_digit(_1: char) -> u32 {
 
     bb5: {
         _0 = move ((_4 as Some).0: u32);
+        StorageDead(_5);
         StorageDead(_4);
         goto -> bb8;
     }
@@ -61,6 +65,7 @@ fn num_to_digit(_1: char) -> u32 {
     }
 
     bb7: {
+        StorageDead(_3);
         _0 = const 0_u32;
         goto -> bb8;
     }
diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir
index 75f81c5aaca..e3c81061a46 100644
--- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir
@@ -36,8 +36,10 @@ fn step_forward(_1: u32, _2: usize) -> u32 {
 
     bb1: {
         StorageLive(_5);
+        StorageLive(_4);
         _4 = discriminant(_3);
         _5 = Eq(_4, const 1_isize);
+        StorageDead(_4);
         _6 = Not(move _5);
         StorageDead(_5);
         switchInt(move _6) -> [0: bb2, otherwise: bb3];
diff --git a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
index 48b780aea62..80a470c9482 100644
--- a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
@@ -18,6 +18,7 @@ fn ezmap(_1: Option<i32>) -> Option<i32> {
     }
 
     bb0: {
+        StorageLive(_2);
         _2 = discriminant(_1);
         switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4];
     }
@@ -37,6 +38,7 @@ fn ezmap(_1: Option<i32>) -> Option<i32> {
     }
 
     bb3: {
+        StorageDead(_2);
         return;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
index ed286beb4ca..9c10e96b0ea 100644
--- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
@@ -98,6 +98,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
         StorageLive(_35);
         StorageLive(_11);
         _11 = _8;
+        StorageLive(_12);
+        StorageLive(_13);
         _12 = deref_copy _4;
         _13 = deref_copy _11;
         StorageLive(_14);
@@ -107,6 +109,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
         _16 = Le(move _14, move _15);
         StorageDead(_15);
         StorageDead(_14);
+        StorageDead(_13);
+        StorageDead(_12);
         switchInt(move _16) -> [0: bb1, otherwise: bb2];
     }
 
@@ -126,6 +130,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
         StorageLive(_37);
         StorageLive(_17);
         _17 = _6;
+        StorageLive(_18);
+        StorageLive(_19);
         _18 = deref_copy _10;
         _19 = deref_copy _17;
         StorageLive(_20);
@@ -135,6 +141,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
         _22 = Le(move _20, move _21);
         StorageDead(_21);
         StorageDead(_20);
+        StorageDead(_19);
+        StorageDead(_18);
         switchInt(move _22) -> [0: bb3, otherwise: bb8];
     }
 
@@ -151,6 +159,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
         StorageLive(_39);
         StorageLive(_23);
         _23 = _4;
+        StorageLive(_24);
+        StorageLive(_25);
         _24 = deref_copy _8;
         _25 = deref_copy _23;
         StorageLive(_26);
@@ -160,6 +170,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
         _28 = Le(move _26, move _27);
         StorageDead(_27);
         StorageDead(_26);
+        StorageDead(_25);
+        StorageDead(_24);
         switchInt(move _28) -> [0: bb5, otherwise: bb6];
     }
 
@@ -179,6 +191,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
         StorageLive(_41);
         StorageLive(_29);
         _29 = _10;
+        StorageLive(_30);
+        StorageLive(_31);
         _30 = deref_copy _6;
         _31 = deref_copy _29;
         StorageLive(_32);
@@ -188,6 +202,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
         _0 = Le(move _32, move _33);
         StorageDead(_33);
         StorageDead(_32);
+        StorageDead(_31);
+        StorageDead(_30);
         StorageDead(_29);
         StorageDead(_41);
         StorageDead(_40);
diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
index ca1528b6ab1..491db551a7d 100644
--- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
+++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
@@ -48,6 +48,7 @@
   
       bb0: {
           StorageLive(_3);
+          StorageLive(_9);
           StorageLive(_10);
           StorageLive(_11);
           _9 = discriminant(_1);
@@ -57,6 +58,7 @@
       bb1: {
           StorageDead(_11);
           StorageDead(_10);
+          StorageDead(_9);
           _5 = discriminant(_3);
           switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3];
       }
diff --git a/tests/run-coverage/unreachable.coverage b/tests/run-coverage/unreachable.coverage
new file mode 100644
index 00000000000..fa0ac9ccfa1
--- /dev/null
+++ b/tests/run-coverage/unreachable.coverage
@@ -0,0 +1,38 @@
+   LL|       |#![feature(core_intrinsics)]
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |// compile-flags: --edition=2021
+   LL|       |
+   LL|       |// <https://github.com/rust-lang/rust/issues/116171>
+   LL|       |// If we instrument a function for coverage, but all of its counter-increment
+   LL|       |// statements are removed by MIR optimizations, LLVM will think it isn't
+   LL|       |// instrumented and it will disappear from coverage maps and coverage reports.
+   LL|       |// Most MIR opts won't cause this because they tend not to remove statements
+   LL|       |// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends
+   LL|       |// with `TerminatorKind::Unreachable`.
+   LL|       |
+   LL|       |use std::hint::{black_box, unreachable_unchecked};
+   LL|       |
+   LL|      0|static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() };
+   LL|       |
+   LL|      0|fn unreachable_function() {
+   LL|      0|    unsafe { unreachable_unchecked() }
+   LL|      0|}
+   LL|       |
+   LL|       |// Use an intrinsic to more reliably trigger unreachable-propagation.
+   LL|      0|fn unreachable_intrinsic() {
+   LL|      0|    unsafe { std::intrinsics::unreachable() }
+   LL|      0|}
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |fn main() {
+   LL|       |    if black_box(false) {
+   LL|       |        UNREACHABLE_CLOSURE();
+   LL|       |    }
+   LL|       |    if black_box(false) {
+   LL|       |        unreachable_function();
+   LL|       |    }
+   LL|       |    if black_box(false) {
+   LL|       |        unreachable_intrinsic();
+   LL|       |    }
+   LL|       |}
+
diff --git a/tests/run-coverage/unreachable.rs b/tests/run-coverage/unreachable.rs
new file mode 100644
index 00000000000..6385bfa160d
--- /dev/null
+++ b/tests/run-coverage/unreachable.rs
@@ -0,0 +1,37 @@
+#![feature(core_intrinsics)]
+#![feature(coverage_attribute)]
+// compile-flags: --edition=2021
+
+// <https://github.com/rust-lang/rust/issues/116171>
+// If we instrument a function for coverage, but all of its counter-increment
+// statements are removed by MIR optimizations, LLVM will think it isn't
+// instrumented and it will disappear from coverage maps and coverage reports.
+// Most MIR opts won't cause this because they tend not to remove statements
+// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends
+// with `TerminatorKind::Unreachable`.
+
+use std::hint::{black_box, unreachable_unchecked};
+
+static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() };
+
+fn unreachable_function() {
+    unsafe { unreachable_unchecked() }
+}
+
+// Use an intrinsic to more reliably trigger unreachable-propagation.
+fn unreachable_intrinsic() {
+    unsafe { std::intrinsics::unreachable() }
+}
+
+#[coverage(off)]
+fn main() {
+    if black_box(false) {
+        UNREACHABLE_CLOSURE();
+    }
+    if black_box(false) {
+        unreachable_function();
+    }
+    if black_box(false) {
+        unreachable_intrinsic();
+    }
+}
diff --git a/tests/rustdoc-js/impl-trait.js b/tests/rustdoc-js/impl-trait.js
index 710e594b547..00d67d639bd 100644
--- a/tests/rustdoc-js/impl-trait.js
+++ b/tests/rustdoc-js/impl-trait.js
@@ -1,3 +1,4 @@
+// exact-check
 // ignore-order
 
 const EXPECTED = [
@@ -20,9 +21,16 @@ const EXPECTED = [
     {
         'query': '-> Aaaaaaa',
         'others': [
-            { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
-            { 'path': 'impl_trait::Ccccccc', 'name': 'ddddddd' },
             { 'path': 'impl_trait', 'name': 'bbbbbbb' },
+            { 'path': 'impl_trait::Ccccccc', 'name': 'ddddddd' },
+            { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
+            { 'path': 'impl_trait::Ccccccc', 'name': 'ggggggg' },
+        ],
+    },
+    {
+        'query': '-> Bbbbbbb',
+        'others': [
+            { 'path': 'impl_trait::Ccccccc', 'name': 'ggggggg' },
         ],
     },
     {
@@ -31,13 +39,14 @@ const EXPECTED = [
             { 'path': 'impl_trait', 'name': 'Aaaaaaa' },
         ],
         'in_args': [
-            { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
             { 'path': 'impl_trait::Ccccccc', 'name': 'eeeeeee' },
+            { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
         ],
         'returned': [
-            { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
-            { 'path': 'impl_trait::Ccccccc', 'name': 'ddddddd' },
             { 'path': 'impl_trait', 'name': 'bbbbbbb' },
+            { 'path': 'impl_trait::Ccccccc', 'name': 'ddddddd' },
+            { 'path': 'impl_trait::Ccccccc', 'name': 'fffffff' },
+            { 'path': 'impl_trait::Ccccccc', 'name': 'ggggggg' },
         ],
     },
 ];
diff --git a/tests/rustdoc-js/impl-trait.rs b/tests/rustdoc-js/impl-trait.rs
index fb8869b46f3..d20fdd60ec9 100644
--- a/tests/rustdoc-js/impl-trait.rs
+++ b/tests/rustdoc-js/impl-trait.rs
@@ -1,6 +1,9 @@
 pub trait Aaaaaaa {}
 
+pub trait Bbbbbbb {}
+
 impl Aaaaaaa for () {}
+impl Bbbbbbb for () {}
 
 pub fn bbbbbbb() -> impl Aaaaaaa {
     ()
@@ -18,4 +21,7 @@ impl Ccccccc {
     pub fn fffffff(&self, x: impl Aaaaaaa) -> impl Aaaaaaa {
         x
     }
+    pub fn ggggggg(&self) -> impl Aaaaaaa + Bbbbbbb {
+        ()
+    }
 }
diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr
index 4f2ded78c29..ad049804213 100644
--- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr
+++ b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr
@@ -28,6 +28,8 @@ LL | |
 LL | | /// main;
 LL | | /// ```
    | |_______^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr
index 83e0d3962ca..b25849f25b4 100644
--- a/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr
+++ b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr
@@ -22,6 +22,7 @@ LL | /// [1]
    |      ^ no item named `1` in scope
    |
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 3 warnings emitted
 
diff --git a/tests/rustdoc-ui/issues/issue-105742.stderr b/tests/rustdoc-ui/issues/issue-105742.stderr
index b63176c9149..4d3f9f5bced 100644
--- a/tests/rustdoc-ui/issues/issue-105742.stderr
+++ b/tests/rustdoc-ui/issues/issue-105742.stderr
@@ -169,6 +169,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a`
    |
 LL |     type Item<'a, T>;
    |          ^^^^ --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     <Self as SVec>::Item<'a>,
@@ -185,6 +186,7 @@ note: associated type defined here, with 1 generic parameter: `T`
    |
 LL |     type Item<'a, T>;
    |          ^^^^     -
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing generic argument
    |
 LL |     <Self as SVec>::Item<T>,
@@ -201,6 +203,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a`
    |
 LL |     type Item<'a, T>;
    |          ^^^^ --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     Output = <Index<<Self as SVec>::Item<'a>,
@@ -217,6 +220,7 @@ note: associated type defined here, with 1 generic parameter: `T`
    |
 LL |     type Item<'a, T>;
    |          ^^^^     -
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing generic argument
    |
 LL |     Output = <Index<<Self as SVec>::Item<T>,
@@ -233,6 +237,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a`
    |
 LL |     type Item<'a, T>;
    |          ^^^^ --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     Output = <Self as SVec>::Item<'a>> as SVec>::Item,
@@ -249,6 +254,7 @@ note: associated type defined here, with 1 generic parameter: `T`
    |
 LL |     type Item<'a, T>;
    |          ^^^^     -
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing generic argument
    |
 LL |     Output = <Self as SVec>::Item<T>> as SVec>::Item,
@@ -265,6 +271,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a`
    |
 LL |     type Item<'a, T>;
    |          ^^^^ --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     Output = <Self as SVec>::Item> as SVec>::Item<'a>,
@@ -281,6 +288,7 @@ note: associated type defined here, with 1 generic parameter: `T`
    |
 LL |     type Item<'a, T>;
    |          ^^^^     -
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing generic argument
    |
 LL |     Output = <Self as SVec>::Item> as SVec>::Item<T>,
@@ -327,6 +335,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a`
    |
 LL |     type Item<'a, T>;
    |          ^^^^ --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     <Self as SVec>::Item<'a>,
@@ -343,6 +352,7 @@ note: associated type defined here, with 1 generic parameter: `T`
    |
 LL |     type Item<'a, T>;
    |          ^^^^     -
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing generic argument
    |
 LL |     <Self as SVec>::Item<T>,
@@ -359,6 +369,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a`
    |
 LL |     type Item<'a, T>;
    |          ^^^^ --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     Output = <Index<<Self as SVec>::Item<'a>,
@@ -375,6 +386,7 @@ note: associated type defined here, with 1 generic parameter: `T`
    |
 LL |     type Item<'a, T>;
    |          ^^^^     -
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing generic argument
    |
 LL |     Output = <Index<<Self as SVec>::Item<T>,
@@ -391,6 +403,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a`
    |
 LL |     type Item<'a, T>;
    |          ^^^^ --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     Output = <Self as SVec>::Item<'a>> as SVec>::Item,
@@ -407,6 +420,7 @@ note: associated type defined here, with 1 generic parameter: `T`
    |
 LL |     type Item<'a, T>;
    |          ^^^^     -
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing generic argument
    |
 LL |     Output = <Self as SVec>::Item<T>> as SVec>::Item,
@@ -423,6 +437,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a`
    |
 LL |     type Item<'a, T>;
    |          ^^^^ --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     Output = <Self as SVec>::Item> as SVec>::Item<'a>,
@@ -439,6 +454,7 @@ note: associated type defined here, with 1 generic parameter: `T`
    |
 LL |     type Item<'a, T>;
    |          ^^^^     -
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing generic argument
    |
 LL |     Output = <Self as SVec>::Item> as SVec>::Item<T>,
diff --git a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.rs b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.rs
index c34ea0567a9..ce94a06c39e 100644
--- a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.rs
+++ b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.rs
@@ -1,12 +1,7 @@
+// compile-flags: -Zdeduplicate-diagnostics=yes
 #![deny(unknown_lints)]
 //~^ NOTE defined here
 #![allow(rustdoc::missing_doc_code_examples)]
 //~^ ERROR unknown lint
-//~| ERROR unknown lint
-//~| ERROR unknown lint
 //~| NOTE lint is unstable
-//~| NOTE lint is unstable
-//~| NOTE lint is unstable
-//~| NOTE see issue
-//~| NOTE see issue
 //~| NOTE see issue
diff --git a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr
index 326dcfe3bde..b8a08e94312 100644
--- a/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr
+++ b/tests/rustdoc-ui/lints/feature-gate-rustdoc_missing_doc_code_examples.stderr
@@ -1,5 +1,5 @@
 error: unknown lint: `rustdoc::missing_doc_code_examples`
-  --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:3:1
+  --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:4:1
    |
 LL | #![allow(rustdoc::missing_doc_code_examples)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,30 +8,10 @@ LL | #![allow(rustdoc::missing_doc_code_examples)]
    = note: see issue #101730 <https://github.com/rust-lang/rust/issues/101730> for more information
    = help: add `#![feature(rustdoc_missing_doc_code_examples)]` to the crate attributes to enable
 note: the lint level is defined here
-  --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:1:9
+  --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:2:9
    |
 LL | #![deny(unknown_lints)]
    |         ^^^^^^^^^^^^^
 
-error: unknown lint: `rustdoc::missing_doc_code_examples`
-  --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:3:1
-   |
-LL | #![allow(rustdoc::missing_doc_code_examples)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: the `rustdoc::missing_doc_code_examples` lint is unstable
-   = note: see issue #101730 <https://github.com/rust-lang/rust/issues/101730> for more information
-   = help: add `#![feature(rustdoc_missing_doc_code_examples)]` to the crate attributes to enable
-
-error: unknown lint: `rustdoc::missing_doc_code_examples`
-  --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:3:1
-   |
-LL | #![allow(rustdoc::missing_doc_code_examples)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: the `rustdoc::missing_doc_code_examples` lint is unstable
-   = note: see issue #101730 <https://github.com/rust-lang/rust/issues/101730> for more information
-   = help: add `#![feature(rustdoc_missing_doc_code_examples)]` to the crate attributes to enable
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr
index 83822f778d0..2b4e491b1fe 100644
--- a/tests/rustdoc-ui/unescaped_backticks.stderr
+++ b/tests/rustdoc-ui/unescaped_backticks.stderr
@@ -302,6 +302,7 @@ LL | |     /// level changes.
    = help: if you meant to use a literal backtick, escape it
             change: or `None` if it isn't.
            to this: or `None\` if it isn't.
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: unescaped backtick
   --> $DIR/unescaped_backticks.rs:323:5
@@ -321,6 +322,7 @@ LL | |     /// level changes.
    = help: if you meant to use a literal backtick, escape it
             change: `on_event` should be called.
            to this: `on_event\` should be called.
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: unescaped backtick
   --> $DIR/unescaped_backticks.rs:323:5
@@ -340,6 +342,7 @@ LL | |     /// level changes.
    = help: if you meant to use a literal backtick, escape it
             change: [`rebuild_interest_cache`][rebuild] is called after the value of the max
            to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: unescaped backtick
   --> $DIR/unescaped_backticks.rs:349:56
diff --git a/tests/rustdoc/issue-25001.rs b/tests/rustdoc/anchor-id-duplicate-method-name-25001.rs
index 268fae59496..ffb0765d3c3 100644
--- a/tests/rustdoc/issue-25001.rs
+++ b/tests/rustdoc/anchor-id-duplicate-method-name-25001.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/25001
+#![crate_name="issue_25001"]
+
 // @has issue_25001/struct.Foo.html
 pub struct Foo<T>(T);
 
diff --git a/tests/rustdoc/issue-28478.rs b/tests/rustdoc/anchor-id-trait-tymethod-28478.rs
index 497276e6826..5685040dc1e 100644
--- a/tests/rustdoc/issue-28478.rs
+++ b/tests/rustdoc/anchor-id-trait-tymethod-28478.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/28478
+#![crate_name="issue_28478"]
+
 #![feature(associated_type_defaults)]
 
 // @has issue_28478/trait.Bar.html
diff --git a/tests/rustdoc/issue-21474.rs b/tests/rustdoc/deduplicate-glob-import-impl-21474.rs
index 5de26abace6..2a675b4b6ef 100644
--- a/tests/rustdoc/issue-21474.rs
+++ b/tests/rustdoc/deduplicate-glob-import-impl-21474.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/21474
+#![crate_name="issue_21474"]
+
 pub use inner::*;
 
 mod inner {
diff --git a/tests/rustdoc/issue-22025.rs b/tests/rustdoc/deduplicate-trait-impl-22025.rs
index a721a15f463..65a556e3a70 100644
--- a/tests/rustdoc/issue-22025.rs
+++ b/tests/rustdoc/deduplicate-trait-impl-22025.rs
@@ -1,6 +1,9 @@
 // aux-build:issue-22025.rs
 // ignore-cross-compile
 
+// https://github.com/rust-lang/rust/issues/22025
+#![crate_name="issue_22025"]
+
 extern crate issue_22025;
 
 pub use issue_22025::foo::{Foo, Bar};
diff --git a/tests/rustdoc/doctest-hide-empty-line-23106.rs b/tests/rustdoc/doctest-hide-empty-line-23106.rs
new file mode 100644
index 00000000000..8e1e2cf098c
--- /dev/null
+++ b/tests/rustdoc/doctest-hide-empty-line-23106.rs
@@ -0,0 +1,10 @@
+// compile-flags:--test
+
+// https://github.com/rust-lang/rust/issues/23106
+#![crate_name="issue_23106"]
+
+/// ```
+/// #
+/// ```
+pub fn main() {
+}
diff --git a/tests/rustdoc/issue-23744.rs b/tests/rustdoc/doctest-markdown-inline-parse-23744.rs
index 642817396b2..128e2daba07 100644
--- a/tests/rustdoc/issue-23744.rs
+++ b/tests/rustdoc/doctest-markdown-inline-parse-23744.rs
@@ -1,5 +1,8 @@
 // compile-flags:--test
 
+// https://github.com/rust-lang/rust/issues/23744
+#![crate_name="issue_23744"]
+
 /// Example of rustdoc incorrectly parsing <code>```rust,should_panic</code>.
 ///
 /// ```should_panic
diff --git a/tests/rustdoc/issue-25944.rs b/tests/rustdoc/doctest-multi-line-string-literal-25944.rs
index 49625294bbe..eec796e4fbf 100644
--- a/tests/rustdoc/issue-25944.rs
+++ b/tests/rustdoc/doctest-multi-line-string-literal-25944.rs
@@ -1,5 +1,8 @@
 // compile-flags:--test
 
+// https://github.com/rust-lang/rust/issues/25944
+#![crate_name="issue_25944"]
+
 /// ```
 /// let a = r#"
 /// foo
diff --git a/tests/rustdoc/issue-22038.rs b/tests/rustdoc/extern-fn-22038.rs
index de6cc78707c..72d39c32a1c 100644
--- a/tests/rustdoc/issue-22038.rs
+++ b/tests/rustdoc/extern-fn-22038.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/22038
+#![crate_name="issue_22038"]
+
 extern "C" {
     // @has issue_22038/fn.foo1.html \
     //      '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn foo1()'
diff --git a/tests/rustdoc/issue-28927.rs b/tests/rustdoc/ice-reexport-crate-root-28927.rs
index 38a520850b6..26debfc60e4 100644
--- a/tests/rustdoc/issue-28927.rs
+++ b/tests/rustdoc/ice-reexport-crate-root-28927.rs
@@ -2,5 +2,8 @@
 // aux-build:issue-28927-1.rs
 // ignore-cross-compile
 
+// https://github.com/rust-lang/rust/issues/28927
+#![crate_name="issue_28927"]
+
 pub extern crate issue_28927_1 as inner1;
 pub use inner1 as foo;
diff --git a/tests/rustdoc/issue-21092.rs b/tests/rustdoc/impl-assoc-type-21092.rs
index b054145a483..f01f098a92f 100644
--- a/tests/rustdoc/issue-21092.rs
+++ b/tests/rustdoc/impl-assoc-type-21092.rs
@@ -1,6 +1,9 @@
 // aux-build:issue-21092.rs
 // ignore-cross-compile
 
+// https://github.com/rust-lang/rust/issues/21092
+#![crate_name="issue_21092"]
+
 extern crate issue_21092;
 
 // @has issue_21092/struct.Bar.html
diff --git a/tests/rustdoc/inline_cross/auxiliary/fn-type.rs b/tests/rustdoc/inline_cross/auxiliary/fn-type.rs
new file mode 100644
index 00000000000..dacda516bb8
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/fn-type.rs
@@ -0,0 +1 @@
+pub type F = for<'z, 'a, '_unused> fn(&'z for<'b> fn(&'b str), &'a ()) -> &'a ();
diff --git a/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
index 42cfc3dc319..fa61312ebc8 100644
--- a/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
+++ b/tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
@@ -15,7 +15,7 @@ pub fn func4<T: Iterator<Item = impl Clone>>(_x: T) {}
 
 pub fn func5(
     _f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,
-    _a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>,
+    _a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>,
 ) {}
 
 pub trait Other {
diff --git a/tests/rustdoc/auxiliary/issue-21801.rs b/tests/rustdoc/inline_cross/auxiliary/issue-21801.rs
index 732612ff000..732612ff000 100644
--- a/tests/rustdoc/auxiliary/issue-21801.rs
+++ b/tests/rustdoc/inline_cross/auxiliary/issue-21801.rs
diff --git a/tests/rustdoc/auxiliary/issue-23207-1.rs b/tests/rustdoc/inline_cross/auxiliary/issue-23207-1.rs
index 8531d5f1acd..8531d5f1acd 100644
--- a/tests/rustdoc/auxiliary/issue-23207-1.rs
+++ b/tests/rustdoc/inline_cross/auxiliary/issue-23207-1.rs
diff --git a/tests/rustdoc/auxiliary/issue-23207-2.rs b/tests/rustdoc/inline_cross/auxiliary/issue-23207-2.rs
index b92b1665316..b92b1665316 100644
--- a/tests/rustdoc/auxiliary/issue-23207-2.rs
+++ b/tests/rustdoc/inline_cross/auxiliary/issue-23207-2.rs
diff --git a/tests/rustdoc/auxiliary/issue-27362-aux.rs b/tests/rustdoc/inline_cross/auxiliary/issue-27362-aux.rs
index 077bdc33e66..077bdc33e66 100644
--- a/tests/rustdoc/auxiliary/issue-27362-aux.rs
+++ b/tests/rustdoc/inline_cross/auxiliary/issue-27362-aux.rs
diff --git a/tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs b/tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs
new file mode 100644
index 00000000000..9170be16892
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs
@@ -0,0 +1,10 @@
+#![feature(non_lifetime_binders)]
+
+pub trait Trait<T> {}
+
+pub fn f(_: impl for<T> Trait<T>) {}
+
+pub fn g<T>(_: T)
+where
+    T: for<U> Trait<U>,
+{}
diff --git a/tests/rustdoc/issue-27362.rs b/tests/rustdoc/inline_cross/const-fn-27362.rs
index 097e4e3b03d..39b904662e0 100644
--- a/tests/rustdoc/issue-27362.rs
+++ b/tests/rustdoc/inline_cross/const-fn-27362.rs
@@ -1,6 +1,9 @@
 // aux-build:issue-27362-aux.rs
 // ignore-cross-compile
 
+// https://github.com/rust-lang/rust/issues/27362
+#![crate_name="issue_27362"]
+
 extern crate issue_27362_aux;
 
 pub use issue_27362_aux::*;
diff --git a/tests/rustdoc/issue-23207.rs b/tests/rustdoc/inline_cross/deduplicate-inlined-items-23207.rs
index 1a4b849ee82..4e9596db589 100644
--- a/tests/rustdoc/issue-23207.rs
+++ b/tests/rustdoc/inline_cross/deduplicate-inlined-items-23207.rs
@@ -2,6 +2,9 @@
 // aux-build:issue-23207-2.rs
 // ignore-cross-compile
 
+// https://github.com/rust-lang/rust/issues/23207
+#![crate_name="issue_23207"]
+
 extern crate issue_23207_2;
 
 // @has issue_23207/fmt/index.html
diff --git a/tests/rustdoc/inline_cross/fn-type.rs b/tests/rustdoc/inline_cross/fn-type.rs
new file mode 100644
index 00000000000..e65790d3b05
--- /dev/null
+++ b/tests/rustdoc/inline_cross/fn-type.rs
@@ -0,0 +1,12 @@
+// Make sure that we print the higher-ranked parameters of cross-crate function pointer types.
+// They should be rendered exactly as the user wrote it, i.e., in source order and with unused
+// parameters present, not stripped.
+
+// aux-crate:fn_type=fn-type.rs
+// edition: 2021
+#![crate_name = "user"]
+
+// @has user/type.F.html
+// @has - '//*[@class="rust item-decl"]//code' \
+//     "for<'z, 'a, '_unused> fn(_: &'z for<'b> fn(_: &'b str), _: &'a ()) -> &'a ();"
+pub use fn_type::F;
diff --git a/tests/rustdoc/inline_cross/impl_trait.rs b/tests/rustdoc/inline_cross/impl_trait.rs
index 5c802c51486..9b22026e490 100644
--- a/tests/rustdoc/inline_cross/impl_trait.rs
+++ b/tests/rustdoc/inline_cross/impl_trait.rs
@@ -29,7 +29,7 @@ pub use impl_trait_aux::func4;
 // @has impl_trait/fn.func5.html
 // @has - '//pre[@class="rust item-decl"]' "func5("
 // @has - '//pre[@class="rust item-decl"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
-// @has - '//pre[@class="rust item-decl"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
+// @has - '//pre[@class="rust item-decl"]' "_a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
 // @!has - '//pre[@class="rust item-decl"]' 'where'
 pub use impl_trait_aux::func5;
 
diff --git a/tests/rustdoc/inline_cross/non_lifetime_binders.rs b/tests/rustdoc/inline_cross/non_lifetime_binders.rs
new file mode 100644
index 00000000000..9d3085c3ef2
--- /dev/null
+++ b/tests/rustdoc/inline_cross/non_lifetime_binders.rs
@@ -0,0 +1,13 @@
+// aux-crate:non_lifetime_binders=non_lifetime_binders.rs
+// edition: 2021
+#![crate_name = "user"]
+
+// @has user/fn.f.html
+// @has - '//pre[@class="rust item-decl"]' "f(_: impl for<T> Trait<T>)"
+pub use non_lifetime_binders::f;
+
+// @has user/fn.g.html
+// @has - '//pre[@class="rust item-decl"]' "g<T>(_: T)\
+// where \
+//     T: for<U> Trait<U>"
+pub use non_lifetime_binders::g;
diff --git a/tests/rustdoc/issue-21801.rs b/tests/rustdoc/inline_cross/sugar-closure-crate-21801.rs
index 29d2ec64c20..bcbb2e9f408 100644
--- a/tests/rustdoc/issue-21801.rs
+++ b/tests/rustdoc/inline_cross/sugar-closure-crate-21801.rs
@@ -1,6 +1,9 @@
 // aux-build:issue-21801.rs
 // ignore-cross-compile
 
+// https://github.com/rust-lang/rust/issues/21801
+#![crate_name="issue_21801"]
+
 extern crate issue_21801;
 
 // @has issue_21801/struct.Foo.html
diff --git a/tests/rustdoc/issue-23106.rs b/tests/rustdoc/issue-23106.rs
deleted file mode 100644
index 8cda2fc3380..00000000000
--- a/tests/rustdoc/issue-23106.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// compile-flags:--test
-
-/// ```
-/// #
-/// ```
-pub fn main() {
-}
diff --git a/tests/rustdoc/issue-23812.rs b/tests/rustdoc/macro-doc-comment-23812.rs
index 08fd1833bce..57c18510b1e 100644
--- a/tests/rustdoc/issue-23812.rs
+++ b/tests/rustdoc/macro-doc-comment-23812.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/23812
+#![crate_name="issue_23812"]
+
 macro_rules! doc {
     (#[$outer:meta] mod $i:ident { #![$inner:meta] }) =>
     (
diff --git a/tests/rustdoc/issue-27862.rs b/tests/rustdoc/markdown-table-escape-pipe-27862.rs
index 77522f1be23..9af75d24888 100644
--- a/tests/rustdoc/issue-27862.rs
+++ b/tests/rustdoc/markdown-table-escape-pipe-27862.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/27862
+#![crate_name="issue_27862"]
+
 /// Tests  | Table
 /// ------|-------------
 /// t = b | id = \|x\| x
diff --git a/tests/rustdoc/issue-23511.rs b/tests/rustdoc/search-index-primitive-inherent-method-23511.rs
index 21d02842431..1d0fe27e192 100644
--- a/tests/rustdoc/issue-23511.rs
+++ b/tests/rustdoc/search-index-primitive-inherent-method-23511.rs
@@ -2,6 +2,9 @@
 #![feature(rustdoc_internals)]
 #![no_std]
 
+// https://github.com/rust-lang/rust/issues/23511
+#![crate_name="issue_23511"]
+
 pub mod str {
     #![rustc_doc_primitive = "str"]
 
diff --git a/tests/rustdoc/issue-26606.rs b/tests/rustdoc/src-link-external-macro-26606.rs
index d5cb2c710cd..de717a5273b 100644
--- a/tests/rustdoc/issue-26606.rs
+++ b/tests/rustdoc/src-link-external-macro-26606.rs
@@ -2,10 +2,13 @@
 // ignore-cross-compile
 // build-aux-docs
 
+// https://github.com/rust-lang/rust/issues/26606
+#![crate_name="issue_26606"]
+
 // @has issue_26606_macro/macro.make_item.html
 #[macro_use]
 extern crate issue_26606_macro;
 
 // @has issue_26606/constant.FOO.html
-// @has - '//a[@href="../src/issue_26606/issue-26606.rs.html#11"]' 'source'
+// @has - '//a[@href="../src/issue_26606/src-link-external-macro-26606.rs.html#14"]' 'source'
 make_item!(FOO);
diff --git a/tests/rustdoc/issue-26995.rs b/tests/rustdoc/src-mod-path-absolute-26995.rs
index fedc9f51749..b67fd9b26db 100644
--- a/tests/rustdoc/issue-26995.rs
+++ b/tests/rustdoc/src-mod-path-absolute-26995.rs
@@ -1,6 +1,9 @@
 // ignore-windows
 // compile-flags: --no-defaults
 
+// https://github.com/rust-lang/rust/issues/26995
+#![crate_name="issue_26995"]
+
 // @has src/issue_26995/dev/null.html
 // @has issue_26995/null/index.html '//a/@href' '../../src/issue_26995/dev/null.html'
 #[path="/dev/null"]
diff --git a/tests/rustdoc/issue-27759.rs b/tests/rustdoc/staged-api-feature-issue-27759.rs
index 65e0f7cb87b..56a45a600da 100644
--- a/tests/rustdoc/issue-27759.rs
+++ b/tests/rustdoc/staged-api-feature-issue-27759.rs
@@ -1,3 +1,6 @@
+// https://github.com/rust-lang/rust/issues/27759
+#![crate_name="issue_27759"]
+
 #![feature(staged_api)]
 #![doc(issue_tracker_base_url = "http://issue_url/")]
 
diff --git a/tests/rustdoc/issue-27104.rs b/tests/rustdoc/strip-priv-imports-pass-27104.rs
index 9f2fd907114..e400a8f5011 100644
--- a/tests/rustdoc/issue-27104.rs
+++ b/tests/rustdoc/strip-priv-imports-pass-27104.rs
@@ -2,6 +2,9 @@
 // aux-build:empty.rs
 // ignore-cross-compile
 
+// https://github.com/rust-lang/rust/issues/27104
+#![crate_name="issue_27104"]
+
 // @has issue_27104/index.html
 // @!hasraw - 'extern crate std'
 // @!hasraw - 'use std::prelude::'
diff --git a/tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.stderr b/tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.stderr
index ae34b25cc2f..66ea2e88f0c 100644
--- a/tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.stderr
+++ b/tests/ui-fulldeps/plugin/lint-plugin-forbid-attrs.stderr
@@ -27,6 +27,8 @@ LL | #![forbid(test_lint)]
 ...
 LL | #[allow(test_lint)]
    |         ^^^^^^^^^ overruled by previous forbid
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
   --> $DIR/lint-plugin-forbid-attrs.rs:5:1
diff --git a/tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.stderr b/tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.stderr
index 491c4d20646..9dbad702545 100644
--- a/tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.stderr
+++ b/tests/ui-fulldeps/plugin/lint-plugin-forbid-cmdline.stderr
@@ -21,6 +21,7 @@ LL | #[allow(test_lint)]
    |         ^^^^^^^^^ overruled by previous forbid
    |
    = note: `forbid` lint level was set on command line
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
   --> $DIR/lint-plugin-forbid-cmdline.rs:6:1
diff --git a/tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.stderr b/tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.stderr
index 0e661795999..4916b180a36 100644
--- a/tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.stderr
+++ b/tests/ui-fulldeps/plugin/lint-tool-cmdline-allow.stderr
@@ -8,6 +8,7 @@ warning: lint name `test_lint` is deprecated and may not have an effect in the f
    |
    = help: change it to clippy::test_lint
    = note: requested on the command line with `-A test_lint`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: item is named 'lintme'
   --> $DIR/lint-tool-cmdline-allow.rs:9:1
@@ -29,6 +30,7 @@ warning: lint name `test_lint` is deprecated and may not have an effect in the f
    |
    = help: change it to clippy::test_lint
    = note: requested on the command line with `-A test_lint`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 5 warnings emitted
 
diff --git a/tests/ui-fulldeps/plugin/lint-tool-test.stderr b/tests/ui-fulldeps/plugin/lint-tool-test.stderr
index 027cf8f80cf..d1f0714f042 100644
--- a/tests/ui-fulldeps/plugin/lint-tool-test.stderr
+++ b/tests/ui-fulldeps/plugin/lint-tool-test.stderr
@@ -23,12 +23,16 @@ warning: lint name `test_lint` is deprecated and may not have an effect in the f
    |
 LL | #![cfg_attr(foo, warn(test_lint))]
    |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
   --> $DIR/lint-tool-test.rs:13:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: item is named 'lintme'
   --> $DIR/lint-tool-test.rs:18:1
@@ -56,6 +60,8 @@ warning: lint name `test_group` is deprecated and may not have an effect in the
    |
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `this_lint_does_not_exist`
   --> $DIR/lint-tool-test.rs:33:8
@@ -78,18 +84,24 @@ warning: lint name `test_lint` is deprecated and may not have an effect in the f
    |
 LL | #![cfg_attr(foo, warn(test_lint))]
    |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
   --> $DIR/lint-tool-test.rs:13:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: lint name `test_group` is deprecated and may not have an effect in the future.
   --> $DIR/lint-tool-test.rs:29:9
    |
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors; 11 warnings emitted
 
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index ca09f1f0153..014cd5a73bd 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -414,6 +414,8 @@ error: `#[lint(...)]` is not a valid attribute
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:601:1
diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs
index ce4ee3c2463..d482f62ff06 100644
--- a/tests/ui-fulldeps/stable-mir/crate-info.rs
+++ b/tests/ui-fulldeps/stable-mir/crate-info.rs
@@ -47,12 +47,12 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
     assert_eq!(body.blocks.len(), 1);
     let block = &body.blocks[0];
     assert_eq!(block.statements.len(), 1);
-    match &block.statements[0] {
-        stable_mir::mir::Statement::Assign(..) => {}
+    match &block.statements[0].kind {
+        stable_mir::mir::StatementKind::Assign(..) => {}
         other => panic!("{other:?}"),
     }
-    match &block.terminator {
-        stable_mir::mir::Terminator::Return => {}
+    match &block.terminator.kind {
+        stable_mir::mir::TerminatorKind::Return => {}
         other => panic!("{other:?}"),
     }
 
@@ -61,8 +61,8 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
     assert_eq!(body.locals.len(), 7);
     assert_eq!(body.blocks.len(), 4);
     let block = &body.blocks[0];
-    match &block.terminator {
-        stable_mir::mir::Terminator::Call { .. } => {}
+    match &block.terminator.kind {
+        stable_mir::mir::TerminatorKind::Call { .. } => {}
         other => panic!("{other:?}"),
     }
 
@@ -70,27 +70,27 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
     let body = types.body();
     assert_eq!(body.locals.len(), 6);
     assert_matches!(
-        body.locals[0].kind(),
+        body.locals[0].ty.kind(),
         stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Bool)
     );
     assert_matches!(
-        body.locals[1].kind(),
+        body.locals[1].ty.kind(),
         stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Bool)
     );
     assert_matches!(
-        body.locals[2].kind(),
+        body.locals[2].ty.kind(),
         stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Char)
     );
     assert_matches!(
-        body.locals[3].kind(),
+        body.locals[3].ty.kind(),
         stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Int(stable_mir::ty::IntTy::I32))
     );
     assert_matches!(
-        body.locals[4].kind(),
+        body.locals[4].ty.kind(),
         stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Uint(stable_mir::ty::UintTy::U64))
     );
     assert_matches!(
-        body.locals[5].kind(),
+        body.locals[5].ty.kind(),
         stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Float(
             stable_mir::ty::FloatTy::F64
         ))
@@ -100,8 +100,8 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
     let body = drop.body();
     assert_eq!(body.blocks.len(), 2);
     let block = &body.blocks[0];
-    match &block.terminator {
-        stable_mir::mir::Terminator::Drop { .. } => {}
+    match &block.terminator.kind {
+        stable_mir::mir::TerminatorKind::Drop { .. } => {}
         other => panic!("{other:?}"),
     }
 
@@ -109,15 +109,15 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
     let body = assert.body();
     assert_eq!(body.blocks.len(), 2);
     let block = &body.blocks[0];
-    match &block.terminator {
-        stable_mir::mir::Terminator::Assert { .. } => {}
+    match &block.terminator.kind {
+        stable_mir::mir::TerminatorKind::Assert { .. } => {}
         other => panic!("{other:?}"),
     }
 
     let monomorphic = get_item(&items, (DefKind::Fn, "monomorphic")).unwrap();
     for block in monomorphic.body().blocks {
-        match &block.terminator {
-            stable_mir::mir::Terminator::Call { func, .. } => match func {
+        match &block.terminator.kind {
+            stable_mir::mir::TerminatorKind::Call { func, .. } => match func {
                 stable_mir::mir::Operand::Constant(c) => match &c.literal.literal {
                     stable_mir::ty::ConstantKind::Allocated(alloc) => {
                         assert!(alloc.bytes.is_empty());
@@ -127,7 +127,7 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
                                 mut args,
                             )) => {
                                 let func = def.body();
-                                match func.locals[1]
+                                match func.locals[1].ty
                                     .fold(&mut args)
                                     .continue_value()
                                     .unwrap()
@@ -149,7 +149,7 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
                 },
                 other => panic!("{other:?}"),
             },
-            stable_mir::mir::Terminator::Return => {}
+            stable_mir::mir::TerminatorKind::Return => {}
             other => panic!("{other:?}"),
         }
     }
diff --git a/tests/ui/allocator/not-an-allocator.stderr b/tests/ui/allocator/not-an-allocator.stderr
index 62bb0679f81..e1967b70013 100644
--- a/tests/ui/allocator/not-an-allocator.stderr
+++ b/tests/ui/allocator/not-an-allocator.stderr
@@ -18,6 +18,7 @@ LL | static A: usize = 0;
    |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
    = help: the trait `GlobalAlloc` is implemented for `System`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
    = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
@@ -29,6 +30,7 @@ LL | static A: usize = 0;
    |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
    = help: the trait `GlobalAlloc` is implemented for `System`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
    = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
@@ -40,6 +42,7 @@ LL | static A: usize = 0;
    |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
    = help: the trait `GlobalAlloc` is implemented for `System`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
    = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/associated-consts/defaults-not-assumed-fail.stderr b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr
index d659912341a..ac5ec8e05ea 100644
--- a/tests/ui/associated-consts/defaults-not-assumed-fail.stderr
+++ b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr
@@ -24,6 +24,7 @@ note: erroneous constant encountered
 LL |     assert_eq!(<() as Tr>::B, 0);    // causes the error above
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
    = note: this note originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr
index 927422fa8dc..200856caa25 100644
--- a/tests/ui/associated-consts/issue-105330.stderr
+++ b/tests/ui/associated-consts/issue-105330.stderr
@@ -33,7 +33,7 @@ LL | fn main<A: TraitWAssocConst<A=32>>() {
    = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
    = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers
   --> $DIR/issue-105330.rs:6:27
    |
 LL | impl TraitWAssocConst for impl Demo {
diff --git a/tests/ui/associated-inherent-types/issue-109789.stderr b/tests/ui/associated-inherent-types/issue-109789.stderr
index 84fc85cd09e..e844f6795e6 100644
--- a/tests/ui/associated-inherent-types/issue-109789.stderr
+++ b/tests/ui/associated-inherent-types/issue-109789.stderr
@@ -15,6 +15,7 @@ LL | fn bar(_: Foo<for<'a> fn(&'a ())>::Assoc) {}
    |
    = note: expected struct `Foo<fn(&'static ())>`
               found struct `Foo<for<'a> fn(&'a ())>`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/associated-type-bounds/duplicate.stderr b/tests/ui/associated-type-bounds/duplicate.stderr
index 08721eff7b0..3629aa4fcea 100644
--- a/tests/ui/associated-type-bounds/duplicate.stderr
+++ b/tests/ui/associated-type-bounds/duplicate.stderr
@@ -373,6 +373,8 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
    |                      |
    |                      `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
   --> $DIR/duplicate.rs:197:34
@@ -389,6 +391,8 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
    |                      |
    |                      `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
   --> $DIR/duplicate.rs:200:37
@@ -405,6 +409,8 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |                      -------------  ^^^^^^^^^^^^^ re-bound here
    |                      |
    |                      `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
   --> $DIR/duplicate.rs:205:29
@@ -445,6 +451,8 @@ LL |     Self: Iterator<Item: Copy, Item: Send>,
    |                    ----------  ^^^^^^^^^^ re-bound here
    |                    |
    |                    `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
   --> $DIR/duplicate.rs:230:32
@@ -461,6 +469,8 @@ LL |     Self: Iterator<Item: Copy, Item: Copy>,
    |                    ----------  ^^^^^^^^^^ re-bound here
    |                    |
    |                    `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
   --> $DIR/duplicate.rs:237:35
@@ -477,6 +487,8 @@ LL |     Self: Iterator<Item: 'static, Item: 'static>,
    |                    -------------  ^^^^^^^^^^^^^ re-bound here
    |                    |
    |                    `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
   --> $DIR/duplicate.rs:255:40
diff --git a/tests/ui/associated-type-bounds/issue-71443-1.stderr b/tests/ui/associated-type-bounds/issue-71443-1.stderr
index 15cc9646b2c..09c8ec2e289 100644
--- a/tests/ui/associated-type-bounds/issue-71443-1.stderr
+++ b/tests/ui/associated-type-bounds/issue-71443-1.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-71443-1.rs:6:5
    |
 LL | fn hello<F: for<'a> Iterator<Item: 'a>>() {
-   |                                           - help: try adding a return type: `-> Incorrect`
+   |                                          - help: try adding a return type: `-> Incorrect`
 LL |     Incorrect
    |     ^^^^^^^^^ expected `()`, found `Incorrect`
 
diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr
index 366670269d7..1a749007ab6 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr
@@ -45,6 +45,7 @@ LL | trait Z<'a, T: ?Sized>
 ...
 LL |     for<'b> <T as Z<'b, u16>>::W: Clone,
    |                                   ^^^^^ required by this bound in `Z`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/async-await/async-await-let-else.stderr b/tests/ui/async-await/async-await-let-else.stderr
index 9a1c1782233..c3b4e761824 100644
--- a/tests/ui/async-await/async-await-let-else.stderr
+++ b/tests/ui/async-await/async-await-let-else.stderr
@@ -22,7 +22,7 @@ error[E0277]: `Rc<()>` cannot be sent between threads safely
   --> $DIR/async-await-let-else.rs:47:13
    |
 LL | async fn foo2(x: Option<bool>) {
-   |                                - within this `impl Future<Output = ()>`
+   | ------------------------------ within this `impl Future<Output = ()>`
 ...
 LL |     is_send(foo2(Some(true)));
    |     ------- ^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely
diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr
index cfb0ebe38b6..0d3ee8a9377 100644
--- a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr
+++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr
@@ -23,6 +23,7 @@ LL | |     });
    |
    = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`...
    = note: ...but it actually implements `FnOnce<(&(),)>`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/async-await/in-trait/async-associated-types.rs b/tests/ui/async-await/in-trait/async-associated-types.rs
index 3e2739a164f..14f18811c1e 100644
--- a/tests/ui/async-await/in-trait/async-associated-types.rs
+++ b/tests/ui/async-await/in-trait/async-associated-types.rs
@@ -9,12 +9,14 @@ use std::fmt::Debug;
 trait MyTrait<'a, 'b, T> where Self: 'a, T: Debug + Sized + 'b {
     type MyAssoc;
 
+    #[allow(async_fn_in_trait)]
     async fn foo(&'a self, key: &'b T) -> Self::MyAssoc;
 }
 
 impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U {
     type MyAssoc = (&'a U, &'b T);
 
+    #[allow(async_fn_in_trait)]
     async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
         (self, key)
     }
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
index 06413fe6f82..8143f0bca03 100644
--- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
@@ -6,10 +6,12 @@
 use std::future::Future;
 
 trait AsyncTrait {
+    #[allow(async_fn_in_trait)]
     async fn default_impl() {
         assert!(false);
     }
 
+    #[allow(async_fn_in_trait)]
     async fn call_default_impl() {
         Self::default_impl().await
     }
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
index 168ef8e9ee4..3f1f1766eb5 100644
--- a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
@@ -1,8 +1,8 @@
 error[E0053]: method `foo` has an incompatible type for trait
-  --> $DIR/async-example-desugared-boxed-in-trait.rs:15:28
+  --> $DIR/async-example-desugared-boxed-in-trait.rs:15:5
    |
 LL |     async fn foo(&self) -> i32 {
-   |                            ^^^ expected `Pin<Box<dyn Future<Output = i32>>>`, found future
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Pin<Box<dyn Future<Output = i32>>>`, found future
    |
 note: type in trait
   --> $DIR/async-example-desugared-boxed-in-trait.rs:11:22
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs
index 3505690f1ec..5d5aa817b4c 100644
--- a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs
+++ b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs
@@ -10,6 +10,7 @@ use std::pin::Pin;
 use std::task::Poll;
 
 pub trait MyTrait {
+    #[allow(async_fn_in_trait)]
     async fn foo(&self) -> i32;
 }
 
diff --git a/tests/ui/async-await/in-trait/async-example-desugared.rs b/tests/ui/async-await/in-trait/async-example-desugared.rs
index 0a5023176fe..7987645c97b 100644
--- a/tests/ui/async-await/in-trait/async-example-desugared.rs
+++ b/tests/ui/async-await/in-trait/async-example-desugared.rs
@@ -8,6 +8,7 @@
 use std::future::Future;
 
 trait MyTrait {
+    #[allow(async_fn_in_trait)]
     async fn foo(&self) -> i32;
 }
 
diff --git a/tests/ui/async-await/in-trait/async-example.rs b/tests/ui/async-await/in-trait/async-example.rs
index abf94ef7450..8c80c21eabe 100644
--- a/tests/ui/async-await/in-trait/async-example.rs
+++ b/tests/ui/async-await/in-trait/async-example.rs
@@ -5,7 +5,10 @@
 #![allow(incomplete_features)]
 
 trait MyTrait {
+    #[allow(async_fn_in_trait)]
     async fn foo(&self) -> i32;
+
+    #[allow(async_fn_in_trait)]
     async fn bar(&self) -> i32;
 }
 
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
index 5c8d64fc6cb..90b40e221e4 100644
--- a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
@@ -1,8 +1,8 @@
 error[E0311]: the parameter type `U` may not live long enough
-  --> $DIR/async-generics-and-bounds.rs:12:28
+  --> $DIR/async-generics-and-bounds.rs:12:5
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
-   |                            ^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the parameter type `U` must be valid for the anonymous lifetime as defined here...
   --> $DIR/async-generics-and-bounds.rs:12:18
@@ -10,16 +10,16 @@ note: the parameter type `U` must be valid for the anonymous lifetime as defined
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                  ^
 note: ...so that the reference type `&(T, U)` does not outlive the data it points at
-  --> $DIR/async-generics-and-bounds.rs:12:28
+  --> $DIR/async-generics-and-bounds.rs:12:5
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
-   |                            ^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0311]: the parameter type `T` may not live long enough
-  --> $DIR/async-generics-and-bounds.rs:12:28
+  --> $DIR/async-generics-and-bounds.rs:12:5
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
-   |                            ^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the parameter type `T` must be valid for the anonymous lifetime as defined here...
   --> $DIR/async-generics-and-bounds.rs:12:18
@@ -27,10 +27,10 @@ note: the parameter type `T` must be valid for the anonymous lifetime as defined
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                  ^
 note: ...so that the reference type `&(T, U)` does not outlive the data it points at
-  --> $DIR/async-generics-and-bounds.rs:12:28
+  --> $DIR/async-generics-and-bounds.rs:12:5
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
-   |                            ^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/async-await/in-trait/async-generics.stderr b/tests/ui/async-await/in-trait/async-generics.stderr
index 6ae73d9e3a6..07f986e94e0 100644
--- a/tests/ui/async-await/in-trait/async-generics.stderr
+++ b/tests/ui/async-await/in-trait/async-generics.stderr
@@ -1,8 +1,8 @@
 error[E0311]: the parameter type `U` may not live long enough
-  --> $DIR/async-generics.rs:9:28
+  --> $DIR/async-generics.rs:9:5
    |
 LL |     async fn foo(&self) -> &(T, U);
-   |                            ^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the parameter type `U` must be valid for the anonymous lifetime as defined here...
   --> $DIR/async-generics.rs:9:18
@@ -10,16 +10,16 @@ note: the parameter type `U` must be valid for the anonymous lifetime as defined
 LL |     async fn foo(&self) -> &(T, U);
    |                  ^
 note: ...so that the reference type `&(T, U)` does not outlive the data it points at
-  --> $DIR/async-generics.rs:9:28
+  --> $DIR/async-generics.rs:9:5
    |
 LL |     async fn foo(&self) -> &(T, U);
-   |                            ^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0311]: the parameter type `T` may not live long enough
-  --> $DIR/async-generics.rs:9:28
+  --> $DIR/async-generics.rs:9:5
    |
 LL |     async fn foo(&self) -> &(T, U);
-   |                            ^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the parameter type `T` must be valid for the anonymous lifetime as defined here...
   --> $DIR/async-generics.rs:9:18
@@ -27,10 +27,10 @@ note: the parameter type `T` must be valid for the anonymous lifetime as defined
 LL |     async fn foo(&self) -> &(T, U);
    |                  ^
 note: ...so that the reference type `&(T, U)` does not outlive the data it points at
-  --> $DIR/async-generics.rs:9:28
+  --> $DIR/async-generics.rs:9:5
    |
 LL |     async fn foo(&self) -> &(T, U);
-   |                            ^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
index d5481d277e4..96cda4e35da 100644
--- a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
+++ b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
@@ -7,6 +7,7 @@
 use std::fmt::Debug;
 
 trait MyTrait<'a, 'b, T> {
+    #[allow(async_fn_in_trait)]
     async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized;
 }
 
diff --git a/tests/ui/async-await/in-trait/async-lifetimes.rs b/tests/ui/async-await/in-trait/async-lifetimes.rs
index f298e45d239..4b0264bc8d0 100644
--- a/tests/ui/async-await/in-trait/async-lifetimes.rs
+++ b/tests/ui/async-await/in-trait/async-lifetimes.rs
@@ -5,6 +5,7 @@
 #![allow(incomplete_features)]
 
 trait MyTrait<'a, 'b, T> {
+    #[allow(async_fn_in_trait)]
     async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T);
 }
 
diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.stderr b/tests/ui/async-await/in-trait/async-recursive-generic.stderr
index cab173bdd5b..6897bf1c999 100644
--- a/tests/ui/async-await/in-trait/async-recursive-generic.stderr
+++ b/tests/ui/async-await/in-trait/async-recursive-generic.stderr
@@ -1,8 +1,8 @@
 error[E0733]: recursion in an `async fn` requires boxing
-  --> $DIR/async-recursive-generic.rs:11:48
+  --> $DIR/async-recursive-generic.rs:11:5
    |
 LL |     async fn foo_recursive(&self, n: usize) -> T {
-   |                                                ^ recursive `async fn`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn`
    |
    = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
    = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
diff --git a/tests/ui/async-await/in-trait/async-recursive.stderr b/tests/ui/async-await/in-trait/async-recursive.stderr
index 9feff37b3fe..c9b4784e3b4 100644
--- a/tests/ui/async-await/in-trait/async-recursive.stderr
+++ b/tests/ui/async-await/in-trait/async-recursive.stderr
@@ -1,8 +1,8 @@
 error[E0733]: recursion in an `async fn` requires boxing
-  --> $DIR/async-recursive.rs:11:48
+  --> $DIR/async-recursive.rs:11:5
    |
 LL |     async fn foo_recursive(&self, n: usize) -> i32 {
-   |                                                ^^^ recursive `async fn`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn`
    |
    = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
    = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
index 7c750bf5101..4ba6d4cba0c 100644
--- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
+++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
@@ -1,14 +1,14 @@
 error[E0053]: method `foo` has an incompatible type for trait
-  --> $DIR/dont-project-to-specializable-projection.rs:14:35
+  --> $DIR/dont-project-to-specializable-projection.rs:14:5
    |
 LL |     default async fn foo(_: T) -> &'static str {
-   |                                   ^^^^^^^^^^^^ expected associated type, found future
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found future
    |
 note: type in trait
-  --> $DIR/dont-project-to-specializable-projection.rs:10:27
+  --> $DIR/dont-project-to-specializable-projection.rs:10:5
    |
 LL |     async fn foo(_: T) -> &'static str;
-   |                           ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected signature `fn(_) -> impl Future<Output = &'static str>`
               found signature `fn(_) -> impl Future<Output = &'static str>`
 
diff --git a/tests/ui/async-await/in-trait/early-bound-1.rs b/tests/ui/async-await/in-trait/early-bound-1.rs
index 6b3b142014b..bc410cc2954 100644
--- a/tests/ui/async-await/in-trait/early-bound-1.rs
+++ b/tests/ui/async-await/in-trait/early-bound-1.rs
@@ -5,6 +5,7 @@
 #![allow(incomplete_features)]
 
 pub trait Foo {
+    #[allow(async_fn_in_trait)]
     async fn foo(&mut self);
 }
 
diff --git a/tests/ui/async-await/in-trait/early-bound-2.rs b/tests/ui/async-await/in-trait/early-bound-2.rs
index 270443229b0..1974b1d9f7a 100644
--- a/tests/ui/async-await/in-trait/early-bound-2.rs
+++ b/tests/ui/async-await/in-trait/early-bound-2.rs
@@ -5,6 +5,7 @@
 #![allow(incomplete_features)]
 
 pub trait Foo {
+    #[allow(async_fn_in_trait)]
     async fn foo(&mut self);
 }
 
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.rs b/tests/ui/async-await/in-trait/fn-not-async-err2.rs
index 78017429f73..e1703415dbd 100644
--- a/tests/ui/async-await/in-trait/fn-not-async-err2.rs
+++ b/tests/ui/async-await/in-trait/fn-not-async-err2.rs
@@ -11,7 +11,7 @@ trait MyTrait {
 
 impl MyTrait for i32 {
     fn foo(&self) -> impl Future<Output = i32> {
-        //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types
+        //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in `impl` method return types
         async { *self }
     }
 }
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.stderr b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr
index 37d9669c012..a7c897f786e 100644
--- a/tests/ui/async-await/in-trait/fn-not-async-err2.stderr
+++ b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `impl` method return types
   --> $DIR/fn-not-async-err2.rs:13:22
    |
 LL |     fn foo(&self) -> impl Future<Output = i32> {
diff --git a/tests/ui/async-await/in-trait/implied-bounds.rs b/tests/ui/async-await/in-trait/implied-bounds.rs
index 52bceb3cc5c..40eebad86c2 100644
--- a/tests/ui/async-await/in-trait/implied-bounds.rs
+++ b/tests/ui/async-await/in-trait/implied-bounds.rs
@@ -7,6 +7,8 @@
 trait TcpStack {
     type Connection<'a>: Sized where Self: 'a;
     fn connect<'a>(&'a self) -> Self::Connection<'a>;
+
+    #[allow(async_fn_in_trait)]
     async fn async_connect<'a>(&'a self) -> Self::Connection<'a>;
 }
 
diff --git a/tests/ui/async-await/in-trait/issue-102138.rs b/tests/ui/async-await/in-trait/issue-102138.rs
index f61b34ed99e..3d9cef0210f 100644
--- a/tests/ui/async-await/in-trait/issue-102138.rs
+++ b/tests/ui/async-await/in-trait/issue-102138.rs
@@ -10,6 +10,8 @@ async fn yield_now() {}
 
 trait AsyncIterator {
     type Item;
+
+    #[allow(async_fn_in_trait)]
     async fn next(&mut self) -> Option<Self::Item>;
 }
 
diff --git a/tests/ui/async-await/in-trait/issue-102219.rs b/tests/ui/async-await/in-trait/issue-102219.rs
index 9a35f6515cb..4a23e4be4f7 100644
--- a/tests/ui/async-await/in-trait/issue-102219.rs
+++ b/tests/ui/async-await/in-trait/issue-102219.rs
@@ -6,5 +6,6 @@
 #![allow(incomplete_features)]
 
 trait T {
+    #[allow(async_fn_in_trait)]
     async fn foo();
 }
diff --git a/tests/ui/async-await/in-trait/issue-102310.rs b/tests/ui/async-await/in-trait/issue-102310.rs
index 49c3e9feeb4..327d432a6a6 100644
--- a/tests/ui/async-await/in-trait/issue-102310.rs
+++ b/tests/ui/async-await/in-trait/issue-102310.rs
@@ -5,6 +5,7 @@
 #![allow(incomplete_features)]
 
 pub trait SpiDevice {
+    #[allow(async_fn_in_trait)]
     async fn transaction<F, R>(&mut self);
 }
 
diff --git a/tests/ui/async-await/in-trait/issue-104678.rs b/tests/ui/async-await/in-trait/issue-104678.rs
index e396df4e5d1..0a334707505 100644
--- a/tests/ui/async-await/in-trait/issue-104678.rs
+++ b/tests/ui/async-await/in-trait/issue-104678.rs
@@ -8,6 +8,7 @@ use std::future::Future;
 pub trait Pool {
     type Conn;
 
+    #[allow(async_fn_in_trait)]
     async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>(
         &'a self,
         callback: F,
diff --git a/tests/ui/async-await/in-trait/missing-feature-flag.stderr b/tests/ui/async-await/in-trait/missing-feature-flag.stderr
index f6aba1fcdbf..87a7e85bfbb 100644
--- a/tests/ui/async-await/in-trait/missing-feature-flag.stderr
+++ b/tests/ui/async-await/in-trait/missing-feature-flag.stderr
@@ -7,6 +7,12 @@ LL |     async fn foo(_: T) -> &'static str;
 LL | impl<T> MyTrait<T> for MyStruct {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
 
+error[E0308]: mismatched types
+  --> $DIR/missing-feature-flag.rs:16:42
+   |
+LL |     async fn foo(_: i32) -> &'static str {}
+   |                                          ^^ expected `&str`, found `()`
+
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
   --> $DIR/missing-feature-flag.rs:16:5
    |
@@ -18,12 +24,6 @@ LL |     async fn foo(_: i32) -> &'static str {}
    |
    = note: to specialize, `foo` in the parent `impl` must be marked `default`
 
-error[E0308]: mismatched types
-  --> $DIR/missing-feature-flag.rs:16:42
-   |
-LL |     async fn foo(_: i32) -> &'static str {}
-   |                                          ^^ expected `&str`, found `()`
-
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0046, E0308, E0520.
diff --git a/tests/ui/async-await/in-trait/nested-rpit.rs b/tests/ui/async-await/in-trait/nested-rpit.rs
index 9cdc23bbc78..8c43e1b07e2 100644
--- a/tests/ui/async-await/in-trait/nested-rpit.rs
+++ b/tests/ui/async-await/in-trait/nested-rpit.rs
@@ -9,6 +9,7 @@ use std::future::Future;
 use std::marker::PhantomData;
 
 trait Lockable<K, V> {
+    #[allow(async_fn_in_trait)]
     async fn lock_all_entries(&self) -> impl Future<Output = Guard<'_>>;
 }
 
diff --git a/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs b/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs
index c4008f2b7e7..f8fe0d1bde8 100644
--- a/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs
+++ b/tests/ui/async-await/in-trait/normalize-opaque-with-bound-vars.rs
@@ -11,6 +11,7 @@
 pub struct SharedState {}
 
 pub trait State {
+    #[allow(async_fn_in_trait)]
     async fn execute(self, shared_state: &SharedState);
 }
 
diff --git a/tests/ui/async-await/in-trait/warn.rs b/tests/ui/async-await/in-trait/warn.rs
new file mode 100644
index 00000000000..4f981c31f5c
--- /dev/null
+++ b/tests/ui/async-await/in-trait/warn.rs
@@ -0,0 +1,23 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![deny(async_fn_in_trait)]
+
+pub trait Foo {
+    async fn not_send();
+    //~^ ERROR  use of `async fn` in public traits is discouraged
+}
+
+mod private {
+    pub trait FooUnreachable {
+        async fn not_send();
+        // No warning
+    }
+}
+
+pub(crate) trait FooCrate {
+    async fn not_send();
+    // No warning
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/in-trait/warn.stderr b/tests/ui/async-await/in-trait/warn.stderr
new file mode 100644
index 00000000000..eac41a6e924
--- /dev/null
+++ b/tests/ui/async-await/in-trait/warn.stderr
@@ -0,0 +1,20 @@
+error: use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified
+  --> $DIR/warn.rs:7:5
+   |
+LL |     async fn not_send();
+   |     ^^^^^
+   |
+   = note: you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future`
+note: the lint level is defined here
+  --> $DIR/warn.rs:4:9
+   |
+LL | #![deny(async_fn_in_trait)]
+   |         ^^^^^^^^^^^^^^^^^
+help: you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`
+   |
+LL -     async fn not_send();
+LL +     fn not_send() -> impl std::future::Future<Output = ()> + Send;
+   |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-108572.fixed b/tests/ui/async-await/issue-108572.fixed
new file mode 100644
index 00000000000..8f0133d97b5
--- /dev/null
+++ b/tests/ui/async-await/issue-108572.fixed
@@ -0,0 +1,16 @@
+// edition: 2021
+// run-rustfix
+#![allow(unused_must_use, dead_code)]
+
+use std::future::Future;
+fn foo() -> impl Future<Output=()> {
+    async { }
+}
+
+fn bar(cx: &mut std::task::Context<'_>) {
+    let fut = foo();
+    let mut pinned = std::pin::pin!(fut);
+    pinned.as_mut().poll(cx);
+    //~^ ERROR no method named `poll` found for opaque type `impl Future<Output = ()>` in the current scope [E0599]
+}
+fn main() {}
diff --git a/tests/ui/async-await/issue-108572.rs b/tests/ui/async-await/issue-108572.rs
index efcb8b8ebab..3596580763c 100644
--- a/tests/ui/async-await/issue-108572.rs
+++ b/tests/ui/async-await/issue-108572.rs
@@ -1,12 +1,15 @@
 // edition: 2021
+// run-rustfix
+#![allow(unused_must_use, dead_code)]
 
 use std::future::Future;
 fn foo() -> impl Future<Output=()> {
     async { }
 }
 
-fn main() {
+fn bar(cx: &mut std::task::Context<'_>) {
     let fut = foo();
-    fut.poll();
+    fut.poll(cx);
     //~^ ERROR no method named `poll` found for opaque type `impl Future<Output = ()>` in the current scope [E0599]
 }
+fn main() {}
diff --git a/tests/ui/async-await/issue-108572.stderr b/tests/ui/async-await/issue-108572.stderr
index 0dbcf4d660a..588669092b0 100644
--- a/tests/ui/async-await/issue-108572.stderr
+++ b/tests/ui/async-await/issue-108572.stderr
@@ -1,11 +1,16 @@
 error[E0599]: no method named `poll` found for opaque type `impl Future<Output = ()>` in the current scope
-  --> $DIR/issue-108572.rs:10:9
+  --> $DIR/issue-108572.rs:12:9
    |
-LL |     fut.poll();
+LL |     fut.poll(cx);
    |         ^^^^ method not found in `impl Future<Output = ()>`
    |
    = help: method `poll` found on `Pin<&mut impl Future<Output = ()>>`, see documentation for `std::pin::Pin`
    = help: self type must be pinned to call `Future::poll`, see https://rust-lang.github.io/async-book/04_pinning/01_chapter.html#pinning-in-practice
+help: consider pinning the expression
+   |
+LL ~     let mut pinned = std::pin::pin!(fut);
+LL ~     pinned.as_mut().poll(cx);
+   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/async-await/issue-64130-3-other.stderr b/tests/ui/async-await/issue-64130-3-other.stderr
index 573da1034c5..4bbb7731b11 100644
--- a/tests/ui/async-await/issue-64130-3-other.stderr
+++ b/tests/ui/async-await/issue-64130-3-other.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future<Output
   --> $DIR/issue-64130-3-other.rs:25:12
    |
 LL | async fn bar() {
-   |                - within this `impl Future<Output = ()>`
+   | -------------- within this `impl Future<Output = ()>`
 ...
 LL |     is_qux(bar());
    |            ^^^^^ within `impl Future<Output = ()>`, the trait `Qux` is not implemented for `Foo`
diff --git a/tests/ui/async-await/issues/issue-67893.stderr b/tests/ui/async-await/issues/issue-67893.stderr
index f36269e8f36..3d6d1fb5c09 100644
--- a/tests/ui/async-await/issues/issue-67893.stderr
+++ b/tests/ui/async-await/issues/issue-67893.stderr
@@ -6,10 +6,10 @@ LL |     g(issue_67893::run())
    |     |
    |     required by a bound introduced by this call
    |
-  ::: $DIR/auxiliary/issue_67893.rs:9:20
+  ::: $DIR/auxiliary/issue_67893.rs:9:1
    |
 LL | pub async fn run() {
-   |                    - within this `impl Future<Output = ()>`
+   | ------------------ within this `impl Future<Output = ()>`
    |
    = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
    = note: required because it captures the following types: `Arc<Mutex<()>>`, `MutexGuard<'_, ()>`, `impl Future<Output = ()>`
diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
index f789ad2a05c..9442609e805 100644
--- a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
+++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
@@ -1,17 +1,17 @@
 error[E0733]: recursion in an `async fn` requires boxing
-  --> $DIR/mutually-recursive-async-impl-trait-type.rs:5:18
+  --> $DIR/mutually-recursive-async-impl-trait-type.rs:5:1
    |
 LL | async fn rec_1() {
-   |                  ^ recursive `async fn`
+   | ^^^^^^^^^^^^^^^^ recursive `async fn`
    |
    = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
    = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
 
 error[E0733]: recursion in an `async fn` requires boxing
-  --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18
+  --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:1
    |
 LL | async fn rec_2() {
-   |                  ^ recursive `async fn`
+   | ^^^^^^^^^^^^^^^^ recursive `async fn`
    |
    = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
    = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
diff --git a/tests/ui/async-await/partial-drop-partial-reinit.stderr b/tests/ui/async-await/partial-drop-partial-reinit.stderr
index 85e1830c78e..d115c1b1cc4 100644
--- a/tests/ui/async-await/partial-drop-partial-reinit.stderr
+++ b/tests/ui/async-await/partial-drop-partial-reinit.stderr
@@ -7,7 +7,7 @@ LL |     gimme_send(foo());
    |     required by a bound introduced by this call
 ...
 LL | async fn foo() {
-   |                - within this `impl Future<Output = ()>`
+   | -------------- within this `impl Future<Output = ()>`
    |
    = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend`
    = note: required because it appears within the type `(NotSend,)`
diff --git a/tests/ui/async-await/pin-needed-to-poll.stderr b/tests/ui/async-await/pin-needed-to-poll.stderr
index b1f4a73aafe..964709daeda 100644
--- a/tests/ui/async-await/pin-needed-to-poll.stderr
+++ b/tests/ui/async-await/pin-needed-to-poll.stderr
@@ -6,14 +6,12 @@ LL | struct Sleep;
 ...
 LL |         self.sleep.poll(cx)
    |                    ^^^^ method not found in `Sleep`
-  --> $SRC_DIR/core/src/future/future.rs:LL:COL
    |
-   = note: the method is available for `Pin<&mut Sleep>` here
+help: consider pinning the expression
    |
-help: consider wrapping the receiver expression with the appropriate type
+LL ~         let mut pinned = std::pin::pin!(self.sleep);
+LL ~         pinned.as_mut().poll(cx)
    |
-LL |         Pin::new(&mut self.sleep).poll(cx)
-   |         +++++++++++++           +
 
 error: aborting due to previous error
 
diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.stderr b/tests/ui/async-await/recursive-async-impl-trait-type.stderr
index 63f64f44557..64917329c49 100644
--- a/tests/ui/async-await/recursive-async-impl-trait-type.stderr
+++ b/tests/ui/async-await/recursive-async-impl-trait-type.stderr
@@ -1,8 +1,8 @@
 error[E0733]: recursion in an `async fn` requires boxing
-  --> $DIR/recursive-async-impl-trait-type.rs:5:40
+  --> $DIR/recursive-async-impl-trait-type.rs:5:1
    |
 LL | async fn recursive_async_function() -> () {
-   |                                        ^^ recursive `async fn`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn`
    |
    = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
    = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
index 969094a2c58..98e3cbd0d7f 100644
--- a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
+++ b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
@@ -44,6 +44,7 @@ note: the lifetime requirement is introduced here
    |
 LL |     F: Future + Send + 'static,
    |                 ^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/tests/ui/auto-traits/pre-cfg.rs b/tests/ui/auto-traits/pre-cfg.rs
new file mode 100644
index 00000000000..e6e840dcbab
--- /dev/null
+++ b/tests/ui/auto-traits/pre-cfg.rs
@@ -0,0 +1,8 @@
+// check-pass
+
+#[cfg(FALSE)]
+auto trait Foo {}
+//~^ WARN `auto` traits are unstable
+//~| WARN unstable syntax can change at any point in the future, causing a hard error!
+
+fn main() {}
diff --git a/tests/ui/auto-traits/pre-cfg.stderr b/tests/ui/auto-traits/pre-cfg.stderr
new file mode 100644
index 00000000000..6efa05b4326
--- /dev/null
+++ b/tests/ui/auto-traits/pre-cfg.stderr
@@ -0,0 +1,13 @@
+warning: `auto` traits are unstable
+  --> $DIR/pre-cfg.rs:4:1
+   |
+LL | auto trait Foo {}
+   | ^^^^
+   |
+   = note: see issue #13231 <https://github.com/rust-lang/rust/issues/13231> for more information
+   = help: add `#![feature(auto_traits)]` to the crate attributes to enable
+   = warning: unstable syntax can change at any point in the future, causing a hard error!
+   = note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/block-result/block-must-not-have-result-res.stderr b/tests/ui/block-result/block-must-not-have-result-res.stderr
index 0080d06dd20..b7427462bcb 100644
--- a/tests/ui/block-result/block-must-not-have-result-res.stderr
+++ b/tests/ui/block-result/block-must-not-have-result-res.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/block-must-not-have-result-res.rs:5:9
    |
 LL |     fn drop(&mut self) {
-   |                        - expected `()` because of default return type
+   |                       - expected `()` because of default return type
 LL |         true
    |         ^^^^ expected `()`, found `bool`
 
diff --git a/tests/ui/block-result/issue-20862.stderr b/tests/ui/block-result/issue-20862.stderr
index 17b524fe311..1df3a683620 100644
--- a/tests/ui/block-result/issue-20862.stderr
+++ b/tests/ui/block-result/issue-20862.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-20862.rs:2:5
    |
 LL | fn foo(x: i32) {
-   |                - help: a return type might be missing here: `-> _`
+   |               - help: a return type might be missing here: `-> _`
 LL |     |y| x + y
    |     ^^^^^^^^^ expected `()`, found closure
    |
diff --git a/tests/ui/block-result/issue-22645.stderr b/tests/ui/block-result/issue-22645.stderr
index 677b40aaa9d..1064848f513 100644
--- a/tests/ui/block-result/issue-22645.stderr
+++ b/tests/ui/block-result/issue-22645.stderr
@@ -17,7 +17,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-22645.rs:15:3
    |
 LL | fn main() {
-   |           - expected `()` because of default return type
+   |          - expected `()` because of default return type
 LL |   let b = Bob + 3.5;
 LL |   b + 3
    |   ^^^^^ expected `()`, found `Bob`
diff --git a/tests/ui/block-result/issue-5500.stderr b/tests/ui/block-result/issue-5500.stderr
index 8cd4bd65871..417991e9e0b 100644
--- a/tests/ui/block-result/issue-5500.stderr
+++ b/tests/ui/block-result/issue-5500.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-5500.rs:2:5
    |
 LL | fn main() {
-   |           - expected `()` because of default return type
+   |          - expected `()` because of default return type
 LL |     &panic!()
    |     ^^^^^^^^^ expected `()`, found `&_`
    |
diff --git a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
index 930fea9158d..7ebea3c03d3 100644
--- a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
+++ b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
@@ -53,6 +53,7 @@ note: ...does not necessarily outlive the lifetime `'c` as defined here
    |
 LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
    |                        ^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration
   --> $DIR/regions-bound-missing-bound-in-impl.rs:42:20
diff --git a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr
index 9ce4710d69b..75df314e0ba 100644
--- a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr
+++ b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr
@@ -25,6 +25,7 @@ LL | #![cfg_attr(foo, crate_type="bin")]
    |
    = 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 #91632 <https://github.com/rust-lang/rust/issues/91632>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: `crate_name` within an `#![cfg_attr] attribute is deprecated`
   --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:9:18
@@ -34,6 +35,7 @@ LL | #![cfg_attr(foo, crate_name="bar")]
    |
    = 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 #91632 <https://github.com/rust-lang/rust/issues/91632>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/closures/add_semicolon_non_block_closure.stderr b/tests/ui/closures/add_semicolon_non_block_closure.stderr
index ed829fc98f8..6f9c309edda 100644
--- a/tests/ui/closures/add_semicolon_non_block_closure.stderr
+++ b/tests/ui/closures/add_semicolon_non_block_closure.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/add_semicolon_non_block_closure.rs:8:12
    |
 LL | fn main() {
-   |           - expected `()` because of default return type
+   |          - expected `()` because of default return type
 LL |     foo(|| bar())
    |            ^^^^^ expected `()`, found `i32`
    |
diff --git a/tests/ui/closures/binder/implicit-return.stderr b/tests/ui/closures/binder/implicit-return.stderr
index 5bfb9711334..35db34ce21d 100644
--- a/tests/ui/closures/binder/implicit-return.stderr
+++ b/tests/ui/closures/binder/implicit-return.stderr
@@ -1,8 +1,8 @@
 error: implicit types in closure signatures are forbidden when `for<...>` is present
-  --> $DIR/implicit-return.rs:4:34
+  --> $DIR/implicit-return.rs:4:33
    |
 LL |     let _f = for<'a> |_: &'a ()| {};
-   |              -------             ^
+   |              -------            ^
    |              |
    |              `for<...>` is here
 
diff --git a/tests/ui/closures/binder/implicit-stuff.stderr b/tests/ui/closures/binder/implicit-stuff.stderr
index 779a08a44e5..cec2a60ba28 100644
--- a/tests/ui/closures/binder/implicit-stuff.stderr
+++ b/tests/ui/closures/binder/implicit-stuff.stderr
@@ -41,10 +41,10 @@ LL |     let _ = for<'a> |x: &'a ()| -> &() { x };
    |                                    ^ explicit lifetime name needed here
 
 error: implicit types in closure signatures are forbidden when `for<...>` is present
-  --> $DIR/implicit-stuff.rs:5:22
+  --> $DIR/implicit-stuff.rs:5:21
    |
 LL |     let _ = for<> || {};
-   |             -----    ^
+   |             -----   ^
    |             |
    |             `for<...>` is here
 
diff --git a/tests/ui/codegen/issue-79865-llvm-miscompile.rs b/tests/ui/codegen/issue-79865-llvm-miscompile.rs
index b77f09f8e9a..6f994a5cb74 100644
--- a/tests/ui/codegen/issue-79865-llvm-miscompile.rs
+++ b/tests/ui/codegen/issue-79865-llvm-miscompile.rs
@@ -4,7 +4,7 @@
 
 // Regression test for issue #79865.
 // The assertion will fail when compiled with Rust 1.56..=1.59
-// due to a LLVM miscompilation.
+// due to an LLVM miscompilation.
 
 use std::arch::x86_64::*;
 
diff --git a/tests/ui/codemap_tests/tab.stderr b/tests/ui/codemap_tests/tab.stderr
index c3f19d20d39..d2de7486557 100644
--- a/tests/ui/codemap_tests/tab.stderr
+++ b/tests/ui/codemap_tests/tab.stderr
@@ -8,7 +8,7 @@ error[E0308]: mismatched types
   --> $DIR/tab.rs:8:2
    |
 LL | fn foo() {
-   |          - help: try adding a return type: `-> &'static str`
+   |         - help: try adding a return type: `-> &'static str`
 LL |     "bar            boo"
    |     ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&str`
 
diff --git a/tests/ui/compare-method/bad-self-type.stderr b/tests/ui/compare-method/bad-self-type.stderr
index f632a53f264..a87b713c2b4 100644
--- a/tests/ui/compare-method/bad-self-type.stderr
+++ b/tests/ui/compare-method/bad-self-type.stderr
@@ -28,10 +28,10 @@ LL |     fn foo(self);
               found signature `fn(Box<MyFuture>)`
 
 error[E0053]: method `bar` has an incompatible type for trait
-  --> $DIR/bad-self-type.rs:24:18
+  --> $DIR/bad-self-type.rs:24:17
    |
 LL |     fn bar(self) {}
-   |                  ^ expected `Option<()>`, found `()`
+   |                 ^ expected `Option<()>`, found `()`
    |
 note: type in trait
   --> $DIR/bad-self-type.rs:18:21
diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
index d5b4349c00f..12557ff6360 100644
--- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
+++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
@@ -74,6 +74,7 @@ LL |         #[cfg(feature = $expr)]
 LL | generate_s10!(concat!("nonexistent"));
    | ------------------------------------- in this macro invocation
    |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
    = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 11 previous errors
diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr
index d7e5e50cba8..6d5cd45479e 100644
--- a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr
+++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr
@@ -39,6 +39,7 @@ note: associated constant defined here
    |
 LL |     const MODE: Mode;
    |     ^^^^^^^^^^^^^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/const-generics/issues/issue-74950.min.stderr b/tests/ui/const-generics/issues/issue-74950.min.stderr
index a5dbe10b78a..54ef1ea1e94 100644
--- a/tests/ui/const-generics/issues/issue-74950.min.stderr
+++ b/tests/ui/const-generics/issues/issue-74950.min.stderr
@@ -15,6 +15,7 @@ LL | struct Outer<const I: Inner>;
    |
    = note: the only supported types are integers, `bool` and `char`
    = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:20:23
@@ -24,6 +25,7 @@ LL | struct Outer<const I: Inner>;
    |
    = note: the only supported types are integers, `bool` and `char`
    = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:20:23
@@ -33,6 +35,7 @@ LL | struct Outer<const I: Inner>;
    |
    = note: the only supported types are integers, `bool` and `char`
    = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:20:23
@@ -42,6 +45,7 @@ LL | struct Outer<const I: Inner>;
    |
    = note: the only supported types are integers, `bool` and `char`
    = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr
index 51ef354e3ed..61d055e8084 100644
--- a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr
+++ b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `A<_>: Bar<_>` is not satisfied
 LL |     let _ = A;
    |             ^ the trait `Bar<_>` is not implemented for `A<_>`
    |
-   = help: the trait `Bar<N>` is implemented for `A<7>`
+   = help: the trait `Bar<_>` is implemented for `A<7>`
 note: required by a bound in `A`
   --> $DIR/unused-substs-1.rs:9:11
    |
diff --git a/tests/ui/consts/const-adt-align-mismatch.rs b/tests/ui/consts/const-adt-align-mismatch.rs
index bd51bc9f215..89b3a9b744b 100644
--- a/tests/ui/consts/const-adt-align-mismatch.rs
+++ b/tests/ui/consts/const-adt-align-mismatch.rs
@@ -12,7 +12,7 @@ enum Foo {
 }
 
 // NOTE(eddyb) Don't make this a const, needs to be a static
-// so it is always instantiated as a LLVM constant value.
+// so it is always instantiated as an LLVM constant value.
 static FOO: Foo = Foo::C;
 
 fn main() {
diff --git a/tests/ui/consts/const-err-late.stderr b/tests/ui/consts/const-err-late.stderr
index 85bc56baed8..35c3d000117 100644
--- a/tests/ui/consts/const-err-late.stderr
+++ b/tests/ui/consts/const-err-late.stderr
@@ -27,6 +27,8 @@ note: erroneous constant encountered
    |
 LL |     black_box((S::<i32>::FOO, S::<u32>::FOO));
    |                ^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/const-eval/issue-44578.stderr b/tests/ui/consts/const-eval/issue-44578.stderr
index c7aaee94271..eea42c8ce45 100644
--- a/tests/ui/consts/const-eval/issue-44578.stderr
+++ b/tests/ui/consts/const-eval/issue-44578.stderr
@@ -24,6 +24,7 @@ note: erroneous constant encountered
 LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = 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 previous error
diff --git a/tests/ui/consts/const-eval/nrvo.rs b/tests/ui/consts/const-eval/nrvo.rs
index 1d2c6acc06c..22da96a3fc1 100644
--- a/tests/ui/consts/const-eval/nrvo.rs
+++ b/tests/ui/consts/const-eval/nrvo.rs
@@ -1,7 +1,8 @@
 // run-pass
 
 // When the NRVO is applied, the return place (`_0`) gets treated like a normal local. For example,
-// its address may be taken and it may be written to indirectly. Ensure that MIRI can handle this.
+// its address may be taken and it may be written to indirectly. Ensure that the const-eval
+// interpreter can handle this.
 
 #![feature(const_mut_refs)]
 
diff --git a/tests/ui/consts/const-eval/panic-assoc-never-type.stderr b/tests/ui/consts/const-eval/panic-assoc-never-type.stderr
index 4706497dbc4..50660664f87 100644
--- a/tests/ui/consts/const-eval/panic-assoc-never-type.stderr
+++ b/tests/ui/consts/const-eval/panic-assoc-never-type.stderr
@@ -17,6 +17,8 @@ note: erroneous constant encountered
    |
 LL |     let _ = PrintName::VOID;
    |             ^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr
index 40fc4a876e9..8eee392d15c 100644
--- a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr
@@ -40,6 +40,7 @@ help: the constant being evaluated
    |
 LL | const Y: u32 = simple_loop(35);
    | ^^^^^^^^^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: constant evaluation is taking a long time
   --> $DIR/ctfe-simple-loop.rs:9:5
diff --git a/tests/ui/consts/const-eval/union-const-eval-field.rs b/tests/ui/consts/const-eval/union-const-eval-field.rs
index a94fcbbfa56..c9799989ea8 100644
--- a/tests/ui/consts/const-eval/union-const-eval-field.rs
+++ b/tests/ui/consts/const-eval/union-const-eval-field.rs
@@ -1,5 +1,3 @@
-// only-x86_64
-
 type Field1 = i32;
 type Field2 = f32;
 type Field3 = i64;
diff --git a/tests/ui/consts/const-eval/union-const-eval-field.stderr b/tests/ui/consts/const-eval/union-const-eval-field.stderr
index ce260300fc8..b299208ae81 100644
--- a/tests/ui/consts/const-eval/union-const-eval-field.stderr
+++ b/tests/ui/consts/const-eval/union-const-eval-field.stderr
@@ -1,20 +1,22 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/union-const-eval-field.rs:28:37
+  --> $DIR/union-const-eval-field.rs:26:37
    |
 LL |     const FIELD3: Field3 = unsafe { UNION.field3 };
    |                                     ^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
 
 note: erroneous constant encountered
-  --> $DIR/union-const-eval-field.rs:31:5
+  --> $DIR/union-const-eval-field.rs:29:5
    |
 LL |     FIELD3
    |     ^^^^^^
 
 note: erroneous constant encountered
-  --> $DIR/union-const-eval-field.rs:31:5
+  --> $DIR/union-const-eval-field.rs:29:5
    |
 LL |     FIELD3
    |     ^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 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 dc6b9a33197..df772740ab1 100644
--- a/tests/ui/consts/const_in_pattern/reject_non_structural.rs
+++ b/tests/ui/consts/const_in_pattern/reject_non_structural.rs
@@ -1,3 +1,5 @@
+// compile-flags: -Zdeduplicate-diagnostics=yes
+
 // This test of structural match checking enumerates the different kinds of
 // const definitions, collecting cases where the const pattern is rejected.
 //
@@ -78,9 +80,6 @@ fn main() {
     //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
     //~| NOTE the traits must be derived
     //~| NOTE StructuralEq.html for details
-    //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
-    //~| NOTE the traits must be derived
-    //~| NOTE StructuralEq.html for details
 
     trait Trait: Sized { const ASSOC: Option<Self>; }
     impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
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 b6e439f2139..72bb0aeafa4 100644
--- a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr
+++ b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr
@@ -1,5 +1,5 @@
 error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/reject_non_structural.rs:40:36
+  --> $DIR/reject_non_structural.rs:42:36
    |
 LL |     match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
    |                                    ^^^^
@@ -8,7 +8,7 @@ LL |     match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/reject_non_structural.rs:46:28
+  --> $DIR/reject_non_structural.rs:48:28
    |
 LL |     match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
    |                            ^^^^^
@@ -17,7 +17,7 @@ LL |     match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/reject_non_structural.rs:53:27
+  --> $DIR/reject_non_structural.rs:55:27
    |
 LL |     match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
    |                           ^^^^^^^^
@@ -26,7 +26,7 @@ LL |     match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops")
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/reject_non_structural.rs:59:36
+  --> $DIR/reject_non_structural.rs:61:36
    |
 LL |     match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
    |                                    ^^^^^
@@ -35,7 +35,7 @@ LL |     match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoop
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/reject_non_structural.rs:65:28
+  --> $DIR/reject_non_structural.rs:67:28
    |
 LL |     match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), };
    |                            ^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL |     match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => p
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/reject_non_structural.rs:71:36
+  --> $DIR/reject_non_structural.rs:73:36
    |
 LL |     match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
    |                                    ^^^^^
@@ -53,7 +53,7 @@ LL |     match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoop
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/reject_non_structural.rs:77:33
+  --> $DIR/reject_non_structural.rs:79:33
    |
 LL |     match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
    |                                 ^^^^^^
@@ -62,16 +62,7 @@ LL |     match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/reject_non_structural.rs:77:33
-   |
-LL |     match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
-   |                                 ^^^^^^
-   |
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
-
-error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/reject_non_structural.rs:87:28
+  --> $DIR/reject_non_structural.rs:86:28
    |
 LL |     match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
    |                            ^^^^^^^^^^^^^^^
@@ -80,7 +71,7 @@ LL |     match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => p
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/reject_non_structural.rs:93:28
+  --> $DIR/reject_non_structural.rs:92:28
    |
 LL |     match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
    |                            ^^^^^
@@ -89,7 +80,7 @@ LL |     match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/reject_non_structural.rs:99:29
+  --> $DIR/reject_non_structural.rs:98:29
    |
 LL |     match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
    |                             ^^^^^^^
@@ -99,10 +90,10 @@ LL |     match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops")
    = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 note: the lint level is defined here
-  --> $DIR/reject_non_structural.rs:12:9
+  --> $DIR/reject_non_structural.rs:14:9
    |
 LL | #![warn(indirect_structural_match)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 10 previous errors; 1 warning emitted
+error: aborting due to 9 previous errors; 1 warning emitted
 
diff --git a/tests/ui/consts/enum-discr-type-err.stderr b/tests/ui/consts/enum-discr-type-err.stderr
index 2f97582bea8..9a09d6a96f1 100644
--- a/tests/ui/consts/enum-discr-type-err.stderr
+++ b/tests/ui/consts/enum-discr-type-err.stderr
@@ -24,6 +24,7 @@ LL | |     B = T,
 LL | | }
    | |_- in this macro invocation
    |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr
index 658a0b7b2a0..3d82837d530 100644
--- a/tests/ui/consts/fn_trait_refs.stderr
+++ b/tests/ui/consts/fn_trait_refs.stderr
@@ -21,6 +21,8 @@ error: ~const can only be applied to `#[const_trait]` traits
    |
 LL |     T: ~const Fn<()> + ~const Destruct,
    |               ^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: ~const can only be applied to `#[const_trait]` traits
   --> $DIR/fn_trait_refs.rs:22:15
@@ -33,6 +35,8 @@ error: ~const can only be applied to `#[const_trait]` traits
    |
 LL |     T: ~const FnMut<()> + ~const Destruct,
    |               ^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: ~const can only be applied to `#[const_trait]` traits
   --> $DIR/fn_trait_refs.rs:29:15
@@ -45,6 +49,8 @@ error: ~const can only be applied to `#[const_trait]` traits
    |
 LL |     T: ~const FnOnce<()>,
    |               ^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: ~const can only be applied to `#[const_trait]` traits
   --> $DIR/fn_trait_refs.rs:36:15
@@ -57,6 +63,8 @@ error: ~const can only be applied to `#[const_trait]` traits
    |
 LL |     T: ~const Fn<()> + ~const Destruct,
    |               ^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: ~const can only be applied to `#[const_trait]` traits
   --> $DIR/fn_trait_refs.rs:50:15
@@ -69,6 +77,8 @@ error: ~const can only be applied to `#[const_trait]` traits
    |
 LL |     T: ~const FnMut<()> + ~const Destruct,
    |               ^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 12 previous errors
 
diff --git a/tests/ui/consts/invalid-union.32bit.stderr b/tests/ui/consts/invalid-union.32bit.stderr
index b6cf060e5ae..0c57751cbfa 100644
--- a/tests/ui/consts/invalid-union.32bit.stderr
+++ b/tests/ui/consts/invalid-union.32bit.stderr
@@ -20,6 +20,8 @@ note: erroneous constant encountered
    |
 LL |     let _: &'static _ = &C;
    |                         ^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/invalid-union.64bit.stderr b/tests/ui/consts/invalid-union.64bit.stderr
index e3a3ef62c4a..6c4d5882158 100644
--- a/tests/ui/consts/invalid-union.64bit.stderr
+++ b/tests/ui/consts/invalid-union.64bit.stderr
@@ -20,6 +20,8 @@ note: erroneous constant encountered
    |
 LL |     let _: &'static _ = &C;
    |                         ^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/issue-102117.stderr b/tests/ui/consts/issue-102117.stderr
index f42bcf90fb7..a297916b30f 100644
--- a/tests/ui/consts/issue-102117.stderr
+++ b/tests/ui/consts/issue-102117.stderr
@@ -15,6 +15,7 @@ error[E0310]: the parameter type `T` may not live long enough
 LL |                 type_id: TypeId::of::<T>(),
    |                          ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider adding an explicit lifetime bound...
    |
 LL |     pub fn new<T: 'static>() -> &'static Self {
diff --git a/tests/ui/consts/issue-17718-const-bad-values.stderr b/tests/ui/consts/issue-17718-const-bad-values.stderr
index ce60aaa0797..405c2195dec 100644
--- a/tests/ui/consts/issue-17718-const-bad-values.stderr
+++ b/tests/ui/consts/issue-17718-const-bad-values.stderr
@@ -19,6 +19,7 @@ LL | const C2: &'static mut usize = unsafe { &mut S };
    |                                              ^
    |
    = help: consider extracting the value of the `static` to a `const`, and referring to that
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/miri_unleashed/assoc_const.stderr b/tests/ui/consts/miri_unleashed/assoc_const.stderr
index 274b1de7e7d..b129aef3452 100644
--- a/tests/ui/consts/miri_unleashed/assoc_const.stderr
+++ b/tests/ui/consts/miri_unleashed/assoc_const.stderr
@@ -24,6 +24,8 @@ note: erroneous constant encountered
    |
 LL |     let y = <String as Bar<Vec<u32>, String>>::F;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: skipping const checks
    |
diff --git a/tests/ui/consts/miri_unleashed/assoc_const_2.stderr b/tests/ui/consts/miri_unleashed/assoc_const_2.stderr
index c8e4cab4e71..46408f6748d 100644
--- a/tests/ui/consts/miri_unleashed/assoc_const_2.stderr
+++ b/tests/ui/consts/miri_unleashed/assoc_const_2.stderr
@@ -15,6 +15,8 @@ note: erroneous constant encountered
    |
 LL |     let y = <String as Bar<String>>::F;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/uninhabited-const-issue-61744.stderr b/tests/ui/consts/uninhabited-const-issue-61744.stderr
index f48e6c4ce51..c92824a0d1a 100644
--- a/tests/ui/consts/uninhabited-const-issue-61744.stderr
+++ b/tests/ui/consts/uninhabited-const-issue-61744.stderr
@@ -656,6 +656,8 @@ note: erroneous constant encountered
    |
 LL |     dbg!(i32::CONSTANT);
    |          ^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/crate-loading/invalid-rlib.rs b/tests/ui/crate-loading/invalid-rlib.rs
index aea861e3261..0997bee19bb 100644
--- a/tests/ui/crate-loading/invalid-rlib.rs
+++ b/tests/ui/crate-loading/invalid-rlib.rs
@@ -8,3 +8,4 @@ use ::foo; //~ ERROR invalid metadata files for crate `foo`
 //~| NOTE failed to mmap file
 //~^^ ERROR invalid metadata files for crate `foo`
 //~| NOTE failed to mmap file
+//~| NOTE duplicate diagnostic
diff --git a/tests/ui/crate-loading/invalid-rlib.stderr b/tests/ui/crate-loading/invalid-rlib.stderr
index 3c0d23bf7b4..63bb1b95cbb 100644
--- a/tests/ui/crate-loading/invalid-rlib.stderr
+++ b/tests/ui/crate-loading/invalid-rlib.stderr
@@ -13,6 +13,7 @@ LL | use ::foo;
    |       ^^^
    |
    = note: failed to mmap file 'auxiliary/libfoo.rlib'
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/debuginfo/sroa-fragment-debuginfo.rs b/tests/ui/debuginfo/sroa-fragment-debuginfo.rs
index 9c3c359e395..fc3bbb88efe 100644
--- a/tests/ui/debuginfo/sroa-fragment-debuginfo.rs
+++ b/tests/ui/debuginfo/sroa-fragment-debuginfo.rs
@@ -1,4 +1,4 @@
-// Verify that we do not trigger a LLVM assertion by creating zero-sized DWARF fragments.
+// Verify that we do not trigger an LLVM assertion by creating zero-sized DWARF fragments.
 //
 // build-pass
 // compile-flags: -g -Zmir-opt-level=0 -Zmir-enable-passes=+ScalarReplacementOfAggregates
diff --git a/tests/ui/deduplicate-diagnostics.duplicate.stderr b/tests/ui/deduplicate-diagnostics.duplicate.stderr
index cd4700c7a7c..0544b993278 100644
--- a/tests/ui/deduplicate-diagnostics.duplicate.stderr
+++ b/tests/ui/deduplicate-diagnostics.duplicate.stderr
@@ -15,12 +15,16 @@ error: cannot find derive macro `Unresolved` in this scope
    |
 LL | #[derive(Unresolved)]
    |          ^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0452]: malformed lint attribute input
   --> $DIR/deduplicate-diagnostics.rs:8:8
    |
 LL | #[deny("literal")]
    |        ^^^^^^^^^ bad attribute argument
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr
index 8b2b480d195..383212ad9b4 100644
--- a/tests/ui/deprecation/deprecation-sanity.stderr
+++ b/tests/ui/deprecation/deprecation-sanity.stderr
@@ -16,25 +16,25 @@ error[E0541]: unknown meta item 'reason'
 LL |     #[deprecated(since = "a", note = "a", reason)]
    |                                           ^^^^^^ expected one of `since`, `note`
 
-error[E0551]: incorrect meta item
+error[E0539]: incorrect meta item
   --> $DIR/deprecation-sanity.rs:7:31
    |
 LL |     #[deprecated(since = "a", note)]
    |                               ^^^^
 
-error[E0551]: incorrect meta item
+error[E0539]: incorrect meta item
   --> $DIR/deprecation-sanity.rs:10:18
    |
 LL |     #[deprecated(since, note = "a")]
    |                  ^^^^^
 
-error[E0551]: incorrect meta item
+error[E0539]: incorrect meta item
   --> $DIR/deprecation-sanity.rs:13:31
    |
 LL |     #[deprecated(since = "a", note(b))]
    |                               ^^^^^^^
 
-error[E0551]: incorrect meta item
+error[E0539]: incorrect meta item
   --> $DIR/deprecation-sanity.rs:16:18
    |
 LL |     #[deprecated(since(b), note = "a")]
@@ -70,5 +70,5 @@ LL | #[deprecated = "hello"]
 
 error: aborting due to 10 previous errors
 
-Some errors have detailed explanations: E0538, E0541, E0551, E0565.
+Some errors have detailed explanations: E0538, E0539, E0541, E0565.
 For more information about an error, try `rustc --explain E0538`.
diff --git a/tests/ui/derives/deriving-bounds.stderr b/tests/ui/derives/deriving-bounds.stderr
index 74ca37287d2..4461652eb02 100644
--- a/tests/ui/derives/deriving-bounds.stderr
+++ b/tests/ui/derives/deriving-bounds.stderr
@@ -21,6 +21,7 @@ note: unsafe traits like `Sync` should be implemented explicitly
    |
 LL | #[derive(Sync)]
    |          ^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: cannot find derive macro `Send` in this scope
   --> $DIR/deriving-bounds.rs:1:10
@@ -45,6 +46,7 @@ note: unsafe traits like `Send` should be implemented explicitly
    |
 LL | #[derive(Send)]
    |          ^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/derives/deriving-meta-unknown-trait.stderr b/tests/ui/derives/deriving-meta-unknown-trait.stderr
index 053d34f6825..28753b8f9f2 100644
--- a/tests/ui/derives/deriving-meta-unknown-trait.stderr
+++ b/tests/ui/derives/deriving-meta-unknown-trait.stderr
@@ -15,6 +15,8 @@ LL | #[derive(Eqr)]
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: similarly named derive macro `Eq` defined here
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/derives/deriving-primitive.stderr b/tests/ui/derives/deriving-primitive.stderr
index ca64c9ee732..b39637825e5 100644
--- a/tests/ui/derives/deriving-primitive.stderr
+++ b/tests/ui/derives/deriving-primitive.stderr
@@ -9,6 +9,8 @@ error: cannot find derive macro `FromPrimitive` in this scope
    |
 LL | #[derive(FromPrimitive)]
    |          ^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
index bb1b29ef248..bd39c91ffe8 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
@@ -35,6 +35,8 @@ warning: malformed `on_unimplemented` attribute
    |
 LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
    |                                ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:14
@@ -60,6 +62,8 @@ warning: malformed `on_unimplemented` attribute
    |
 LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
    |                                                  ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Boom
   --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:33:14
@@ -85,6 +89,8 @@ warning: malformed `on_unimplemented` attribute
    |
 LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))]
    |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Boom
   --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:35:15
diff --git a/tests/ui/did_you_mean/auxiliary/doc-hidden-fields.rs b/tests/ui/did_you_mean/auxiliary/doc-hidden-fields.rs
new file mode 100644
index 00000000000..4e2ee97403c
--- /dev/null
+++ b/tests/ui/did_you_mean/auxiliary/doc-hidden-fields.rs
@@ -0,0 +1,6 @@
+#[derive(Default)]
+pub struct B {
+    #[doc(hidden)]
+    pub hello: i32,
+    pub bye: i32,
+}
diff --git a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs
new file mode 100644
index 00000000000..6040f3f30a7
--- /dev/null
+++ b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs
@@ -0,0 +1,38 @@
+// Regression test for issue #93210.
+
+// aux-crate:doc_hidden_fields=doc-hidden-fields.rs
+// edition: 2021
+
+#[derive(Default)]
+pub struct A {
+    #[doc(hidden)]
+    pub hello: i32,
+    pub bye: i32,
+}
+
+#[derive(Default)]
+pub struct C {
+    pub hello: i32,
+    pub bye: i32,
+}
+
+fn main() {
+    // We want to list the field `hello` despite being marked
+    // `doc(hidden)` because it's defined in this crate.
+    A::default().hey;
+    //~^ ERROR no field `hey` on type `A`
+    //~| NOTE unknown field
+    //~| NOTE available fields are: `hello`, `bye`
+
+    // Here we want to hide the field `hello` since it's marked
+    // `doc(hidden)` and comes from an external crate.
+    doc_hidden_fields::B::default().hey;
+    //~^ ERROR no field `hey` on type `B`
+    //~| NOTE unknown field
+    //~| NOTE available fields are: `bye`
+
+    C::default().hey;
+    //~^ ERROR no field `hey` on type `C`
+    //~| NOTE unknown field
+    //~| NOTE available fields are: `hello`, `bye`
+}
diff --git a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr
new file mode 100644
index 00000000000..b7fe3b79b47
--- /dev/null
+++ b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr
@@ -0,0 +1,27 @@
+error[E0609]: no field `hey` on type `A`
+  --> $DIR/dont-suggest-doc-hidden-fields.rs:22:18
+   |
+LL |     A::default().hey;
+   |                  ^^^ unknown field
+   |
+   = note: available fields are: `hello`, `bye`
+
+error[E0609]: no field `hey` on type `B`
+  --> $DIR/dont-suggest-doc-hidden-fields.rs:29:37
+   |
+LL |     doc_hidden_fields::B::default().hey;
+   |                                     ^^^ unknown field
+   |
+   = note: available fields are: `bye`
+
+error[E0609]: no field `hey` on type `C`
+  --> $DIR/dont-suggest-doc-hidden-fields.rs:34:18
+   |
+LL |     C::default().hey;
+   |                  ^^^ unknown field
+   |
+   = note: available fields are: `hello`, `bye`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.rs b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.rs
new file mode 100644
index 00000000000..fb7040b2df0
--- /dev/null
+++ b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.rs
@@ -0,0 +1,47 @@
+// Regression test for issue #116334.
+// Don't include hygienic fields from different syntax contexts in
+// the list of available or similarly named fields.
+
+#![feature(decl_macro)]
+
+macro compound($Ty:ident) {
+    #[derive(Default)]
+    struct $Ty {
+        field: u32, // field `field` is hygienic
+    }
+}
+
+macro component($Ty:ident) {
+    struct $Ty(u64); // field `0` is hygienic (but still accessible via the constructor)
+}
+
+compound! { Compound }
+component! { Component }
+
+fn main() {
+    let ty = Compound::default();
+
+    let _ = ty.field; //~ ERROR no field `field` on type `Compound`
+    let _ = ty.fieeld; //~ ERROR no field `fieeld` on type `Compound`
+
+    let Compound { field } = ty;
+    //~^ ERROR struct `Compound` does not have a field named `field`
+    //~| ERROR pattern requires `..` due to inaccessible fields
+    //~| HELP ignore the inaccessible and unused fields
+
+    let ty = Component(90);
+
+    let _ = ty.0; //~ ERROR no field `0` on type `Component`
+}
+
+environment!();
+
+macro environment() {
+    struct Crate { field: () }
+
+    // Here, we do want to suggest `field` even though it's hygienic
+    // precisely because they come from the same syntax context.
+    const CRATE: Crate = Crate { fiel: () };
+    //~^ ERROR struct `Crate` has no field named `fiel`
+    //~| HELP a field with a similar name exists
+}
diff --git a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr
new file mode 100644
index 00000000000..7066d29760e
--- /dev/null
+++ b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr
@@ -0,0 +1,50 @@
+error[E0560]: struct `Crate` has no field named `fiel`
+  --> $DIR/dont-suggest-hygienic-fields.rs:44:34
+   |
+LL | environment!();
+   | -------------- in this macro invocation
+...
+LL |     const CRATE: Crate = Crate { fiel: () };
+   |                                  ^^^^ help: a field with a similar name exists: `field`
+   |
+   = note: this error originates in the macro `environment` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0609]: no field `field` on type `Compound`
+  --> $DIR/dont-suggest-hygienic-fields.rs:24:16
+   |
+LL |     let _ = ty.field;
+   |                ^^^^^ unknown field
+
+error[E0609]: no field `fieeld` on type `Compound`
+  --> $DIR/dont-suggest-hygienic-fields.rs:25:16
+   |
+LL |     let _ = ty.fieeld;
+   |                ^^^^^^ unknown field
+
+error[E0026]: struct `Compound` does not have a field named `field`
+  --> $DIR/dont-suggest-hygienic-fields.rs:27:20
+   |
+LL |     let Compound { field } = ty;
+   |                    ^^^^^ struct `Compound` does not have this field
+
+error: pattern requires `..` due to inaccessible fields
+  --> $DIR/dont-suggest-hygienic-fields.rs:27:9
+   |
+LL |     let Compound { field } = ty;
+   |         ^^^^^^^^^^^^^^^^^^
+   |
+help: ignore the inaccessible and unused fields
+   |
+LL |     let Compound { field, .. } = ty;
+   |                         ++++
+
+error[E0609]: no field `0` on type `Component`
+  --> $DIR/dont-suggest-hygienic-fields.rs:34:16
+   |
+LL |     let _ = ty.0;
+   |                ^ unknown field
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0026, E0560, E0609.
+For more information about an error, try `rustc --explain E0026`.
diff --git a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs b/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs
deleted file mode 100644
index 0efc7daa3e1..00000000000
--- a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-#[derive(Default)]
-pub struct A {
-    #[doc(hidden)]
-    pub hello: i32,
-    pub bye: i32,
-}
-
-#[derive(Default)]
-pub struct B {
-    pub hello: i32,
-    pub bye: i32,
-}
-
-fn main() {
-    A::default().hey;
-    //~^ ERROR no field `hey` on type `A`
-    //~| NOTE unknown field
-    //~| NOTE available fields are: `bye`
-
-    B::default().hey;
-    //~^ ERROR no field `hey` on type `B`
-    //~| NOTE unknown field
-    //~| NOTE available fields are: `hello`, `bye`
-}
diff --git a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr b/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr
deleted file mode 100644
index 784986d3b95..00000000000
--- a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0609]: no field `hey` on type `A`
-  --> $DIR/issue-93210-ignore-doc-hidden.rs:15:18
-   |
-LL |     A::default().hey;
-   |                  ^^^ unknown field
-   |
-   = note: available fields are: `bye`
-
-error[E0609]: no field `hey` on type `B`
-  --> $DIR/issue-93210-ignore-doc-hidden.rs:20:18
-   |
-LL |     B::default().hey;
-   |                  ^^^ unknown field
-   |
-   = note: available fields are: `hello`, `bye`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0609`.
diff --git a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr
index 6bafff9192a..93178667214 100644
--- a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr
+++ b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr
@@ -50,6 +50,7 @@ LL | fn function(x: &SomeTrait, y: Box<SomeTrait>) {
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | fn function(x: &dyn SomeTrait, y: Box<SomeTrait>) {
@@ -63,6 +64,7 @@ LL | fn function(x: &SomeTrait, y: Box<SomeTrait>) {
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | fn function(x: &dyn SomeTrait, y: Box<SomeTrait>) {
@@ -76,6 +78,7 @@ LL | fn function(x: &SomeTrait, y: Box<SomeTrait>) {
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | fn function(x: &SomeTrait, y: Box<dyn SomeTrait>) {
@@ -89,6 +92,7 @@ LL | fn function(x: &SomeTrait, y: Box<SomeTrait>) {
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | fn function(x: &SomeTrait, y: Box<dyn SomeTrait>) {
diff --git a/tests/ui/error-codes/E0452.stderr b/tests/ui/error-codes/E0452.stderr
index f67b740ffe2..986c135ed89 100644
--- a/tests/ui/error-codes/E0452.stderr
+++ b/tests/ui/error-codes/E0452.stderr
@@ -9,18 +9,24 @@ error[E0452]: malformed lint attribute input
    |
 LL | #![allow(foo = "")]
    |          ^^^^^^^^ bad attribute argument
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0452]: malformed lint attribute input
   --> $DIR/E0452.rs:1:10
    |
 LL | #![allow(foo = "")]
    |          ^^^^^^^^ bad attribute argument
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0452]: malformed lint attribute input
   --> $DIR/E0452.rs:1:10
    |
 LL | #![allow(foo = "")]
    |          ^^^^^^^^ bad attribute argument
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/error-codes/E0453.stderr b/tests/ui/error-codes/E0453.stderr
index f982ed26f5c..bb2c39298c0 100644
--- a/tests/ui/error-codes/E0453.stderr
+++ b/tests/ui/error-codes/E0453.stderr
@@ -15,6 +15,8 @@ LL | #![forbid(non_snake_case)]
 LL |
 LL | #[allow(non_snake_case)]
    |         ^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/error-codes/E0602.stderr b/tests/ui/error-codes/E0602.stderr
index 60ecec7cdd7..b6b5cd5c3d3 100644
--- a/tests/ui/error-codes/E0602.stderr
+++ b/tests/ui/error-codes/E0602.stderr
@@ -6,10 +6,12 @@ warning[E0602]: unknown lint: `bogus`
 warning[E0602]: unknown lint: `bogus`
    |
    = note: requested on the command line with `-D bogus`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning[E0602]: unknown lint: `bogus`
    |
    = note: requested on the command line with `-D bogus`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/error-codes/E0719.stderr b/tests/ui/error-codes/E0719.stderr
index e302f406d02..685bd7175e3 100644
--- a/tests/ui/error-codes/E0719.stderr
+++ b/tests/ui/error-codes/E0719.stderr
@@ -13,6 +13,8 @@ LL | trait Foo: Iterator<Item = i32, Item = i32> {}
    |                     ----------  ^^^^^^^^^^ re-bound here
    |                     |
    |                     `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
   --> $DIR/E0719.rs:7:42
diff --git a/tests/ui/error-codes/E0789.stderr b/tests/ui/error-codes/E0789.stderr
index faab92bae03..6df9daafec7 100644
--- a/tests/ui/error-codes/E0789.stderr
+++ b/tests/ui/error-codes/E0789.stderr
@@ -9,6 +9,8 @@ error[E0789]: `rustc_allowed_through_unstable_modules` attribute must be paired
    |
 LL | struct Foo;
    | ^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs
index 49fb10e6029..152c7a8de66 100644
--- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs
+++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs
@@ -54,20 +54,20 @@ fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
 
 const _cdef: impl Tr1<As1: Copy> = S1;
 //~^ ERROR associated type bounds are unstable
-//~| ERROR `impl Trait` only allowed in function and inherent method return types
+//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types
 // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed.
 // const _cdef_dyn: &dyn Tr1<As1: Copy> = &S1;
 
 static _sdef: impl Tr1<As1: Copy> = S1;
 //~^ ERROR associated type bounds are unstable
-//~| ERROR `impl Trait` only allowed in function and inherent method return types
+//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types
 // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed.
 // static _sdef_dyn: &dyn Tr1<As1: Copy> = &S1;
 
 fn main() {
     let _: impl Tr1<As1: Copy> = S1;
     //~^ ERROR associated type bounds are unstable
-    //~| ERROR `impl Trait` only allowed in function and inherent method return types
+    //~| ERROR `impl Trait` only allowed in function and inherent method argument and return types
     // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed.
     // let _: &dyn Tr1<As1: Copy> = &S1;
 }
diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr
index 4233a8af9b6..f2bceda9bea 100644
--- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr
+++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr
@@ -115,19 +115,19 @@ LL |     let _: impl Tr1<As1: Copy> = S1;
    = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types
   --> $DIR/feature-gate-associated_type_bounds.rs:55:14
    |
 LL | const _cdef: impl Tr1<As1: Copy> = S1;
    |              ^^^^^^^^^^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types
   --> $DIR/feature-gate-associated_type_bounds.rs:61:15
    |
 LL | static _sdef: impl Tr1<As1: Copy> = S1;
    |               ^^^^^^^^^^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings
   --> $DIR/feature-gate-associated_type_bounds.rs:68:12
    |
 LL |     let _: impl Tr1<As1: Copy> = S1;
diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs
index 0db8088f7ee..1b9530fa82f 100644
--- a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs
+++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs
@@ -1,6 +1,6 @@
 fn f() -> impl Fn() -> impl Sized { || () }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return
 fn g() -> &'static dyn Fn() -> impl Sized { &|| () }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
index c8c3e13d7fc..f0c0cd040e0 100644
--- a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
+++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types
   --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:1:24
    |
 LL | fn f() -> impl Fn() -> impl Sized { || () }
@@ -7,7 +7,7 @@ LL | fn f() -> impl Fn() -> impl Sized { || () }
    = note: see issue #99697 <https://github.com/rust-lang/rust/issues/99697> for more information
    = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types
   --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32
    |
 LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () }
diff --git a/tests/ui/feature-gates/feature-gate-lint-reasons.stderr b/tests/ui/feature-gates/feature-gate-lint-reasons.stderr
index 12793c7a28f..6d49b7ed2cd 100644
--- a/tests/ui/feature-gates/feature-gate-lint-reasons.stderr
+++ b/tests/ui/feature-gates/feature-gate-lint-reasons.stderr
@@ -15,6 +15,7 @@ LL | #![warn(nonstandard_style, reason = "the standard should be respected")]
    |
    = note: see issue #54503 <https://github.com/rust-lang/rust/issues/54503> for more information
    = help: add `#![feature(lint_reasons)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr
index 1f725f35417..5e14bf6397f 100644
--- a/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr
+++ b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr
@@ -25,6 +25,7 @@ LL | #![deny(multiple_supertrait_upcastable)]
    |
    = note: the `multiple_supertrait_upcastable` lint is unstable
    = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `multiple_supertrait_upcastable`
   --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
@@ -34,6 +35,7 @@ LL | #![warn(multiple_supertrait_upcastable)]
    |
    = note: the `multiple_supertrait_upcastable` lint is unstable
    = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `multiple_supertrait_upcastable`
   --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1
@@ -43,6 +45,7 @@ LL | #![deny(multiple_supertrait_upcastable)]
    |
    = note: the `multiple_supertrait_upcastable` lint is unstable
    = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `multiple_supertrait_upcastable`
   --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
@@ -52,6 +55,7 @@ LL | #![warn(multiple_supertrait_upcastable)]
    |
    = note: the `multiple_supertrait_upcastable` lint is unstable
    = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 6 warnings emitted
 
diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
index fb39c404c20..1c14622d637 100644
--- a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
+++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
@@ -38,6 +38,7 @@ LL |     #[allow(non_exhaustive_omitted_patterns)]
    = note: the `non_exhaustive_omitted_patterns` lint is unstable
    = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
    = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
   --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:29:9
@@ -58,6 +59,7 @@ LL | #![deny(non_exhaustive_omitted_patterns)]
    = note: the `non_exhaustive_omitted_patterns` lint is unstable
    = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
    = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
   --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:6:1
@@ -68,6 +70,7 @@ LL | #![allow(non_exhaustive_omitted_patterns)]
    = note: the `non_exhaustive_omitted_patterns` lint is unstable
    = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
    = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
   --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5
@@ -78,6 +81,7 @@ LL |     #[allow(non_exhaustive_omitted_patterns)]
    = note: the `non_exhaustive_omitted_patterns` lint is unstable
    = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
    = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
   --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5
@@ -88,6 +92,7 @@ LL |     #[allow(non_exhaustive_omitted_patterns)]
    = note: the `non_exhaustive_omitted_patterns` lint is unstable
    = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
    = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `non_exhaustive_omitted_patterns`
   --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:29:9
@@ -98,6 +103,7 @@ LL |         #[warn(non_exhaustive_omitted_patterns)]
    = note: the `non_exhaustive_omitted_patterns` lint is unstable
    = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
    = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0004]: non-exhaustive patterns: `Foo::C` not covered
   --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:20:11
diff --git a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs
index 637765fff11..a8d6365ca79 100644
--- a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs
+++ b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs
@@ -5,14 +5,14 @@
 #![feature(async_fn_in_trait)]
 
 trait Foo {
-    fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return
-    fn baz() -> Box<impl std::fmt::Display>; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return
+    fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return
+    fn baz() -> Box<impl std::fmt::Display>; //~ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return
 }
 
 // Both return_position_impl_trait_in_trait and async_fn_in_trait are required for this (see also
 // feature-gate-async_fn_in_trait.rs)
 trait AsyncFoo {
-    async fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return
+    async fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return
 }
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr
index 0082b6fafee..86f138fabdb 100644
--- a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr
+++ b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return types
   --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:8:17
    |
 LL |     fn bar() -> impl Sized;
@@ -7,7 +7,7 @@ LL |     fn bar() -> impl Sized;
    = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
    = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return types
   --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:9:21
    |
 LL |     fn baz() -> Box<impl std::fmt::Display>;
@@ -16,7 +16,7 @@ LL |     fn baz() -> Box<impl std::fmt::Display>;
    = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
    = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return types
   --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:15:23
    |
 LL |     async fn bar() -> impl Sized;
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr
index 1bdb2574ead..f6230b76463 100644
--- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr
@@ -1,5 +1,5 @@
 error[E0658]: return type notation is experimental
-  --> $DIR/feature-gate-return_type_notation.rs:14:17
+  --> $DIR/feature-gate-return_type_notation.rs:15:17
    |
 LL | fn foo<T: Trait<m(): Send>>() {}
    |                 ^^^^^^^^^
@@ -8,7 +8,7 @@ LL | fn foo<T: Trait<m(): Send>>() {}
    = help: add `#![feature(return_type_notation)]` to the crate attributes to enable
 
 error: parenthesized generic arguments cannot be used in associated type constraints
-  --> $DIR/feature-gate-return_type_notation.rs:14:17
+  --> $DIR/feature-gate-return_type_notation.rs:15:17
    |
 LL | fn foo<T: Trait<m(): Send>>() {}
    |                 ^--
@@ -16,7 +16,7 @@ LL | fn foo<T: Trait<m(): Send>>() {}
    |                  help: remove these parentheses
 
 error[E0220]: associated type `m` not found for `Trait`
-  --> $DIR/feature-gate-return_type_notation.rs:14:17
+  --> $DIR/feature-gate-return_type_notation.rs:15:17
    |
 LL | fn foo<T: Trait<m(): Send>>() {}
    |                 ^ associated type `m` not found
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr
index dd6ebb61038..c7f52d7cddc 100644
--- a/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr
@@ -1,5 +1,5 @@
 warning: return type notation is experimental
-  --> $DIR/feature-gate-return_type_notation.rs:14:17
+  --> $DIR/feature-gate-return_type_notation.rs:15:17
    |
 LL | fn foo<T: Trait<m(): Send>>() {}
    |                 ^^^^^^^^^
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.rs b/tests/ui/feature-gates/feature-gate-return_type_notation.rs
index ae12495b5dc..c0c285cef3c 100644
--- a/tests/ui/feature-gates/feature-gate-return_type_notation.rs
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.rs
@@ -7,6 +7,7 @@
 #![feature(async_fn_in_trait)]
 
 trait Trait {
+    #[allow(async_fn_in_trait)]
     async fn m();
 }
 
diff --git a/tests/ui/feature-gates/feature-gate-strict_provenance.stderr b/tests/ui/feature-gates/feature-gate-strict_provenance.stderr
index 751da87cc0d..1e6d762a540 100644
--- a/tests/ui/feature-gates/feature-gate-strict_provenance.stderr
+++ b/tests/ui/feature-gates/feature-gate-strict_provenance.stderr
@@ -28,6 +28,7 @@ LL | #![deny(fuzzy_provenance_casts)]
    = note: the `fuzzy_provenance_casts` lint is unstable
    = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information
    = help: add `#![feature(strict_provenance)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `lossy_provenance_casts`
   --> $DIR/feature-gate-strict_provenance.rs:7:1
@@ -38,6 +39,7 @@ LL | #![deny(lossy_provenance_casts)]
    = note: the `lossy_provenance_casts` lint is unstable
    = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information
    = help: add `#![feature(strict_provenance)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `fuzzy_provenance_casts`
   --> $DIR/feature-gate-strict_provenance.rs:3:1
@@ -48,6 +50,7 @@ LL | #![deny(fuzzy_provenance_casts)]
    = note: the `fuzzy_provenance_casts` lint is unstable
    = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information
    = help: add `#![feature(strict_provenance)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `lossy_provenance_casts`
   --> $DIR/feature-gate-strict_provenance.rs:7:1
@@ -58,6 +61,7 @@ LL | #![deny(lossy_provenance_casts)]
    = note: the `lossy_provenance_casts` lint is unstable
    = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information
    = help: add `#![feature(strict_provenance)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 6 warnings emitted
 
diff --git a/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr b/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr
index b4d6aa658e1..562aa478a93 100644
--- a/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr
+++ b/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr
@@ -16,6 +16,7 @@ LL | #![allow(test_unstable_lint)]
    |
    = note: the `test_unstable_lint` lint is unstable
    = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `test_unstable_lint`
   --> $DIR/feature-gate-test_unstable_lint.rs:4:1
@@ -25,6 +26,7 @@ LL | #![allow(test_unstable_lint)]
    |
    = note: the `test_unstable_lint` lint is unstable
    = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr b/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr
index 4349fea6f89..2614f2b3c35 100644
--- a/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr
+++ b/tests/ui/feature-gates/feature-gate-type_privacy_lints.stderr
@@ -18,6 +18,7 @@ LL | #![warn(unnameable_types)]
    = note: the `unnameable_types` lint is unstable
    = note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
    = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `unnameable_types`
   --> $DIR/feature-gate-type_privacy_lints.rs:3:1
@@ -28,6 +29,7 @@ LL | #![warn(unnameable_types)]
    = note: the `unnameable_types` lint is unstable
    = note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
    = help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-derive-2.stderr b/tests/ui/feature-gates/issue-43106-gating-of-derive-2.stderr
index ab165917344..1e47259cb7e 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-derive-2.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-derive-2.stderr
@@ -9,6 +9,8 @@ error: cannot find derive macro `x3300` in this scope
    |
 LL |     #[derive(x3300)]
    |              ^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: cannot find derive macro `x3300` in this scope
   --> $DIR/issue-43106-gating-of-derive-2.rs:9:14
@@ -21,6 +23,8 @@ error: cannot find derive macro `x3300` in this scope
    |
 LL |     #[derive(x3300)]
    |              ^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: cannot find derive macro `x3300` in this scope
   --> $DIR/issue-43106-gating-of-derive-2.rs:4:14
@@ -33,6 +37,8 @@ error: cannot find derive macro `x3300` in this scope
    |
 LL |     #[derive(x3300)]
    |              ^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
index 499221637ba..7f535ec432c 100644
--- a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
+++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
@@ -25,6 +25,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a`
    |
 LL |   type Y<'a>;
    |        ^ --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |   fn foo<'a, T1: X<Y<'a> = T1>>(t : T1) -> T1::Y<'a> {
diff --git a/tests/ui/generic-associated-types/issue-91139.stderr b/tests/ui/generic-associated-types/issue-91139.stderr
index d9d76adfbb5..89a4ba77e4e 100644
--- a/tests/ui/generic-associated-types/issue-91139.stderr
+++ b/tests/ui/generic-associated-types/issue-91139.stderr
@@ -9,6 +9,8 @@ error: `T` does not live long enough
    |
 LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/generic-const-items/unsatisfied-bounds.stderr b/tests/ui/generic-const-items/unsatisfied-bounds.stderr
index 2cee53431a4..14894cef770 100644
--- a/tests/ui/generic-const-items/unsatisfied-bounds.stderr
+++ b/tests/ui/generic-const-items/unsatisfied-bounds.stderr
@@ -17,6 +17,7 @@ LL |     let () = K::<()>;
    |                  ^^ the trait `From<()>` is not implemented for `Infallible`
    |
    = help: the trait `From<!>` is implemented for `Infallible`
+   = help: for that trait implementation, expected `!`, found `()`
 note: required by a bound in `K`
   --> $DIR/unsatisfied-bounds.rs:12:17
    |
@@ -48,6 +49,7 @@ LL |     let _ = <() as Trait<&'static str>>::B::<()>;
    |                                              ^^ the trait `From<()>` is not implemented for `Infallible`
    |
    = help: the trait `From<!>` is implemented for `Infallible`
+   = help: for that trait implementation, expected `!`, found `()`
 note: required by a bound in `Trait::B`
   --> $DIR/unsatisfied-bounds.rs:21:21
    |
diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr
index a73c03feb87..48703186cc6 100644
--- a/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr
+++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr
@@ -24,6 +24,7 @@ LL | | for<'a>    fn(Inv<'a>, Inv<'a>)) }
    |
    = note: expected enum `Option<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>`
               found enum `Option<for<'a> fn(Inv<'a>, Inv<'a>)>`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
    = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr
index 46f5308dd87..69c58c5919e 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr
@@ -15,6 +15,7 @@ LL | fn b() { want_foo2::<SomeStruct>(); }
    |
    = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
    = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr
index fad0b812d43..d3c2d5d5b9f 100644
--- a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr
+++ b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr
@@ -20,6 +20,7 @@ LL | fn ice() -> impl AsRef<Fn(&())> {
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | fn ice() -> impl AsRef<dyn Fn(&())> {
@@ -33,6 +34,7 @@ LL | fn ice() -> impl AsRef<Fn(&())> {
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | fn ice() -> impl AsRef<dyn Fn(&())> {
diff --git a/tests/ui/impl-trait/impl-subtyper.rs b/tests/ui/impl-trait/impl-subtyper.rs
new file mode 100644
index 00000000000..2d99cdd4f50
--- /dev/null
+++ b/tests/ui/impl-trait/impl-subtyper.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+#![crate_type = "lib"]
+fn checkpoints() -> impl Iterator {
+    Some(()).iter().flat_map(|_| std::iter::once(()))
+}
+
+fn block_checkpoints() -> impl Iterator {
+    checkpoints()
+}
+
+fn iter_raw() -> impl Iterator {
+    let mut iter = block_checkpoints();
+
+    (0..9).map(move |_| {
+        iter.next();
+    })
+}
diff --git a/tests/ui/impl-trait/impl-subtyper2.rs b/tests/ui/impl-trait/impl-subtyper2.rs
new file mode 100644
index 00000000000..2e0acbae68b
--- /dev/null
+++ b/tests/ui/impl-trait/impl-subtyper2.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+fn ages() -> Option<impl Iterator> {
+    None::<std::slice::Iter<()>>
+}
+
+fn main(){}
diff --git a/tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs b/tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs
index 2a61c5cc8df..5de9c01e3e0 100644
--- a/tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs
+++ b/tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs
@@ -9,6 +9,7 @@ trait AsyncLendingIterator {
     where
         Self: 'a;
 
+    #[allow(async_fn_in_trait)]
     async fn next(&mut self) -> Option<Self::Item<'_>>;
 }
 
diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
index 25133214dc6..9c60cf4e72a 100644
--- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
+++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
@@ -7,6 +7,7 @@
 use std::fmt::Debug;
 
 trait Foo {
+    #[allow(async_fn_in_trait)]
     async fn baz(&self) -> impl Debug {
         ""
     }
diff --git a/tests/ui/impl-trait/in-trait/default-body.rs b/tests/ui/impl-trait/in-trait/default-body.rs
index b0baf5bb10d..d3ea9fbeabc 100644
--- a/tests/ui/impl-trait/in-trait/default-body.rs
+++ b/tests/ui/impl-trait/in-trait/default-body.rs
@@ -7,6 +7,7 @@
 use std::fmt::Debug;
 
 trait Foo {
+    #[allow(async_fn_in_trait)]
     async fn baz(&self) -> &str {
         ""
     }
diff --git a/tests/ui/impl-trait/in-trait/early.rs b/tests/ui/impl-trait/in-trait/early.rs
index 9c1c2b50339..bb5718b4934 100644
--- a/tests/ui/impl-trait/in-trait/early.rs
+++ b/tests/ui/impl-trait/in-trait/early.rs
@@ -5,6 +5,7 @@
 #![allow(incomplete_features)]
 
 pub trait Foo {
+    #[allow(async_fn_in_trait)]
     async fn bar<'a: 'a>(&'a mut self);
 }
 
diff --git a/tests/ui/impl-trait/in-trait/refine.rs b/tests/ui/impl-trait/in-trait/refine.rs
index a91f9b3e722..f00478b0bb9 100644
--- a/tests/ui/impl-trait/in-trait/refine.rs
+++ b/tests/ui/impl-trait/in-trait/refine.rs
@@ -45,4 +45,15 @@ impl Late for D {
     //~^ ERROR impl method signature does not match trait method signature
 }
 
+mod unreachable {
+    pub trait UnreachablePub {
+        fn bar() -> impl Sized;
+    }
+
+    struct E;
+    impl UnreachablePub for E {
+        fn bar() {}
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/refine.stderr b/tests/ui/impl-trait/in-trait/refine.stderr
index 29aa08e25bb..1d9852c682c 100644
--- a/tests/ui/impl-trait/in-trait/refine.stderr
+++ b/tests/ui/impl-trait/in-trait/refine.stderr
@@ -30,8 +30,8 @@ LL |     fn bar() {}
    = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
 help: replace the return type so that it matches the trait
    |
-LL |     fn bar() -> impl Sized {}
-   |              +++++++++++++
+LL |     fn bar()-> impl Sized  {}
+   |             +++++++++++++
 
 error: impl trait in impl method signature does not match trait method signature
   --> $DIR/refine.rs:22:17
diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed
index d9f775a6c84..58d83384a23 100644
--- a/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed
+++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed
@@ -4,12 +4,15 @@
 #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
 
 trait Trait {
+    #[allow(async_fn_in_trait)]
     async fn foo();
 
+    #[allow(async_fn_in_trait)]
     async fn bar() -> i32;
 
     fn test(&self) -> impl Sized + '_;
 
+    #[allow(async_fn_in_trait)]
     async fn baz(&self) -> &i32;
 }
 
diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.rs b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs
index 26979b5149b..c27229806e1 100644
--- a/tests/ui/impl-trait/in-trait/suggest-missing-item.rs
+++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs
@@ -4,12 +4,15 @@
 #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
 
 trait Trait {
+    #[allow(async_fn_in_trait)]
     async fn foo();
 
+    #[allow(async_fn_in_trait)]
     async fn bar() -> i32;
 
     fn test(&self) -> impl Sized + '_;
 
+    #[allow(async_fn_in_trait)]
     async fn baz(&self) -> &i32;
 }
 
diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr
index 44f98896eb3..29f6bad86dc 100644
--- a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr
+++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr
@@ -1,15 +1,15 @@
 error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `test`, `baz`
-  --> $DIR/suggest-missing-item.rs:18:1
+  --> $DIR/suggest-missing-item.rs:21:1
    |
 LL |     async fn foo();
    |     --------------- `foo` from trait
-LL |
+...
 LL |     async fn bar() -> i32;
    |     ---------------------- `bar` from trait
 LL |
 LL |     fn test(&self) -> impl Sized + '_;
    |     ---------------------------------- `test` from trait
-LL |
+...
 LL |     async fn baz(&self) -> &i32;
    |     ---------------------------- `baz` from trait
 ...
diff --git a/tests/ui/impl-trait/issue-55872-2.stderr b/tests/ui/impl-trait/issue-55872-2.stderr
index 3e70f1cf800..b5b7f293a40 100644
--- a/tests/ui/impl-trait/issue-55872-2.stderr
+++ b/tests/ui/impl-trait/issue-55872-2.stderr
@@ -9,6 +9,8 @@ error: type parameter `T` is part of concrete type but not used in parameter lis
    |
 LL |         async {}
    |         ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/issues/issue-54600.rs b/tests/ui/impl-trait/issues/issue-54600.rs
index 3024fedf7b5..ccf2767012e 100644
--- a/tests/ui/impl-trait/issues/issue-54600.rs
+++ b/tests/ui/impl-trait/issues/issue-54600.rs
@@ -2,6 +2,6 @@ use std::fmt::Debug;
 
 fn main() {
     let x: Option<impl Debug> = Some(44_u32);
-    //~^ `impl Trait` only allowed in function and inherent method return types
+    //~^ `impl Trait` only allowed in function and inherent method argument and return types
     println!("{:?}", x);
 }
diff --git a/tests/ui/impl-trait/issues/issue-54600.stderr b/tests/ui/impl-trait/issues/issue-54600.stderr
index 7ef063af952..9a8e3675b95 100644
--- a/tests/ui/impl-trait/issues/issue-54600.stderr
+++ b/tests/ui/impl-trait/issues/issue-54600.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings
   --> $DIR/issue-54600.rs:4:19
    |
 LL |     let x: Option<impl Debug> = Some(44_u32);
diff --git a/tests/ui/impl-trait/issues/issue-54840.rs b/tests/ui/impl-trait/issues/issue-54840.rs
index 8f1e0ece03a..910d23f1d93 100644
--- a/tests/ui/impl-trait/issues/issue-54840.rs
+++ b/tests/ui/impl-trait/issues/issue-54840.rs
@@ -3,5 +3,5 @@ use std::ops::Add;
 fn main() {
     let i: i32 = 0;
     let j: &impl Add = &i;
-    //~^ `impl Trait` only allowed in function and inherent method return types
+    //~^ `impl Trait` only allowed in function and inherent method argument and return types
 }
diff --git a/tests/ui/impl-trait/issues/issue-54840.stderr b/tests/ui/impl-trait/issues/issue-54840.stderr
index 1d1316f0e11..67cabf44950 100644
--- a/tests/ui/impl-trait/issues/issue-54840.stderr
+++ b/tests/ui/impl-trait/issues/issue-54840.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings
   --> $DIR/issue-54840.rs:5:13
    |
 LL |     let j: &impl Add = &i;
diff --git a/tests/ui/impl-trait/issues/issue-58504.rs b/tests/ui/impl-trait/issues/issue-58504.rs
index e5865d0dfff..f1d7b94ef2d 100644
--- a/tests/ui/impl-trait/issues/issue-58504.rs
+++ b/tests/ui/impl-trait/issues/issue-58504.rs
@@ -8,5 +8,5 @@ fn mk_gen() -> impl Generator<Return=!, Yield=()> {
 
 fn main() {
     let gens: [impl Generator<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ];
-    //~^ `impl Trait` only allowed in function and inherent method return types
+    //~^ `impl Trait` only allowed in function and inherent method argument and return types
 }
diff --git a/tests/ui/impl-trait/issues/issue-58504.stderr b/tests/ui/impl-trait/issues/issue-58504.stderr
index 26ec2a4f9cf..1be676ee075 100644
--- a/tests/ui/impl-trait/issues/issue-58504.stderr
+++ b/tests/ui/impl-trait/issues/issue-58504.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings
   --> $DIR/issue-58504.rs:10:16
    |
 LL |     let gens: [impl Generator<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ];
diff --git a/tests/ui/impl-trait/issues/issue-58956.rs b/tests/ui/impl-trait/issues/issue-58956.rs
index 68cfcd9ba4f..5d5566860c0 100644
--- a/tests/ui/impl-trait/issues/issue-58956.rs
+++ b/tests/ui/impl-trait/issues/issue-58956.rs
@@ -5,9 +5,9 @@ impl Lam for B {}
 pub struct Wrap<T>(T);
 
 const _A: impl Lam = {
-    //~^ `impl Trait` only allowed in function and inherent method return types
+    //~^ `impl Trait` only allowed in function and inherent method argument and return types
     let x: Wrap<impl Lam> = Wrap(B);
-    //~^ `impl Trait` only allowed in function and inherent method return types
+    //~^ `impl Trait` only allowed in function and inherent method argument and return types
     x.0
 };
 
diff --git a/tests/ui/impl-trait/issues/issue-58956.stderr b/tests/ui/impl-trait/issues/issue-58956.stderr
index 2b4d0abdffc..5ee33352afa 100644
--- a/tests/ui/impl-trait/issues/issue-58956.stderr
+++ b/tests/ui/impl-trait/issues/issue-58956.stderr
@@ -1,10 +1,10 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types
   --> $DIR/issue-58956.rs:7:11
    |
 LL | const _A: impl Lam = {
    |           ^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings
   --> $DIR/issue-58956.rs:9:17
    |
 LL |     let x: Wrap<impl Lam> = Wrap(B);
diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr
index d872291c870..8d969e8e0f3 100644
--- a/tests/ui/impl-trait/issues/issue-62742.stderr
+++ b/tests/ui/impl-trait/issues/issue-62742.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
 LL |     WrongImpl::foo(0i32);
    |     ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
    |
-   = help: the trait `Raw<[T]>` is implemented for `RawImpl<T>`
+   = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
 note: required by a bound in `SafeImpl`
   --> $DIR/issue-62742.rs:26:35
    |
@@ -42,7 +42,8 @@ error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
 LL |     WrongImpl::<()>::foo(0i32);
    |     ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
    |
-   = help: the trait `Raw<[T]>` is implemented for `RawImpl<T>`
+   = help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
+   = help: for that trait implementation, expected `[()]`, found `()`
 note: required by a bound in `SafeImpl`
   --> $DIR/issue-62742.rs:26:35
    |
diff --git a/tests/ui/impl-trait/issues/issue-70971.rs b/tests/ui/impl-trait/issues/issue-70971.rs
index f8ae18bacd6..c24259a71eb 100644
--- a/tests/ui/impl-trait/issues/issue-70971.rs
+++ b/tests/ui/impl-trait/issues/issue-70971.rs
@@ -1,4 +1,4 @@
 fn main() {
     let x : (impl Copy,) = (true,);
-    //~^ `impl Trait` only allowed in function and inherent method return types
+    //~^ `impl Trait` only allowed in function and inherent method argument and return types
 }
diff --git a/tests/ui/impl-trait/issues/issue-70971.stderr b/tests/ui/impl-trait/issues/issue-70971.stderr
index d066256bfb0..5609f8b9b01 100644
--- a/tests/ui/impl-trait/issues/issue-70971.stderr
+++ b/tests/ui/impl-trait/issues/issue-70971.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings
   --> $DIR/issue-70971.rs:2:14
    |
 LL |     let x : (impl Copy,) = (true,);
diff --git a/tests/ui/impl-trait/issues/issue-79099.rs b/tests/ui/impl-trait/issues/issue-79099.rs
index da53594f3d0..22c66491ce9 100644
--- a/tests/ui/impl-trait/issues/issue-79099.rs
+++ b/tests/ui/impl-trait/issues/issue-79099.rs
@@ -1,7 +1,7 @@
 struct Bug {
     V1: [(); {
         let f: impl core::future::Future<Output = u8> = async { 1 };
-        //~^ `impl Trait` only allowed in function and inherent method return types
+        //~^ `impl Trait` only allowed in function and inherent method argument and return types
         //~| expected identifier
         1
     }],
diff --git a/tests/ui/impl-trait/issues/issue-79099.stderr b/tests/ui/impl-trait/issues/issue-79099.stderr
index 580250a62fe..82fc03c61b3 100644
--- a/tests/ui/impl-trait/issues/issue-79099.stderr
+++ b/tests/ui/impl-trait/issues/issue-79099.stderr
@@ -9,7 +9,7 @@ LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
    = help: pass `--edition 2021` to `rustc`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings
   --> $DIR/issue-79099.rs:3:16
    |
 LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
diff --git a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs
index 344f359529b..3224145bffe 100644
--- a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs
+++ b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs
@@ -1,8 +1,8 @@
 struct Foo<T = impl Copy>(T);
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 type Result<T, E = impl std::error::Error> = std::result::Result<T, E>;
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // should not cause ICE
 fn x() -> Foo {
diff --git a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr
index 656bd047061..56be4577d51 100644
--- a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr
+++ b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr
@@ -1,10 +1,10 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults
   --> $DIR/issue-83929-impl-trait-in-generic-default.rs:1:16
    |
 LL | struct Foo<T = impl Copy>(T);
    |                ^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults
   --> $DIR/issue-83929-impl-trait-in-generic-default.rs:4:20
    |
 LL | type Result<T, E = impl std::error::Error> = std::result::Result<T, E>;
diff --git a/tests/ui/impl-trait/issues/issue-84919.rs b/tests/ui/impl-trait/issues/issue-84919.rs
index a0b73743a2b..77d27d7c06b 100644
--- a/tests/ui/impl-trait/issues/issue-84919.rs
+++ b/tests/ui/impl-trait/issues/issue-84919.rs
@@ -3,7 +3,7 @@ impl Trait for () {}
 
 fn foo<'a: 'a>() {
     let _x: impl Trait = ();
-    //~^ `impl Trait` only allowed in function and inherent method return types
+    //~^ `impl Trait` only allowed in function and inherent method argument and return types
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/issues/issue-84919.stderr b/tests/ui/impl-trait/issues/issue-84919.stderr
index 36010fdef36..20b131b8bd2 100644
--- a/tests/ui/impl-trait/issues/issue-84919.stderr
+++ b/tests/ui/impl-trait/issues/issue-84919.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings
   --> $DIR/issue-84919.rs:5:13
    |
 LL |     let _x: impl Trait = ();
diff --git a/tests/ui/impl-trait/issues/issue-86642.rs b/tests/ui/impl-trait/issues/issue-86642.rs
index e6e95771400..49f8944ac4a 100644
--- a/tests/ui/impl-trait/issues/issue-86642.rs
+++ b/tests/ui/impl-trait/issues/issue-86642.rs
@@ -1,5 +1,5 @@
 static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
-    //~^ `impl Trait` only allowed in function and inherent method return types
+    //~^ `impl Trait` only allowed in function and inherent method argument and return types
     let res = (move |source| Ok(source))(source);
     let res = res.or((move |source| Ok(source))(source));
     res
diff --git a/tests/ui/impl-trait/issues/issue-86642.stderr b/tests/ui/impl-trait/issues/issue-86642.stderr
index b6f8a54f35a..6d3be3fff0e 100644
--- a/tests/ui/impl-trait/issues/issue-86642.stderr
+++ b/tests/ui/impl-trait/issues/issue-86642.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in const types
   --> $DIR/issue-86642.rs:1:11
    |
 LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
diff --git a/tests/ui/impl-trait/issues/issue-87295.rs b/tests/ui/impl-trait/issues/issue-87295.rs
index aeb8f83326e..eb44020ac0e 100644
--- a/tests/ui/impl-trait/issues/issue-87295.rs
+++ b/tests/ui/impl-trait/issues/issue-87295.rs
@@ -14,5 +14,5 @@ impl<F> Struct<F> {
 
 fn main() {
     let _do_not_waste: Struct<impl Trait<Output = i32>> = Struct::new(());
-    //~^ `impl Trait` only allowed in function and inherent method return types
+    //~^ `impl Trait` only allowed in function and inherent method argument and return types
 }
diff --git a/tests/ui/impl-trait/issues/issue-87295.stderr b/tests/ui/impl-trait/issues/issue-87295.stderr
index ec59b719c10..3fe4ee73c80 100644
--- a/tests/ui/impl-trait/issues/issue-87295.stderr
+++ b/tests/ui/impl-trait/issues/issue-87295.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings
   --> $DIR/issue-87295.rs:16:31
    |
 LL |     let _do_not_waste: Struct<impl Trait<Output = i32>> = Struct::new(());
diff --git a/tests/ui/impl-trait/nested_impl_trait.rs b/tests/ui/impl-trait/nested_impl_trait.rs
index e95fab3b650..c036b9e367a 100644
--- a/tests/ui/impl-trait/nested_impl_trait.rs
+++ b/tests/ui/impl-trait/nested_impl_trait.rs
@@ -9,7 +9,7 @@ fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
 
 fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
 //~^ ERROR nested `impl Trait` is not allowed
-//~| `impl Trait` only allowed in function and inherent method return types
+//~| `impl Trait` only allowed in function and inherent method argument and return types
 
 fn bad_in_arg_position(_: impl Into<impl Debug>) { }
 //~^ ERROR nested `impl Trait` is not allowed
diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr
index ffe84b8e86f..f1cafd958b0 100644
--- a/tests/ui/impl-trait/nested_impl_trait.stderr
+++ b/tests/ui/impl-trait/nested_impl_trait.stderr
@@ -34,7 +34,7 @@ LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                  |         nested `impl Trait` here
    |                                  outer `impl Trait`
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types
   --> $DIR/nested_impl_trait.rs:10:32
    |
 LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
diff --git a/tests/ui/impl-trait/where-allowed.rs b/tests/ui/impl-trait/where-allowed.rs
index 509d2716649..d3fab326e74 100644
--- a/tests/ui/impl-trait/where-allowed.rs
+++ b/tests/ui/impl-trait/where-allowed.rs
@@ -16,47 +16,47 @@ fn in_adt_in_parameters(_: Vec<impl Debug>) { panic!() }
 
 // Disallowed
 fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Allowed
 fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
 
 // Disallowed
 fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 //~^^ ERROR nested `impl Trait` is not allowed
 
 // Disallowed
 fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 //~| ERROR nested `impl Trait` is not allowed
 
 // Allowed
@@ -64,11 +64,11 @@ fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!()
 
 // Disallowed
 fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 
 // Allowed
@@ -81,22 +81,22 @@ fn in_impl_Trait_in_return() -> impl IntoIterator<Item = impl IntoIterator> {
 
 // Disallowed
 struct InBraceStructField { x: impl Debug }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 struct InAdtInBraceStructField { x: Vec<impl Debug> }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 struct InTupleStructField(impl Debug);
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 enum InEnum {
     InBraceVariant { x: impl Debug },
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
     InTupleVariant(impl Debug),
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 }
 
 // Allowed
@@ -107,7 +107,7 @@ trait InTraitDefnParameters {
 // Disallowed
 trait InTraitDefnReturn {
     fn in_return() -> impl Debug;
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 }
 
 // Allowed and disallowed in trait impls
@@ -124,7 +124,7 @@ impl DummyTrait for () {
     // Allowed
 
     fn in_trait_impl_return() -> impl Debug { () }
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 }
 
 // Allowed
@@ -137,10 +137,10 @@ impl DummyType {
 // Disallowed
 extern "C" {
     fn in_foreign_parameters(_: impl Debug);
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
     fn in_foreign_return() -> impl Debug;
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 }
 
 // Allowed
@@ -156,97 +156,97 @@ type InTypeAlias<R> = impl Debug;
 //~^ ERROR `impl Trait` in type aliases is unstable
 
 type InReturnInTypeAlias<R> = fn() -> impl Debug;
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 //~| ERROR `impl Trait` in type aliases is unstable
 
 // Disallowed in impl headers
 impl PartialEq<impl Debug> for () {
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 }
 
 // Disallowed in impl headers
 impl PartialEq<()> for impl Debug {
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 }
 
 // Disallowed in inherent impls
 impl impl Debug {
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 }
 
 // Disallowed in inherent impls
 struct InInherentImplAdt<T> { t: T }
 impl InInherentImplAdt<impl Debug> {
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 }
 
 // Disallowed in where clauses
 fn in_fn_where_clause()
     where impl Debug: Debug
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 {
 }
 
 // Disallowed in where clauses
 fn in_adt_in_fn_where_clause()
     where Vec<impl Debug>: Debug
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 {
 }
 
 // Disallowed
 fn in_trait_parameter_in_fn_where_clause<T>()
     where T: PartialEq<impl Debug>
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 {
 }
 
 // Disallowed
 fn in_Fn_parameter_in_fn_where_clause<T>()
     where T: Fn(impl Debug)
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 {
 }
 
 // Disallowed
 fn in_Fn_return_in_fn_where_clause<T>()
     where T: Fn() -> impl Debug
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 {
 }
 
 // Disallowed
 struct InStructGenericParamDefault<T = impl Debug>(T);
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 enum InEnumGenericParamDefault<T = impl Debug> { Variant(T) }
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 trait InTraitGenericParamDefault<T = impl Debug> {}
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 type InTypeAliasGenericParamDefault<T = impl Debug> = T;
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 // Disallowed
 impl <T = impl Debug> T {}
 //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
 //~| WARNING this was previously accepted by the compiler but is being phased out
-//~| ERROR `impl Trait` only allowed in function and inherent method return types
+//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types
 //~| ERROR no nominal type found
 
 // Disallowed
 fn in_method_generic_param_default<T = impl Debug>(_: T) {}
 //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
 //~| WARNING this was previously accepted by the compiler but is being phased out
-//~| ERROR `impl Trait` only allowed in function and inherent method return types
+//~| ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 fn main() {
     let _in_local_variable: impl Fn() = || {};
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
     let _in_return_in_local_variable = || -> impl Fn() { || {} };
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 }
diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr
index 3e293437975..bd7c9a94793 100644
--- a/tests/ui/impl-trait/where-allowed.stderr
+++ b/tests/ui/impl-trait/where-allowed.stderr
@@ -43,109 +43,109 @@ LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer params
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer params
   --> $DIR/where-allowed.rs:18:40
    |
 LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
    |                                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types
   --> $DIR/where-allowed.rs:22:42
    |
 LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
    |                                          ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer params
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer params
   --> $DIR/where-allowed.rs:26:38
    |
 LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
    |                                      ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types
   --> $DIR/where-allowed.rs:30:40
    |
 LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
    |                                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params
   --> $DIR/where-allowed.rs:34:49
    |
 LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
    |                                                 ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types
   --> $DIR/where-allowed.rs:38:51
    |
 LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
    |                                                   ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params
   --> $DIR/where-allowed.rs:42:55
    |
 LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
    |                                                       ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params
   --> $DIR/where-allowed.rs:49:51
    |
 LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
    |                                                   ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types
   --> $DIR/where-allowed.rs:54:53
    |
 LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
    |                                                     ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params
   --> $DIR/where-allowed.rs:58:57
    |
 LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
    |                                                         ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params
   --> $DIR/where-allowed.rs:66:38
    |
 LL | fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
    |                                      ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types
   --> $DIR/where-allowed.rs:70:40
    |
 LL | fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
    |                                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types
   --> $DIR/where-allowed.rs:83:32
    |
 LL | struct InBraceStructField { x: impl Debug }
    |                                ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types
   --> $DIR/where-allowed.rs:87:41
    |
 LL | struct InAdtInBraceStructField { x: Vec<impl Debug> }
    |                                         ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types
   --> $DIR/where-allowed.rs:91:27
    |
 LL | struct InTupleStructField(impl Debug);
    |                           ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types
   --> $DIR/where-allowed.rs:96:25
    |
 LL |     InBraceVariant { x: impl Debug },
    |                         ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in field types
   --> $DIR/where-allowed.rs:98:20
    |
 LL |     InTupleVariant(impl Debug),
    |                    ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in trait method return types
   --> $DIR/where-allowed.rs:109:23
    |
 LL |     fn in_return() -> impl Debug;
@@ -154,7 +154,7 @@ LL |     fn in_return() -> impl Debug;
    = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
    = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `impl` method return types
   --> $DIR/where-allowed.rs:126:34
    |
 LL |     fn in_trait_impl_return() -> impl Debug { () }
@@ -163,121 +163,121 @@ LL |     fn in_trait_impl_return() -> impl Debug { () }
    = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
    = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` params
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `extern fn` params
   --> $DIR/where-allowed.rs:139:33
    |
 LL |     fn in_foreign_parameters(_: impl Debug);
    |                                 ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `extern fn` return types
   --> $DIR/where-allowed.rs:142:31
    |
 LL |     fn in_foreign_return() -> impl Debug;
    |                               ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types
   --> $DIR/where-allowed.rs:158:39
    |
 LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
    |                                       ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in traits
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in traits
   --> $DIR/where-allowed.rs:163:16
    |
 LL | impl PartialEq<impl Debug> for () {
    |                ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers
   --> $DIR/where-allowed.rs:168:24
    |
 LL | impl PartialEq<()> for impl Debug {
    |                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers
   --> $DIR/where-allowed.rs:173:6
    |
 LL | impl impl Debug {
    |      ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in impl headers
   --> $DIR/where-allowed.rs:179:24
    |
 LL | impl InInherentImplAdt<impl Debug> {
    |                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bounds
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in bounds
   --> $DIR/where-allowed.rs:185:11
    |
 LL |     where impl Debug: Debug
    |           ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bounds
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in bounds
   --> $DIR/where-allowed.rs:192:15
    |
 LL |     where Vec<impl Debug>: Debug
    |               ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bounds
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in bounds
   --> $DIR/where-allowed.rs:199:24
    |
 LL |     where T: PartialEq<impl Debug>
    |                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait params
   --> $DIR/where-allowed.rs:206:17
    |
 LL |     where T: Fn(impl Debug)
    |                 ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `Fn` trait return types
   --> $DIR/where-allowed.rs:213:22
    |
 LL |     where T: Fn() -> impl Debug
    |                      ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults
   --> $DIR/where-allowed.rs:219:40
    |
 LL | struct InStructGenericParamDefault<T = impl Debug>(T);
    |                                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults
   --> $DIR/where-allowed.rs:223:36
    |
 LL | enum InEnumGenericParamDefault<T = impl Debug> { Variant(T) }
    |                                    ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults
   --> $DIR/where-allowed.rs:227:38
    |
 LL | trait InTraitGenericParamDefault<T = impl Debug> {}
    |                                      ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults
   --> $DIR/where-allowed.rs:231:41
    |
 LL | type InTypeAliasGenericParamDefault<T = impl Debug> = T;
    |                                         ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults
   --> $DIR/where-allowed.rs:235:11
    |
 LL | impl <T = impl Debug> T {}
    |           ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generic parameter defaults
   --> $DIR/where-allowed.rs:242:40
    |
 LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    |                                        ^^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings
   --> $DIR/where-allowed.rs:248:29
    |
 LL |     let _in_local_variable: impl Fn() = || {};
    |                             ^^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in closure return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in closure return types
   --> $DIR/where-allowed.rs:250:46
    |
 LL |     let _in_return_in_local_variable = || -> impl Fn() { || {} };
diff --git a/tests/ui/imports/ambiguous-9.stderr b/tests/ui/imports/ambiguous-9.stderr
index 6c7d79174da..2731ed2ba86 100644
--- a/tests/ui/imports/ambiguous-9.stderr
+++ b/tests/ui/imports/ambiguous-9.stderr
@@ -60,6 +60,7 @@ note: `date_range` could also refer to the function imported here
 LL | use prelude::*;
    |     ^^^^^^^^^^
    = help: consider adding an explicit import of `date_range` to disambiguate
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 4 warnings emitted
 
diff --git a/tests/ui/imports/issue-55457.stderr b/tests/ui/imports/issue-55457.stderr
index 788fcc830ae..30d2373652b 100644
--- a/tests/ui/imports/issue-55457.stderr
+++ b/tests/ui/imports/issue-55457.stderr
@@ -38,6 +38,7 @@ LL | #[derive(NonExistent)]
    |          ^^^^^^^^^^^
    |
    = note: import resolution is stuck, try simplifying macro imports
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: cannot determine resolution for the derive macro `NonExistent`
   --> $DIR/issue-55457.rs:5:10
@@ -46,6 +47,7 @@ LL | #[derive(NonExistent)]
    |          ^^^^^^^^^^^
    |
    = note: import resolution is stuck, try simplifying macro imports
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr
index e020d029875..2cb212a0139 100644
--- a/tests/ui/indexing/index-help.stderr
+++ b/tests/ui/indexing/index-help.stderr
@@ -5,7 +5,8 @@ LL |     x[0i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `Vec<{integer}>` to implement `Index<i32>`
 
 error: aborting due to previous error
diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr
index 7a741cfc7de..6ea6bb600e9 100644
--- a/tests/ui/indexing/indexing-requires-a-uint.stderr
+++ b/tests/ui/indexing/indexing-requires-a-uint.stderr
@@ -5,7 +5,8 @@ LL |     [0][0u8];
    |         ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `u8`
    = note: required for `[{integer}]` to implement `Index<u8>`
 
 error[E0308]: mismatched types
diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr
index bbbb2a86a22..97e658617cf 100644
--- a/tests/ui/integral-indexing.stderr
+++ b/tests/ui/integral-indexing.stderr
@@ -5,7 +5,8 @@ LL |     v[3u8];
    |       ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u8`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `u8`
    = note: required for `Vec<isize>` to implement `Index<u8>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `i8`
@@ -15,7 +16,8 @@ LL |     v[3i8];
    |       ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i8`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `i8`
    = note: required for `Vec<isize>` to implement `Index<i8>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `u32`
@@ -25,7 +27,8 @@ LL |     v[3u32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u32`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `u32`
    = note: required for `Vec<isize>` to implement `Index<u32>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `i32`
@@ -35,7 +38,8 @@ LL |     v[3i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i32`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `Vec<isize>` to implement `Index<i32>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `u8`
@@ -45,7 +49,8 @@ LL |     s.as_bytes()[3u8];
    |                  ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u8`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `u8`
    = note: required for `[u8]` to implement `Index<u8>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `i8`
@@ -55,7 +60,8 @@ LL |     s.as_bytes()[3i8];
    |                  ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i8`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `i8`
    = note: required for `[u8]` to implement `Index<i8>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `u32`
@@ -65,7 +71,8 @@ LL |     s.as_bytes()[3u32];
    |                  ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u32`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `u32`
    = note: required for `[u8]` to implement `Index<u32>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `i32`
@@ -75,7 +82,8 @@ LL |     s.as_bytes()[3i32];
    |                  ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i32`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `[u8]` to implement `Index<i32>`
 
 error: aborting due to 8 previous errors
diff --git a/tests/ui/issues/issue-33571.stderr b/tests/ui/issues/issue-33571.stderr
index 2a9ba5ba71b..819a533ddbe 100644
--- a/tests/ui/issues/issue-33571.stderr
+++ b/tests/ui/issues/issue-33571.stderr
@@ -21,6 +21,7 @@ note: unsafe traits like `Sync` should be implemented explicitly
    |
 LL |          Sync,
    |          ^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/issues/issue-34334.stderr b/tests/ui/issues/issue-34334.stderr
index 9d2c315e4db..753942dd1d1 100644
--- a/tests/ui/issues/issue-34334.stderr
+++ b/tests/ui/issues/issue-34334.stderr
@@ -19,7 +19,8 @@ LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece
    |                                                                                       ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
-   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+   = help: the trait `FromIterator<(u32, _, _)>` is implemented for `Vec<(u32, _, _)>`
+   = help: for that trait implementation, expected `(u32, _, _)`, found `()`
 note: the method call chain might not have had the expected associated types
   --> $DIR/issue-34334.rs:5:43
    |
diff --git a/tests/ui/issues/issue-40000.stderr b/tests/ui/issues/issue-40000.stderr
index c41fbb9d2ec..0737a9610e2 100644
--- a/tests/ui/issues/issue-40000.stderr
+++ b/tests/ui/issues/issue-40000.stderr
@@ -15,6 +15,7 @@ LL |     foo(bar);
    |
    = note: expected trait object `dyn for<'a> Fn(&'a i32)`
               found trait object `dyn Fn(&i32)`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/issues/issue-45801.stderr b/tests/ui/issues/issue-45801.stderr
index 8967f49df02..e651e2a68d1 100644
--- a/tests/ui/issues/issue-45801.stderr
+++ b/tests/ui/issues/issue-45801.stderr
@@ -5,6 +5,7 @@ LL |     req.get_ref::<Params>();
    |         ^^^^^^^ the trait `Plugin<i32>` is not implemented for `Params`
    |
    = help: the trait `Plugin<Foo>` is implemented for `Params`
+   = help: for that trait implementation, expected `Foo`, found `i32`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-46101.stderr b/tests/ui/issues/issue-46101.stderr
index 40295b8a115..a0cdd5d5f05 100644
--- a/tests/ui/issues/issue-46101.stderr
+++ b/tests/ui/issues/issue-46101.stderr
@@ -9,6 +9,8 @@ error[E0433]: failed to resolve: partially resolved path in a derive macro
    |
 LL | #[derive(Foo::Anything)]
    |          ^^^^^^^^^^^^^ partially resolved path in a derive macro
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/issues/issue-47715.rs b/tests/ui/issues/issue-47715.rs
index b8088c18dad..0a770593bc9 100644
--- a/tests/ui/issues/issue-47715.rs
+++ b/tests/ui/issues/issue-47715.rs
@@ -7,22 +7,22 @@ trait Iterable {
 }
 
 struct Container<T: Iterable<Item = impl Foo>> {
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
     field: T
 }
 
 enum Enum<T: Iterable<Item = impl Foo>> {
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
     A(T),
 }
 
 union Union<T: Iterable<Item = impl Foo> + Copy> {
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
     x: T,
 }
 
 type Type<T: Iterable<Item = impl Foo>> = T;
-//~^ ERROR `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 
 fn main() {
 }
diff --git a/tests/ui/issues/issue-47715.stderr b/tests/ui/issues/issue-47715.stderr
index dadea34b688..2ded98781c6 100644
--- a/tests/ui/issues/issue-47715.stderr
+++ b/tests/ui/issues/issue-47715.stderr
@@ -1,22 +1,22 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics
   --> $DIR/issue-47715.rs:9:37
    |
 LL | struct Container<T: Iterable<Item = impl Foo>> {
    |                                     ^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics
   --> $DIR/issue-47715.rs:14:30
    |
 LL | enum Enum<T: Iterable<Item = impl Foo>> {
    |                              ^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics
   --> $DIR/issue-47715.rs:19:32
    |
 LL | union Union<T: Iterable<Item = impl Foo> + Copy> {
    |                                ^^^^^^^^
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in generics
   --> $DIR/issue-47715.rs:24:30
    |
 LL | type Type<T: Iterable<Item = impl Foo>> = T;
diff --git a/tests/ui/issues/issue-53251.stderr b/tests/ui/issues/issue-53251.stderr
index d5f14e8deb9..05ea6311589 100644
--- a/tests/ui/issues/issue-53251.stderr
+++ b/tests/ui/issues/issue-53251.stderr
@@ -32,6 +32,7 @@ note: associated function defined here, with 0 generic parameters
    |
 LL |     fn f() {}
    |        ^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
    = note: this error originates in the macro `impl_add` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/issues/issue-66667-function-cmp-cycle.stderr b/tests/ui/issues/issue-66667-function-cmp-cycle.stderr
index d9a960ce197..cec8117702a 100644
--- a/tests/ui/issues/issue-66667-function-cmp-cycle.stderr
+++ b/tests/ui/issues/issue-66667-function-cmp-cycle.stderr
@@ -19,7 +19,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-66667-function-cmp-cycle.rs:2:5
    |
 LL | fn first() {
-   |            - help: try adding a return type: `-> bool`
+   |           - help: try adding a return type: `-> bool`
 LL |     second == 1
    |     ^^^^^^^^^^^ expected `()`, found `bool`
 
@@ -44,7 +44,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-66667-function-cmp-cycle.rs:8:5
    |
 LL | fn second() {
-   |             - help: try adding a return type: `-> bool`
+   |            - help: try adding a return type: `-> bool`
 LL |     first == 1
    |     ^^^^^^^^^^ expected `()`, found `bool`
 
@@ -69,7 +69,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-66667-function-cmp-cycle.rs:14:5
    |
 LL | fn bar() {
-   |          - help: try adding a return type: `-> bool`
+   |         - help: try adding a return type: `-> bool`
 LL |     bar == 1
    |     ^^^^^^^^ expected `()`, found `bool`
 
diff --git a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr
index 22b1da64cb3..128288e28f5 100644
--- a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr
+++ b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr
@@ -5,7 +5,8 @@ LL |     let x2: Vec<f64> = x1.into_iter().collect();
    |                                       ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
-   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+   = help: the trait `FromIterator<f64>` is implemented for `Vec<f64>`
+   = help: for that trait implementation, expected `f64`, found `&f64`
 note: the method call chain might not have had the expected associated types
   --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27
    |
@@ -25,7 +26,8 @@ LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
    |                             required by a bound introduced by this call
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
-   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+   = help: the trait `FromIterator<f64>` is implemented for `Vec<f64>`
+   = help: for that trait implementation, expected `f64`, found `&f64`
 note: the method call chain might not have had the expected associated types
   --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17
    |
diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr
index b355da5cb76..2601c9c0d69 100644
--- a/tests/ui/iterators/invalid-iterator-chain.stderr
+++ b/tests/ui/iterators/invalid-iterator-chain.stderr
@@ -5,7 +5,8 @@ LL |     i.collect()
    |       ^^^^^^^ value of type `Vec<X>` cannot be built from `std::iter::Iterator<Item=&X>`
    |
    = help: the trait `FromIterator<&X>` is not implemented for `Vec<X>`
-   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+   = help: the trait `FromIterator<X>` is implemented for `Vec<X>`
+   = help: for that trait implementation, expected `X`, found `&X`
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain.rs:4:26
    |
@@ -159,7 +160,8 @@ LL |     let g: Vec<i32> = f.collect();
    |                         ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
-   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+   = help: the trait `FromIterator<i32>` is implemented for `Vec<i32>`
+   = help: for that trait implementation, expected `i32`, found `()`
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain.rs:44:15
    |
diff --git a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr
index 2bb29f911a1..14bfcc3d04d 100644
--- a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr
@@ -1,8 +1,8 @@
 error[E0308]: lang item `start` function has wrong type
-  --> $DIR/start_lang_item_args.rs:29:84
+  --> $DIR/start_lang_item_args.rs:29:83
    |
 LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
-   |                                                                                    ^ expected `isize`, found `()`
+   |                                                                                   ^ expected `isize`, found `()`
    |
    = note: expected signature `fn(fn() -> _, _, _, _) -> isize`
               found signature `fn(fn() -> _, _, _, _)`
diff --git a/tests/ui/lifetimes/issue-105675.stderr b/tests/ui/lifetimes/issue-105675.stderr
index 66415f72bcb..54ecd35ed6a 100644
--- a/tests/ui/lifetimes/issue-105675.stderr
+++ b/tests/ui/lifetimes/issue-105675.stderr
@@ -81,6 +81,7 @@ note: the lifetime requirement is introduced here
    |
 LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {}
    |                  ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider specifying the type of the closure parameters
    |
 LL |     let f = |x: &_, y: &_, z: u32| ();
diff --git a/tests/ui/limits/issue-55878.stderr b/tests/ui/limits/issue-55878.stderr
index 93716c0b347..6b463930b00 100644
--- a/tests/ui/limits/issue-55878.stderr
+++ b/tests/ui/limits/issue-55878.stderr
@@ -25,6 +25,7 @@ note: erroneous constant encountered
 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 previous error
diff --git a/tests/ui/lint/cli-unknown-force-warn.stderr b/tests/ui/lint/cli-unknown-force-warn.stderr
index 2ee718a8c8e..5084b4a4001 100644
--- a/tests/ui/lint/cli-unknown-force-warn.stderr
+++ b/tests/ui/lint/cli-unknown-force-warn.stderr
@@ -6,10 +6,12 @@ warning[E0602]: unknown lint: `foo_qux`
 warning[E0602]: unknown lint: `foo_qux`
    |
    = note: requested on the command line with `--force-warn foo_qux`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning[E0602]: unknown lint: `foo_qux`
    |
    = note: requested on the command line with `--force-warn foo_qux`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/lint/command-line-register-unknown-lint-tool.stderr b/tests/ui/lint/command-line-register-unknown-lint-tool.stderr
index c9a2aff2137..65aa1962830 100644
--- a/tests/ui/lint/command-line-register-unknown-lint-tool.stderr
+++ b/tests/ui/lint/command-line-register-unknown-lint-tool.stderr
@@ -5,6 +5,7 @@ error[E0602]: unknown lint tool: `unknown_tool`
 error[E0602]: unknown lint tool: `unknown_tool`
    |
    = note: requested on the command line with `-A unknown_tool::foo`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lint/crate_level_only_lint.stderr b/tests/ui/lint/crate_level_only_lint.stderr
index 8fb06df2a48..fbb1ec381c8 100644
--- a/tests/ui/lint/crate_level_only_lint.stderr
+++ b/tests/ui/lint/crate_level_only_lint.stderr
@@ -27,36 +27,48 @@ error: allow(uncommon_codepoints) is ignored unless specified at crate level
    |
 LL | #![allow(uncommon_codepoints)]
    |          ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
   --> $DIR/crate_level_only_lint.rs:9:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
   --> $DIR/crate_level_only_lint.rs:17:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
   --> $DIR/crate_level_only_lint.rs:4:10
    |
 LL | #![allow(uncommon_codepoints)]
    |          ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
   --> $DIR/crate_level_only_lint.rs:9:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
   --> $DIR/crate_level_only_lint.rs:17:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 9 previous errors
 
diff --git a/tests/ui/lint/forbid-group-group-2.stderr b/tests/ui/lint/forbid-group-group-2.stderr
index b2e2bcea1b4..4a2c8fbd68a 100644
--- a/tests/ui/lint/forbid-group-group-2.stderr
+++ b/tests/ui/lint/forbid-group-group-2.stderr
@@ -26,6 +26,7 @@ LL | #[allow(nonstandard_style)]
    |
    = 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: allow(nonstandard_style) incompatible with previous forbid
   --> $DIR/forbid-group-group-2.rs:7:9
@@ -38,6 +39,7 @@ LL | #[allow(nonstandard_style)]
    |
    = 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: allow(nonstandard_style) incompatible with previous forbid
   --> $DIR/forbid-group-group-2.rs:7:9
@@ -50,6 +52,7 @@ LL | #[allow(nonstandard_style)]
    |
    = 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: allow(nonstandard_style) incompatible with previous forbid
   --> $DIR/forbid-group-group-2.rs:7:9
@@ -62,6 +65,7 @@ LL | #[allow(nonstandard_style)]
    |
    = 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: allow(nonstandard_style) incompatible with previous forbid
   --> $DIR/forbid-group-group-2.rs:7:9
@@ -74,6 +78,7 @@ LL | #[allow(nonstandard_style)]
    |
    = 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: allow(nonstandard_style) incompatible with previous forbid
   --> $DIR/forbid-group-group-2.rs:7:9
@@ -86,6 +91,7 @@ LL | #[allow(nonstandard_style)]
    |
    = 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: allow(nonstandard_style) incompatible with previous forbid
   --> $DIR/forbid-group-group-2.rs:7:9
@@ -98,6 +104,7 @@ LL | #[allow(nonstandard_style)]
    |
    = 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: allow(nonstandard_style) incompatible with previous forbid
   --> $DIR/forbid-group-group-2.rs:7:9
@@ -110,6 +117,7 @@ LL | #[allow(nonstandard_style)]
    |
    = 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 9 previous errors
 
diff --git a/tests/ui/lint/forbid-group-member.stderr b/tests/ui/lint/forbid-group-member.stderr
index 47336d4d890..ddaaafa12ec 100644
--- a/tests/ui/lint/forbid-group-member.stderr
+++ b/tests/ui/lint/forbid-group-member.stderr
@@ -22,6 +22,7 @@ LL | #[allow(unused_variables)]
    |
    = 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: allow(unused_variables) incompatible with previous forbid
   --> $DIR/forbid-group-member.rs:8:9
@@ -34,6 +35,7 @@ LL | #[allow(unused_variables)]
    |
    = 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/lint/forbid-member-group.stderr b/tests/ui/lint/forbid-member-group.stderr
index e6530177833..612dccd8d6c 100644
--- a/tests/ui/lint/forbid-member-group.stderr
+++ b/tests/ui/lint/forbid-member-group.stderr
@@ -15,6 +15,8 @@ LL | #![forbid(unused_variables)]
 LL |
 LL | #[allow(unused)]
    |         ^^^^^^ overruled by previous forbid
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr
index 0f58953a54b..ecdc625015e 100644
--- a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr
+++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr
@@ -20,6 +20,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | pub fn function(_x: Box<dyn SomeTrait>) {}
@@ -33,6 +34,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | pub fn function(_x: Box<dyn SomeTrait>) {}
diff --git a/tests/ui/lint/force-warn/cap-lints-allow.stderr b/tests/ui/lint/force-warn/cap-lints-allow.stderr
index 03a32fa6f08..5f5f2ff52b6 100644
--- a/tests/ui/lint/force-warn/cap-lints-allow.stderr
+++ b/tests/ui/lint/force-warn/cap-lints-allow.stderr
@@ -20,6 +20,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | pub fn function(_x: Box<dyn SomeTrait>) {}
@@ -33,6 +34,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | pub fn function(_x: Box<dyn SomeTrait>) {}
diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr
index b0cd3ddd26f..3a0b1201b0c 100644
--- a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr
+++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr
@@ -21,6 +21,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | pub fn function(_x: Box<dyn SomeTrait>) {}
@@ -34,6 +35,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | pub fn function(_x: Box<dyn SomeTrait>) {}
diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr
index 8c841916c93..92555eda2a7 100644
--- a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr
+++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr
@@ -21,6 +21,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | pub fn function(_x: Box<dyn SomeTrait>) {}
@@ -34,6 +35,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | pub fn function(_x: Box<dyn SomeTrait>) {}
diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr
index c0144205d6a..c14c7957a25 100644
--- a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr
+++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr
@@ -21,6 +21,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | pub fn function(_x: Box<dyn SomeTrait>) {}
@@ -34,6 +35,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | pub fn function(_x: Box<dyn SomeTrait>) {}
diff --git a/tests/ui/lint/force-warn/warnings-lint-group.stderr b/tests/ui/lint/force-warn/warnings-lint-group.stderr
index 1faeed33704..3e73269a233 100644
--- a/tests/ui/lint/force-warn/warnings-lint-group.stderr
+++ b/tests/ui/lint/force-warn/warnings-lint-group.stderr
@@ -1,6 +1,8 @@
 error[E0602]: `warnings` lint group is not supported with ´--force-warn´
 
 error[E0602]: `warnings` lint group is not supported with ´--force-warn´
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lint/issue-80988.stderr b/tests/ui/lint/issue-80988.stderr
index 73e27ffda7f..7a65881b5ed 100644
--- a/tests/ui/lint/issue-80988.stderr
+++ b/tests/ui/lint/issue-80988.stderr
@@ -22,6 +22,7 @@ LL | #[deny(warnings)]
    |
    = 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: deny(warnings) incompatible with previous forbid
   --> $DIR/issue-80988.rs:7:8
@@ -34,6 +35,7 @@ LL | #[deny(warnings)]
    |
    = 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/lint/lint-forbid-attr.stderr b/tests/ui/lint/lint-forbid-attr.stderr
index 5977b9c949d..bd476a0e362 100644
--- a/tests/ui/lint/lint-forbid-attr.stderr
+++ b/tests/ui/lint/lint-forbid-attr.stderr
@@ -15,6 +15,8 @@ LL | #![forbid(deprecated)]
 LL |
 LL | #[allow(deprecated)]
    |         ^^^^^^^^^^ overruled by previous forbid
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lint/lint-forbid-cmdline.stderr b/tests/ui/lint/lint-forbid-cmdline.stderr
index 0a92e58c04a..ed49a2cb427 100644
--- a/tests/ui/lint/lint-forbid-cmdline.stderr
+++ b/tests/ui/lint/lint-forbid-cmdline.stderr
@@ -13,6 +13,7 @@ LL | #[allow(deprecated)]
    |         ^^^^^^^^^^ overruled by previous forbid
    |
    = note: `forbid` lint level was set on command line
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lint/lint-malformed.stderr b/tests/ui/lint/lint-malformed.stderr
index 91b4e509b26..2c9f045de71 100644
--- a/tests/ui/lint/lint-malformed.stderr
+++ b/tests/ui/lint/lint-malformed.stderr
@@ -9,6 +9,8 @@ error[E0452]: malformed lint attribute input
    |
 LL | #![allow(bar = "baz")]
    |          ^^^^^^^^^^^ bad attribute argument
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: malformed `deny` attribute input
   --> $DIR/lint-malformed.rs:1:1
@@ -21,12 +23,16 @@ error[E0452]: malformed lint attribute input
    |
 LL | #![allow(bar = "baz")]
    |          ^^^^^^^^^^^ bad attribute argument
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0452]: malformed lint attribute input
   --> $DIR/lint-malformed.rs:2:10
    |
 LL | #![allow(bar = "baz")]
    |          ^^^^^^^^^^^ bad attribute argument
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/lint/lint-removed-cmdline-deny.stderr b/tests/ui/lint/lint-removed-cmdline-deny.stderr
index 80c85d01e53..3321afa7fcd 100644
--- a/tests/ui/lint/lint-removed-cmdline-deny.stderr
+++ b/tests/ui/lint/lint-removed-cmdline-deny.stderr
@@ -6,10 +6,12 @@ error: lint `raw_pointer_derive` has been removed: using derive with raw pointer
 error: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
    |
    = note: requested on the command line with `-D raw_pointer_derive`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
    |
    = note: requested on the command line with `-D raw_pointer_derive`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: unused variable: `unused`
   --> $DIR/lint-removed-cmdline-deny.rs:13:17
diff --git a/tests/ui/lint/lint-removed-cmdline.stderr b/tests/ui/lint/lint-removed-cmdline.stderr
index ebfae34ade9..6b76ad3b578 100644
--- a/tests/ui/lint/lint-removed-cmdline.stderr
+++ b/tests/ui/lint/lint-removed-cmdline.stderr
@@ -6,10 +6,12 @@ warning: lint `raw_pointer_derive` has been removed: using derive with raw point
 warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
    |
    = note: requested on the command line with `-D raw_pointer_derive`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
    |
    = note: requested on the command line with `-D raw_pointer_derive`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: unused variable: `unused`
   --> $DIR/lint-removed-cmdline.rs:13:17
diff --git a/tests/ui/lint/lint-renamed-cmdline-deny.stderr b/tests/ui/lint/lint-renamed-cmdline-deny.stderr
index df22ef60daf..0e182a4e5de 100644
--- a/tests/ui/lint/lint-renamed-cmdline-deny.stderr
+++ b/tests/ui/lint/lint-renamed-cmdline-deny.stderr
@@ -8,11 +8,13 @@ error: lint `bare_trait_object` has been renamed to `bare_trait_objects`
    |
    = help: use the new name `bare_trait_objects`
    = note: requested on the command line with `-D bare_trait_object`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: lint `bare_trait_object` has been renamed to `bare_trait_objects`
    |
    = help: use the new name `bare_trait_objects`
    = note: requested on the command line with `-D bare_trait_object`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: unused variable: `unused`
   --> $DIR/lint-renamed-cmdline-deny.rs:10:17
diff --git a/tests/ui/lint/lint-renamed-cmdline.stderr b/tests/ui/lint/lint-renamed-cmdline.stderr
index a41284003ed..675443ddedf 100644
--- a/tests/ui/lint/lint-renamed-cmdline.stderr
+++ b/tests/ui/lint/lint-renamed-cmdline.stderr
@@ -8,11 +8,13 @@ warning: lint `bare_trait_object` has been renamed to `bare_trait_objects`
    |
    = help: use the new name `bare_trait_objects`
    = note: requested on the command line with `-D bare_trait_object`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: lint `bare_trait_object` has been renamed to `bare_trait_objects`
    |
    = help: use the new name `bare_trait_objects`
    = note: requested on the command line with `-D bare_trait_object`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: unused variable: `unused`
   --> $DIR/lint-renamed-cmdline.rs:9:17
diff --git a/tests/ui/lint/lint-stability-deprecated.stderr b/tests/ui/lint/lint-stability-deprecated.stderr
index 19a4649e168..609fc56a8ae 100644
--- a/tests/ui/lint/lint-stability-deprecated.stderr
+++ b/tests/ui/lint/lint-stability-deprecated.stderr
@@ -639,18 +639,24 @@ warning: use of deprecated associated type `lint_stability::TraitWithAssociatedT
    |
 LL |         struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
    |                                                ^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
   --> $DIR/lint-stability-deprecated.rs:102:13
    |
 LL |             TypeDeprecated = u16,
    |             ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
   --> $DIR/lint-stability-deprecated.rs:102:13
    |
 LL |             TypeDeprecated = u16,
    |             ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 108 warnings emitted
 
diff --git a/tests/ui/lint/lint-unexported-no-mangle.stderr b/tests/ui/lint/lint-unexported-no-mangle.stderr
index 85852782222..0efec51abaf 100644
--- a/tests/ui/lint/lint-unexported-no-mangle.stderr
+++ b/tests/ui/lint/lint-unexported-no-mangle.stderr
@@ -10,18 +10,22 @@ warning: lint `private_no_mangle_statics` has been removed: no longer a warning,
 warning: lint `private_no_mangle_fns` has been removed: no longer a warning, `#[no_mangle]` functions always exported
    |
    = note: requested on the command line with `-F private_no_mangle_fns`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: lint `private_no_mangle_statics` has been removed: no longer a warning, `#[no_mangle]` statics always exported
    |
    = note: requested on the command line with `-F private_no_mangle_statics`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: lint `private_no_mangle_fns` has been removed: no longer a warning, `#[no_mangle]` functions always exported
    |
    = note: requested on the command line with `-F private_no_mangle_fns`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: lint `private_no_mangle_statics` has been removed: no longer a warning, `#[no_mangle]` statics always exported
    |
    = note: requested on the command line with `-F private_no_mangle_statics`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: const items should never be `#[no_mangle]`
   --> $DIR/lint-unexported-no-mangle.rs:9:1
diff --git a/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr b/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr
index 677b5edc894..f12ce03ddfc 100644
--- a/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr
+++ b/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr
@@ -11,20 +11,24 @@ error[E0602]: unknown lint: `dead_cod`
 error[E0602]: unknown lint: `bogus`
    |
    = note: requested on the command line with `-D bogus`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0602]: unknown lint: `dead_cod`
    |
    = help: did you mean: `dead_code`
    = note: requested on the command line with `-D dead_cod`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0602]: unknown lint: `bogus`
    |
    = note: requested on the command line with `-D bogus`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0602]: unknown lint: `dead_cod`
    |
    = help: did you mean: `dead_code`
    = note: requested on the command line with `-D dead_cod`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.stderr b/tests/ui/lint/lint-unknown-lint-cmdline.stderr
index 10db76ac4f1..f452fc9eb94 100644
--- a/tests/ui/lint/lint-unknown-lint-cmdline.stderr
+++ b/tests/ui/lint/lint-unknown-lint-cmdline.stderr
@@ -11,20 +11,24 @@ warning[E0602]: unknown lint: `dead_cod`
 warning[E0602]: unknown lint: `bogus`
    |
    = note: requested on the command line with `-D bogus`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning[E0602]: unknown lint: `dead_cod`
    |
    = help: did you mean: `dead_code`
    = note: requested on the command line with `-D dead_cod`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning[E0602]: unknown lint: `bogus`
    |
    = note: requested on the command line with `-D bogus`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning[E0602]: unknown lint: `dead_cod`
    |
    = help: did you mean: `dead_code`
    = note: requested on the command line with `-D dead_cod`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 6 warnings emitted
 
diff --git a/tests/ui/lint/must_not_suspend/gated.stderr b/tests/ui/lint/must_not_suspend/gated.stderr
index 64de1ebeaab..f0d2117d42b 100644
--- a/tests/ui/lint/must_not_suspend/gated.stderr
+++ b/tests/ui/lint/must_not_suspend/gated.stderr
@@ -18,6 +18,7 @@ LL | #![deny(must_not_suspend)]
    = note: the `must_not_suspend` lint is unstable
    = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
    = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `must_not_suspend`
   --> $DIR/gated.rs:4:1
@@ -28,6 +29,7 @@ LL | #![deny(must_not_suspend)]
    = note: the `must_not_suspend` lint is unstable
    = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
    = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/lint/reasons-erroneous.rs b/tests/ui/lint/reasons-erroneous.rs
index cd693ae166c..7b286eb1d18 100644
--- a/tests/ui/lint/reasons-erroneous.rs
+++ b/tests/ui/lint/reasons-erroneous.rs
@@ -1,51 +1,27 @@
+// compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![feature(lint_reasons)]
 
 #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
 //~^ ERROR malformed lint attribute
-//~| ERROR malformed lint attribute
-//~| NOTE reason must be a string literal
 //~| NOTE reason must be a string literal
 #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
 //~^ ERROR malformed lint attribute
-//~| ERROR malformed lint attribute
-//~| NOTE reason must be a string literal
 //~| NOTE reason must be a string literal
 #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
 //~^ ERROR malformed lint attribute
-//~| ERROR malformed lint attribute
-//~| ERROR malformed lint attribute
-//~| ERROR malformed lint attribute
-//~| NOTE bad attribute argument
-//~| NOTE bad attribute argument
-//~| NOTE bad attribute argument
 //~| NOTE bad attribute argument
 #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
 //~^ ERROR malformed lint attribute
-//~| ERROR malformed lint attribute
-//~| ERROR malformed lint attribute
-//~| ERROR malformed lint attribute
-//~| NOTE bad attribute argument
-//~| NOTE bad attribute argument
-//~| NOTE bad attribute argument
 //~| NOTE bad attribute argument
 #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
 //~^ ERROR malformed lint attribute
-//~| ERROR malformed lint attribute
-//~| ERROR malformed lint attribute
-//~| ERROR malformed lint attribute
-//~| NOTE bad attribute argument
-//~| NOTE bad attribute argument
-//~| NOTE bad attribute argument
 //~| NOTE bad attribute argument
 #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
 //~^ ERROR malformed lint attribute
-//~| ERROR malformed lint attribute
-//~| NOTE reason in lint attribute must come last
 //~| NOTE reason in lint attribute must come last
 #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
 //~^ ERROR malformed lint attribute
-//~| ERROR malformed lint attribute
-//~| NOTE reason in lint attribute must come last
 //~| NOTE reason in lint attribute must come last
 #![warn(missing_copy_implementations, reason)]
 //~^ WARN unknown lint
diff --git a/tests/ui/lint/reasons-erroneous.stderr b/tests/ui/lint/reasons-erroneous.stderr
index 5521af17c84..003da567370 100644
--- a/tests/ui/lint/reasons-erroneous.stderr
+++ b/tests/ui/lint/reasons-erroneous.stderr
@@ -1,5 +1,5 @@
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:3:58
+  --> $DIR/reasons-erroneous.rs:5:58
    |
 LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
    |                                                          ^ reason must be a string literal
@@ -11,121 +11,43 @@ LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condem
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:13:29
+  --> $DIR/reasons-erroneous.rs:11:29
    |
 LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:13:29
-   |
-LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
-
-error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:22:23
-   |
-LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
-
-error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:22:23
-   |
-LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
-
-error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:31:36
-   |
-LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
-
-error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:31:36
-   |
-LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
-
-error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:40:44
-   |
-LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
-   |                                            ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
-
-error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:45:25
-   |
-LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
-
-error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:3:58
-   |
-LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
-   |                                                          ^ reason must be a string literal
-
-error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:8:40
-   |
-LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
-   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal
-
-error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:13:29
-   |
-LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
-
-error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:13:29
-   |
-LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
-
-error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:22:23
-   |
-LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
-
-error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:22:23
+  --> $DIR/reasons-erroneous.rs:14:23
    |
 LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")]
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:31:36
-   |
-LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
-
-error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:31:36
+  --> $DIR/reasons-erroneous.rs:17:36
    |
 LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:40:44
+  --> $DIR/reasons-erroneous.rs:20:44
    |
 LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
    |                                            ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/reasons-erroneous.rs:45:25
+  --> $DIR/reasons-erroneous.rs:23:25
    |
 LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
 
 warning: unknown lint: `reason`
-  --> $DIR/reasons-erroneous.rs:50:39
+  --> $DIR/reasons-erroneous.rs:26:39
    |
 LL | #![warn(missing_copy_implementations, reason)]
    |                                       ^^^^^^
    |
    = note: `#[warn(unknown_lints)]` on by default
 
-error: aborting due to 20 previous errors; 1 warning emitted
+error: aborting due to 7 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0452`.
diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs
index fba8789e999..25e0c75f70d 100644
--- a/tests/ui/lint/reference_casting.rs
+++ b/tests/ui/lint/reference_casting.rs
@@ -64,6 +64,10 @@ unsafe fn ref_to_mut() {
     let _num = &mut *num;
     //~^ ERROR casting `&T` to `&mut T` is undefined behavior
 
+    let cell = &std::cell::UnsafeCell::new(0);
+    let _num = &mut *(cell as *const _ as *mut i32);
+    //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+
     unsafe fn generic_ref_cast_mut<T>(this: &T) -> &mut T {
         &mut *((this as *const _) as *mut _)
         //~^ ERROR casting `&T` to `&mut T` is undefined behavior
@@ -106,6 +110,8 @@ unsafe fn assign_to_ref() {
         std::mem::transmute::<*const i32, *mut i32>(num),
         -1i32,
     );
+    *((&std::cell::UnsafeCell::new(0)) as *const _ as *mut i32) = 5;
+    //~^ ERROR assigning to `&T` is undefined behavior
 
     let value = num as *const i32 as *mut i32;
     *value = 1;
@@ -148,6 +154,8 @@ unsafe fn no_warn() {
     *RAW_PTR = 42; // RAW_PTR is defined outside the function body,
                    // make sure we don't ICE on it when trying to
                    // determine if we should lint on it or not.
+    let cell = &std::cell::UnsafeCell::new(0);
+    let _num = &mut *(cell.get() as *mut i32);
 
     fn safe_as_mut<T>(x: &std::cell::UnsafeCell<T>) -> &mut T {
         unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr
index 8f89cf9805b..8d5f8da6852 100644
--- a/tests/ui/lint/reference_casting.stderr
+++ b/tests/ui/lint/reference_casting.stderr
@@ -158,7 +158,16 @@ LL |     let _num = &mut *num;
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:68:9
+  --> $DIR/reference_casting.rs:68:16
+   |
+LL |     let _num = &mut *(cell as *const _ as *mut i32);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
+   = note: even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get`
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:72:9
    |
 LL |         &mut *((this as *const _) as *mut _)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -166,7 +175,7 @@ LL |         &mut *((this as *const _) as *mut _)
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:73:18
+  --> $DIR/reference_casting.rs:77:18
    |
 LL |         unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -174,7 +183,7 @@ LL |         unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *con
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:78:18
+  --> $DIR/reference_casting.rs:82:18
    |
 LL |         unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -182,7 +191,7 @@ LL |         unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *con
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:88:5
+  --> $DIR/reference_casting.rs:92:5
    |
 LL |     *(a as *const _ as *mut _) = String::from("Replaced");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -190,7 +199,7 @@ LL |     *(a as *const _ as *mut _) = String::from("Replaced");
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:90:5
+  --> $DIR/reference_casting.rs:94:5
    |
 LL |     *(a as *const _ as *mut String) += " world";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -198,7 +207,7 @@ LL |     *(a as *const _ as *mut String) += " world";
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:92:5
+  --> $DIR/reference_casting.rs:96:5
    |
 LL |     *std::ptr::from_ref(num).cast_mut() += 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -206,7 +215,7 @@ LL |     *std::ptr::from_ref(num).cast_mut() += 1;
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:94:5
+  --> $DIR/reference_casting.rs:98:5
    |
 LL |     *std::ptr::from_ref({ num }).cast_mut() += 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -214,7 +223,7 @@ LL |     *std::ptr::from_ref({ num }).cast_mut() += 1;
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:96:5
+  --> $DIR/reference_casting.rs:100:5
    |
 LL |     *{ std::ptr::from_ref(num) }.cast_mut() += 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -222,7 +231,7 @@ LL |     *{ std::ptr::from_ref(num) }.cast_mut() += 1;
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:98:5
+  --> $DIR/reference_casting.rs:102:5
    |
 LL |     *(std::ptr::from_ref({ num }) as *mut i32) += 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -230,7 +239,7 @@ LL |     *(std::ptr::from_ref({ num }) as *mut i32) += 1;
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:100:5
+  --> $DIR/reference_casting.rs:104:5
    |
 LL |     *std::mem::transmute::<_, *mut i32>(num) += 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -238,7 +247,7 @@ LL |     *std::mem::transmute::<_, *mut i32>(num) += 1;
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:102:5
+  --> $DIR/reference_casting.rs:106:5
    |
 LL |     *(std::mem::transmute::<_, *mut i32>(num) as *mut i32) += 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -246,7 +255,7 @@ LL |     *(std::mem::transmute::<_, *mut i32>(num) as *mut i32) += 1;
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:104:5
+  --> $DIR/reference_casting.rs:108:5
    |
 LL | /     std::ptr::write(
 LL | |
@@ -258,7 +267,16 @@ LL | |     );
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:111:5
+  --> $DIR/reference_casting.rs:113:5
+   |
+LL |     *((&std::cell::UnsafeCell::new(0)) as *const _ as *mut i32) = 5;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
+   = note: even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get`
+
+error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:117:5
    |
 LL |     let value = num as *const i32 as *mut i32;
    |                 ----------------------------- casting happend here
@@ -268,7 +286,7 @@ LL |     *value = 1;
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:114:5
+  --> $DIR/reference_casting.rs:120:5
    |
 LL |     let value = num as *const i32 as *mut i32;
    |                 ----------------------------- casting happend here
@@ -279,7 +297,7 @@ LL |     *value_rebind = 1;
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:116:5
+  --> $DIR/reference_casting.rs:122:5
    |
 LL |     *(num as *const i32).cast::<i32>().cast_mut() = 2;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -287,7 +305,7 @@ LL |     *(num as *const i32).cast::<i32>().cast_mut() = 2;
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:118:5
+  --> $DIR/reference_casting.rs:124:5
    |
 LL |     *(num as *const _ as usize as *mut i32) = 2;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -295,7 +313,7 @@ LL |     *(num as *const _ as usize as *mut i32) = 2;
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:120:5
+  --> $DIR/reference_casting.rs:126:5
    |
 LL |     let value = num as *const i32 as *mut i32;
    |                 ----------------------------- casting happend here
@@ -306,7 +324,7 @@ LL |     std::ptr::write(value, 2);
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:122:5
+  --> $DIR/reference_casting.rs:128:5
    |
 LL |     let value = num as *const i32 as *mut i32;
    |                 ----------------------------- casting happend here
@@ -317,7 +335,7 @@ LL |     std::ptr::write_unaligned(value, 2);
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:124:5
+  --> $DIR/reference_casting.rs:130:5
    |
 LL |     let value = num as *const i32 as *mut i32;
    |                 ----------------------------- casting happend here
@@ -328,12 +346,12 @@ LL |     std::ptr::write_volatile(value, 2);
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:128:9
+  --> $DIR/reference_casting.rs:134:9
    |
 LL |         *(this as *const _ as *mut _) = a;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
 
-error: aborting due to 38 previous errors
+error: aborting due to 40 previous errors
 
diff --git a/tests/ui/lint/register-tool-lint.stderr b/tests/ui/lint/register-tool-lint.stderr
index 842d845ff7c..7ebdbdec929 100644
--- a/tests/ui/lint/register-tool-lint.stderr
+++ b/tests/ui/lint/register-tool-lint.stderr
@@ -13,6 +13,7 @@ LL | #![warn(abc::my_lint)]
    |         ^^^
    |
    = help: add `#![register_tool(abc)]` to the crate root
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs
new file mode 100644
index 00000000000..1e2ff12a206
--- /dev/null
+++ b/tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs
@@ -0,0 +1,30 @@
+// check-pass
+// incremental
+
+#![feature(lint_reasons)]
+#![warn(unused)]
+
+struct OneUnused;
+struct TwoUnused;
+
+impl OneUnused {
+    #[expect(unused)]
+    fn unused() {}
+}
+
+impl TwoUnused {
+    #[expect(unused)]
+    fn unused1(){}
+
+    // This unused method has `#[expect(unused)]`, so the compiler should not emit a warning.
+    // This ui test was added after a regression in the compiler where it did not recognize multiple
+    // `#[expect(unused)]` annotations inside of impl blocks.
+    // issue 114416
+    #[expect(unused)]
+    fn unused2(){}
+}
+
+fn main() {
+    let _ = OneUnused;
+    let _ = TwoUnused;
+}
diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs
index 479ee198e17..77cb5e88bf7 100644
--- a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs
+++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs
@@ -1,24 +1,20 @@
+// compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![feature(lint_reasons)]
 
 #[forbid(unused_variables)]
 //~^ NOTE `forbid` level set here
-//~| NOTE `forbid` level set here
 #[expect(unused_variables)]
 //~^ ERROR incompatible with previous forbid [E0453]
 //~| NOTE overruled by previous forbid
-//~| ERROR incompatible with previous forbid [E0453]
-//~| NOTE overruled by previous forbid
 fn expect_forbidden_lint_1() {}
 
 #[forbid(while_true)]
 //~^ NOTE `forbid` level set here
-//~| NOTE `forbid` level set here
 //~| NOTE the lint level is defined here
 #[expect(while_true)]
 //~^ ERROR incompatible with previous forbid [E0453]
 //~| NOTE overruled by previous forbid
-//~| ERROR incompatible with previous forbid [E0453]
-//~| NOTE overruled by previous forbid
 fn expect_forbidden_lint_2() {
     // This while loop will produce a `while_true` lint as the lint level
     // at this node is still `forbid` and the `while_true` check happens
diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr
index a8116e93404..0f42ffbdea3 100644
--- a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr
+++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr
@@ -1,32 +1,14 @@
 error[E0453]: expect(unused_variables) incompatible with previous forbid
-  --> $DIR/expect_with_forbid.rs:6:10
+  --> $DIR/expect_with_forbid.rs:7:10
    |
 LL | #[forbid(unused_variables)]
    |          ---------------- `forbid` level set here
-...
-LL | #[expect(unused_variables)]
-   |          ^^^^^^^^^^^^^^^^ overruled by previous forbid
-
-error[E0453]: expect(while_true) incompatible with previous forbid
-  --> $DIR/expect_with_forbid.rs:17:10
-   |
-LL | #[forbid(while_true)]
-   |          ---------- `forbid` level set here
-...
-LL | #[expect(while_true)]
-   |          ^^^^^^^^^^ overruled by previous forbid
-
-error[E0453]: expect(unused_variables) incompatible with previous forbid
-  --> $DIR/expect_with_forbid.rs:6:10
-   |
-LL | #[forbid(unused_variables)]
-   |          ---------------- `forbid` level set here
-...
+LL |
 LL | #[expect(unused_variables)]
    |          ^^^^^^^^^^^^^^^^ overruled by previous forbid
 
 error[E0453]: expect(while_true) incompatible with previous forbid
-  --> $DIR/expect_with_forbid.rs:17:10
+  --> $DIR/expect_with_forbid.rs:15:10
    |
 LL | #[forbid(while_true)]
    |          ---------- `forbid` level set here
@@ -35,17 +17,17 @@ LL | #[expect(while_true)]
    |          ^^^^^^^^^^ overruled by previous forbid
 
 error: denote infinite loops with `loop { ... }`
-  --> $DIR/expect_with_forbid.rs:26:5
+  --> $DIR/expect_with_forbid.rs:22:5
    |
 LL |     while true {}
    |     ^^^^^^^^^^ help: use `loop`
    |
 note: the lint level is defined here
-  --> $DIR/expect_with_forbid.rs:13:10
+  --> $DIR/expect_with_forbid.rs:12:10
    |
 LL | #[forbid(while_true)]
    |          ^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/tests/ui/loops/loop-break-value.stderr b/tests/ui/loops/loop-break-value.stderr
index 6c83bc7575c..a691960f962 100644
--- a/tests/ui/loops/loop-break-value.stderr
+++ b/tests/ui/loops/loop-break-value.stderr
@@ -319,7 +319,7 @@ error[E0308]: mismatched types
   --> $DIR/loop-break-value.rs:159:15
    |
 LL | fn main() {
-   |           - expected `()` because of this return type
+   |          - expected `()` because of this return type
 ...
 LL |     loop { // point at the return type
    |     ---- this loop is expected to be of type `()`
diff --git a/tests/ui/lub-glb/old-lub-glb-object.stderr b/tests/ui/lub-glb/old-lub-glb-object.stderr
index 3d0c171e013..c476d6f692b 100644
--- a/tests/ui/lub-glb/old-lub-glb-object.stderr
+++ b/tests/ui/lub-glb/old-lub-glb-object.stderr
@@ -15,6 +15,7 @@ LL |         _ => y,
    |
    = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>`
               found trait object `dyn for<'a> Foo<&'a u8, &'a u8>`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/macros/builtin-std-paths-fail.stderr b/tests/ui/macros/builtin-std-paths-fail.stderr
index 004a39043b7..331943843c0 100644
--- a/tests/ui/macros/builtin-std-paths-fail.stderr
+++ b/tests/ui/macros/builtin-std-paths-fail.stderr
@@ -15,12 +15,16 @@ error[E0433]: failed to resolve: could not find `RustcDecodable` in `core`
    |
 LL |     core::RustcDecodable,
    |           ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0433]: failed to resolve: could not find `RustcDecodable` in `core`
   --> $DIR/builtin-std-paths-fail.rs:4:11
    |
 LL |     core::RustcDecodable,
    |           ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0433]: failed to resolve: could not find `bench` in `core`
   --> $DIR/builtin-std-paths-fail.rs:7:9
@@ -63,12 +67,16 @@ error[E0433]: failed to resolve: could not find `RustcDecodable` in `std`
    |
 LL |     std::RustcDecodable,
    |          ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0433]: failed to resolve: could not find `RustcDecodable` in `std`
   --> $DIR/builtin-std-paths-fail.rs:16:10
    |
 LL |     std::RustcDecodable,
    |          ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0433]: failed to resolve: could not find `bench` in `std`
   --> $DIR/builtin-std-paths-fail.rs:19:8
diff --git a/tests/ui/macros/meta-item-absolute-path.stderr b/tests/ui/macros/meta-item-absolute-path.stderr
index c53971e245f..f0d763d7abb 100644
--- a/tests/ui/macros/meta-item-absolute-path.stderr
+++ b/tests/ui/macros/meta-item-absolute-path.stderr
@@ -9,6 +9,8 @@ error[E0433]: failed to resolve: maybe a missing crate `Absolute`?
    |
 LL | #[derive(::Absolute)]
    |            ^^^^^^^^ maybe a missing crate `Absolute`?
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs
index 816f99baa84..8b4e6250a30 100644
--- a/tests/ui/macros/stringify.rs
+++ b/tests/ui/macros/stringify.rs
@@ -3,6 +3,7 @@
 // compile-flags: --test
 
 #![feature(async_closure)]
+#![feature(auto_traits)]
 #![feature(box_patterns)]
 #![feature(const_trait_impl)]
 #![feature(decl_macro)]
diff --git a/tests/ui/mismatched_types/issue-19109.stderr b/tests/ui/mismatched_types/issue-19109.stderr
index 5cef64bb169..ca819d93a50 100644
--- a/tests/ui/mismatched_types/issue-19109.stderr
+++ b/tests/ui/mismatched_types/issue-19109.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-19109.rs:4:5
    |
 LL | fn function(t: &mut dyn Trait) {
-   |                                - help: try adding a return type: `-> *mut dyn Trait`
+   |                               - help: try adding a return type: `-> *mut dyn Trait`
 LL |     t as *mut dyn Trait
    |     ^^^^^^^^^^^^^^^^^^^ expected `()`, found `*mut dyn Trait`
    |
diff --git a/tests/ui/native-library-link-flags/modifiers-override.stderr b/tests/ui/native-library-link-flags/modifiers-override.stderr
index eb3ab55c310..64427651e9f 100644
--- a/tests/ui/native-library-link-flags/modifiers-override.stderr
+++ b/tests/ui/native-library-link-flags/modifiers-override.stderr
@@ -21,6 +21,8 @@ error: overriding linking modifiers from command line is not supported
    |
 LL | extern "C" {}
    | ^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
index 54c16230fe6..cb378630589 100644
--- a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
+++ b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
@@ -5,6 +5,7 @@ LL |     <E as From<_>>::from(never);
    |      ^ the trait `From<()>` is not implemented for `E`
    |
    = help: the trait `From<!>` is implemented for `E`
+   = help: for that trait implementation, expected `!`, found `()`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/nll/closure-malformed-projection-input-issue-102800.stderr b/tests/ui/nll/closure-malformed-projection-input-issue-102800.stderr
index 46dba006433..aeb0a1394cc 100644
--- a/tests/ui/nll/closure-malformed-projection-input-issue-102800.stderr
+++ b/tests/ui/nll/closure-malformed-projection-input-issue-102800.stderr
@@ -15,6 +15,7 @@ LL |     let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
    |
    = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
    = note: ...but `Trait` is actually implemented for the type `&'static ()`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/issue-97997.stderr b/tests/ui/nll/issue-97997.stderr
index 46440c021f5..89eaf77adf0 100644
--- a/tests/ui/nll/issue-97997.stderr
+++ b/tests/ui/nll/issue-97997.stderr
@@ -15,6 +15,7 @@ LL |     <fn(&u8) as Foo>::ASSOC;
    |
    = note: `Foo` would have to be implemented for the type `for<'a> fn(&'a u8)`
    = note: ...but `Foo` is actually implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr
index c3dd4257a73..988eee61027 100644
--- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr
+++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr
@@ -38,6 +38,7 @@ LL |     accept(callback);
    |
    = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0308]: mismatched types
   --> $DIR/missing-universe-cause-issue-114907.rs:33:5
@@ -73,6 +74,8 @@ error: higher-ranked subtype error
    |
 LL |     accept(callback);
    |                     ^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr
index b945ffedda5..804071a3e6f 100644
--- a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr
+++ b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr
@@ -15,6 +15,7 @@ LL |     let _x = <fn(&())>::make_f();
    |
    = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())`
    = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: implementation of `Y` is not general enough
   --> $DIR/impl-fn-ignore-binder-via-bottom.rs:30:14
@@ -24,6 +25,7 @@ LL |     let _x = <fn(&())>::make_f();
    |
    = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())`
    = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/nll/type-check-pointer-comparisons.stderr b/tests/ui/nll/type-check-pointer-comparisons.stderr
index 0d8480a42c1..37098b585df 100644
--- a/tests/ui/nll/type-check-pointer-comparisons.stderr
+++ b/tests/ui/nll/type-check-pointer-comparisons.stderr
@@ -61,6 +61,8 @@ LL |     x == y;
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 help: `'a` and `'b` must be the same: replace one with the other
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-comparisons.rs:16:5
@@ -93,6 +95,8 @@ LL |     f == g;
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 help: `'a` and `'b` must be the same: replace one with the other
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/nll/user-annotations/normalization-2.stderr b/tests/ui/nll/user-annotations/normalization-2.stderr
index 6b0dcb414ae..dcf049a7a61 100644
--- a/tests/ui/nll/user-annotations/normalization-2.stderr
+++ b/tests/ui/nll/user-annotations/normalization-2.stderr
@@ -131,6 +131,7 @@ help: the following changes may resolve your lifetime errors
    |
    = help: replace `'a` with `'static`
    = help: replace `'b` with `'static`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: lifetime may not live long enough
   --> $DIR/normalization-2.rs:89:5
@@ -185,6 +186,7 @@ help: the following changes may resolve your lifetime errors
    |
    = help: replace `'a` with `'static`
    = help: replace `'b` with `'static`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: lifetime may not live long enough
   --> $DIR/normalization-2.rs:117:5
diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr
index d0a4179fe3e..659679e4440 100644
--- a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr
+++ b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr
@@ -14,6 +14,7 @@ LL | fn foo(_: &dyn Foo<Bar = ()>) {}
    |                    ^^^^^^^^ help: remove this bound
    |
    = note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`.
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unnecessary associated type bound for not object safe associated type
   --> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20
@@ -22,6 +23,7 @@ LL | fn foo(_: &dyn Foo<Bar = ()>) {}
    |                    ^^^^^^^^ help: remove this bound
    |
    = note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`.
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/offset-of/offset-of-output-type.stderr b/tests/ui/offset-of/offset-of-output-type.stderr
index 6133f3263ab..233d4987643 100644
--- a/tests/ui/offset-of/offset-of-output-type.stderr
+++ b/tests/ui/offset-of/offset-of-output-type.stderr
@@ -42,7 +42,7 @@ error[E0308]: mismatched types
   --> $DIR/offset-of-output-type.rs:19:5
    |
 LL | fn main() {
-   |           - expected `()` because of default return type
+   |          - expected `()` because of default return type
 ...
 LL |     offset_of!(S, v)
    |     ^^^^^^^^^^^^^^^^ expected `()`, found `usize`
diff --git a/tests/ui/on-unimplemented/impl-substs.stderr b/tests/ui/on-unimplemented/impl-substs.stderr
index a0fad0acd0b..36d80f3e681 100644
--- a/tests/ui/on-unimplemented/impl-substs.stderr
+++ b/tests/ui/on-unimplemented/impl-substs.stderr
@@ -7,7 +7,8 @@ LL |     Foo::<usize>::foo((1i32, 1i32, 1i32));
    |     required by a bound introduced by this call
    |
    = help: the trait `Foo<usize>` is not implemented for `(i32, i32, i32)`
-   = help: the trait `Foo<A>` is implemented for `(A, B, C)`
+   = help: the trait `Foo<i32>` is implemented for `(i32, i32, i32)`
+   = help: for that trait implementation, expected `i32`, found `usize`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/on-unimplemented/on-impl.stderr b/tests/ui/on-unimplemented/on-impl.stderr
index 2253c5992a6..3a0b8353fa5 100644
--- a/tests/ui/on-unimplemented/on-impl.stderr
+++ b/tests/ui/on-unimplemented/on-impl.stderr
@@ -8,6 +8,7 @@ LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
    = help: the trait `Index<usize>` is implemented for `[i32]`
+   = help: for that trait implementation, expected `usize`, found `u32`
 
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/on-impl.rs:22:5
@@ -17,6 +18,7 @@ LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
    = help: the trait `Index<usize>` is implemented for `[i32]`
+   = help: for that trait implementation, expected `usize`, found `u32`
 
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/on-impl.rs:22:5
@@ -26,6 +28,7 @@ LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
    = help: the trait `Index<usize>` is implemented for `[i32]`
+   = help: for that trait implementation, expected `usize`, found `u32`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr
index b9bca211f43..5e0117be529 100644
--- a/tests/ui/on-unimplemented/slice-index.stderr
+++ b/tests/ui/on-unimplemented/slice-index.stderr
@@ -5,7 +5,8 @@ LL |     x[1i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[i32]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `[i32]` to implement `Index<i32>`
 
 error[E0277]: the type `[i32]` cannot be indexed by `RangeTo<i32>`
diff --git a/tests/ui/or-patterns/missing-bindings.stderr b/tests/ui/or-patterns/missing-bindings.stderr
index 4457b7893d5..7f182a85787 100644
--- a/tests/ui/or-patterns/missing-bindings.stderr
+++ b/tests/ui/or-patterns/missing-bindings.stderr
@@ -103,22 +103,6 @@ LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
    |                 |
    |                 variable not in all patterns
 
-error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/missing-bindings.rs:45:33
-   |
-LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
-   |                        -        ^^^^ pattern doesn't bind `c`
-   |                        |
-   |                        variable not in all patterns
-
-error[E0408]: variable `d` is not bound in all patterns
-  --> $DIR/missing-bindings.rs:45:33
-   |
-LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
-   |                            -    ^^^^ pattern doesn't bind `d`
-   |                            |
-   |                            variable not in all patterns
-
 error[E0408]: variable `e` is not bound in all patterns
   --> $DIR/missing-bindings.rs:45:10
    |
@@ -143,6 +127,22 @@ LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
    |                 |
    |                 variable not in all patterns
 
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:45:33
+   |
+LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
+   |                        -        ^^^^ pattern doesn't bind `c`
+   |                        |
+   |                        variable not in all patterns
+
+error[E0408]: variable `d` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:45:33
+   |
+LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
+   |                            -    ^^^^ pattern doesn't bind `d`
+   |                            |
+   |                            variable not in all patterns
+
 error[E0408]: variable `a` is not bound in all patterns
   --> $DIR/missing-bindings.rs:61:29
    |
@@ -151,14 +151,6 @@ LL |                     Ok(a) | Err(_),
    |                        |
    |                        variable not in all patterns
 
-error[E0408]: variable `a` is not bound in all patterns
-  --> $DIR/missing-bindings.rs:69:21
-   |
-LL |                     A(_, a) |
-   |                          - variable not in all patterns
-LL |                     B(b),
-   |                     ^^^^ pattern doesn't bind `a`
-
 error[E0408]: variable `b` is not bound in all patterns
   --> $DIR/missing-bindings.rs:68:21
    |
@@ -168,6 +160,14 @@ LL |                     B(b),
    |                       - variable not in all patterns
 
 error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:69:21
+   |
+LL |                     A(_, a) |
+   |                          - variable not in all patterns
+LL |                     B(b),
+   |                     ^^^^ pattern doesn't bind `a`
+
+error[E0408]: variable `a` is not bound in all patterns
   --> $DIR/missing-bindings.rs:72:17
    |
 LL |                     A(_, a) |
@@ -185,6 +185,24 @@ LL |                     B(b),
 LL |                 B(_)
    |                 ^^^^ pattern doesn't bind `b`
 
+error[E0408]: variable `b` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:57:13
+   |
+LL | /             V1(
+LL | |
+LL | |
+LL | |                 A(
+...  |
+LL | |                 B(Ok(a) | Err(a))
+LL | |             ) |
+   | |_____________^ pattern doesn't bind `b`
+...
+LL |                       B(b),
+   |                         - variable not in all patterns
+...
+LL |               V3(c),
+   |               ^^^^^ pattern doesn't bind `b`
+
 error[E0408]: variable `c` is not bound in all patterns
   --> $DIR/missing-bindings.rs:57:13
    |
@@ -219,24 +237,6 @@ LL |                     A(_, a) |
 LL |             V3(c),
    |             ^^^^^ pattern doesn't bind `a`
 
-error[E0408]: variable `b` is not bound in all patterns
-  --> $DIR/missing-bindings.rs:57:13
-   |
-LL | /             V1(
-LL | |
-LL | |
-LL | |                 A(
-...  |
-LL | |                 B(Ok(a) | Err(a))
-LL | |             ) |
-   | |_____________^ pattern doesn't bind `b`
-...
-LL |                       B(b),
-   |                         - variable not in all patterns
-...
-LL |               V3(c),
-   |               ^^^^^ pattern doesn't bind `b`
-
 error: aborting due to 26 previous errors
 
 For more information about this error, try `rustc --explain E0408`.
diff --git a/tests/ui/parser/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attr-stmt-expr-attr-bad.stderr
index 96899fd3fc5..e46c591080d 100644
--- a/tests/ui/parser/attr-stmt-expr-attr-bad.stderr
+++ b/tests/ui/parser/attr-stmt-expr-attr-bad.stderr
@@ -27,6 +27,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
    = note: outer attributes, like `#[test]`, annotate the item following them
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: expected expression, found `)`
   --> $DIR/attr-stmt-expr-attr-bad.rs:7:44
diff --git a/tests/ui/parser/issues/issue-84117.stderr b/tests/ui/parser/issues/issue-84117.stderr
index 237bc11bd06..958f3b40bb0 100644
--- a/tests/ui/parser/issues/issue-84117.stderr
+++ b/tests/ui/parser/issues/issue-84117.stderr
@@ -47,6 +47,7 @@ LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
    |                                         |
    |                                         while parsing the type for `inner_local`
    |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: you might have meant to end the type parameters here
    |
 LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str>, }
@@ -61,6 +62,8 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, fo
    |
 LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
    |                                                                 ^ expected one of 8 possible tokens
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
   --> $DIR/issue-84117.rs:2:33
diff --git a/tests/ui/parser/macro/macro-repeat.stderr b/tests/ui/parser/macro/macro-repeat.stderr
index 63554b197b9..ade2bbf9b0b 100644
--- a/tests/ui/parser/macro/macro-repeat.stderr
+++ b/tests/ui/parser/macro/macro-repeat.stderr
@@ -9,6 +9,8 @@ error: variable 'v' is still repeating at this depth
    |
 LL |         $v
    |         ^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/recover-quantified-closure.stderr b/tests/ui/parser/recover-quantified-closure.stderr
index 39eec80f658..37e93cbee7b 100644
--- a/tests/ui/parser/recover-quantified-closure.stderr
+++ b/tests/ui/parser/recover-quantified-closure.stderr
@@ -25,10 +25,10 @@ LL |     for <Foo>::Bar in x {}
    = help: consider removing `for<...>`
 
 error: implicit types in closure signatures are forbidden when `for<...>` is present
-  --> $DIR/recover-quantified-closure.rs:2:25
+  --> $DIR/recover-quantified-closure.rs:2:24
    |
 LL |     for<'a> |x: &'a u8| *x + 1;
-   |     -------             ^
+   |     -------            ^
    |     |
    |     `for<...>` is here
 
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
index c0a6558a1bf..0b432487615 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
@@ -307,6 +307,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |                                                                  ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0507]: cannot move out of `a` in pattern guard
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66
@@ -323,6 +324,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    |                                                                  ^ move occurs because `a` has type `&mut Result<U, U>`, which does not implement the `Copy` trait
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9
diff --git a/tests/ui/pattern/patkind-litrange-no-expr.stderr b/tests/ui/pattern/patkind-litrange-no-expr.stderr
index eb1ee7e4567..45a26148940 100644
--- a/tests/ui/pattern/patkind-litrange-no-expr.stderr
+++ b/tests/ui/pattern/patkind-litrange-no-expr.stderr
@@ -9,6 +9,8 @@ error: arbitrary expressions aren't allowed in patterns
    |
 LL |     Arith = 1 + 1,
    |             ^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/pattern/usefulness/floats.rs b/tests/ui/pattern/usefulness/floats.rs
index 095f5ac9a89..2616dfadb85 100644
--- a/tests/ui/pattern/usefulness/floats.rs
+++ b/tests/ui/pattern/usefulness/floats.rs
@@ -1,19 +1,45 @@
+#![feature(exclusive_range_pattern)]
 #![allow(illegal_floating_point_literal_pattern)]
 #![deny(unreachable_patterns)]
 
 fn main() {
     match 0.0 {
-      0.0..=1.0 => {}
-      _ => {} // ok
+        0.0..=1.0 => {}
+        _ => {} // ok
     }
 
-    match 0.0 { //~ ERROR non-exhaustive patterns
-      0.0..=1.0 => {}
+    match 0.0 {
+        //~^ ERROR non-exhaustive patterns
+        0.0..=1.0 => {}
     }
 
     match 1.0f64 {
-      0.01f64 ..= 6.5f64 => {}
-      0.02f64 => {} //~ ERROR unreachable pattern
-      _ => {}
+        0.01f64..=6.5f64 => {}
+        0.005f64 => {}
+        0.01f64 => {} //~ ERROR unreachable pattern
+        0.02f64 => {} //~ ERROR unreachable pattern
+        6.5f64 => {}  //~ ERROR unreachable pattern
+        6.6f64 => {}
+        1.0f64..=4.0f64 => {} //~ ERROR unreachable pattern
+        5.0f64..=7.0f64 => {}
+        _ => {}
+    };
+    match 1.0f64 {
+        0.01f64..6.5f64 => {}
+        6.5f64 => {} // this is reachable
+        _ => {}
+    };
+
+    match 1.0f32 {
+        0.01f32..=6.5f32 => {}
+        0.01f32 => {} //~ ERROR unreachable pattern
+        0.02f32 => {} //~ ERROR unreachable pattern
+        6.5f32 => {}  //~ ERROR unreachable pattern
+        _ => {}
+    };
+    match 1.0f32 {
+        0.01f32..6.5f32 => {}
+        6.5f32 => {} // this is reachable
+        _ => {}
     };
 }
diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr
index d66d4ba298b..f5041911824 100644
--- a/tests/ui/pattern/usefulness/floats.stderr
+++ b/tests/ui/pattern/usefulness/floats.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/floats.rs:10:11
+  --> $DIR/floats.rs:11:11
    |
 LL |     match 0.0 {
    |           ^^^ pattern `_` not covered
@@ -7,22 +7,58 @@ LL |     match 0.0 {
    = note: the matched value is of type `f64`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~       0.0..=1.0 => {},
-LL +       _ => todo!()
+LL ~         0.0..=1.0 => {},
+LL +         _ => todo!()
    |
 
 error: unreachable pattern
-  --> $DIR/floats.rs:16:7
+  --> $DIR/floats.rs:19:9
    |
-LL |       0.02f64 => {}
-   |       ^^^^^^^
+LL |         0.01f64 => {}
+   |         ^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/floats.rs:2:9
+  --> $DIR/floats.rs:3:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: unreachable pattern
+  --> $DIR/floats.rs:20:9
+   |
+LL |         0.02f64 => {}
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/floats.rs:21:9
+   |
+LL |         6.5f64 => {}
+   |         ^^^^^^
+
+error: unreachable pattern
+  --> $DIR/floats.rs:23:9
+   |
+LL |         1.0f64..=4.0f64 => {}
+   |         ^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/floats.rs:35:9
+   |
+LL |         0.01f32 => {}
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/floats.rs:36:9
+   |
+LL |         0.02f32 => {}
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/floats.rs:37:9
+   |
+LL |         6.5f32 => {}
+   |         ^^^^^^
+
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/privacy/effective_visibilities.stderr b/tests/ui/privacy/effective_visibilities.stderr
index f74f812e1a0..41d63532dea 100644
--- a/tests/ui/privacy/effective_visibilities.stderr
+++ b/tests/ui/privacy/effective_visibilities.stderr
@@ -45,6 +45,8 @@ error: not in the table
    |
 LL |         struct PrivStruct;
    |         ^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
   --> $DIR/effective_visibilities.rs:25:9
@@ -81,6 +83,8 @@ error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImpl
    |
 LL |             A(
    |             ^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
   --> $DIR/effective_visibilities.rs:38:17
diff --git a/tests/ui/privacy/effective_visibilities_full_priv.stderr b/tests/ui/privacy/effective_visibilities_full_priv.stderr
index 29d82e2ee01..0577be1475f 100644
--- a/tests/ui/privacy/effective_visibilities_full_priv.stderr
+++ b/tests/ui/privacy/effective_visibilities_full_priv.stderr
@@ -9,6 +9,8 @@ error: not in the table
    |
 LL |     struct Priv;
    |     ^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
   --> $DIR/effective_visibilities_full_priv.rs:13:5
diff --git a/tests/ui/privacy/privacy1.stderr b/tests/ui/privacy/privacy1.stderr
index ca8f242e0be..a3552e146a6 100644
--- a/tests/ui/privacy/privacy1.stderr
+++ b/tests/ui/privacy/privacy1.stderr
@@ -21,6 +21,7 @@ note: the module `baz` is defined here
    |
 LL |     mod baz {
    |     ^^^^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:141:18
diff --git a/tests/ui/proc-macro/issue-37788.stderr b/tests/ui/proc-macro/issue-37788.stderr
index e437bb90b1d..0a116d6f80d 100644
--- a/tests/ui/proc-macro/issue-37788.stderr
+++ b/tests/ui/proc-macro/issue-37788.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-37788.rs:8:5
    |
 LL | fn main() {
-   |           - expected `()` because of default return type
+   |          - expected `()` because of default return type
 LL |     // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE.
 LL |     std::cell::Cell::new(0)
    |     ^^^^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
diff --git a/tests/ui/proc-macro/issue-75930-derive-cfg.stderr b/tests/ui/proc-macro/issue-75930-derive-cfg.stderr
index 6d1efb0dc28..f3f470676e4 100644
--- a/tests/ui/proc-macro/issue-75930-derive-cfg.stderr
+++ b/tests/ui/proc-macro/issue-75930-derive-cfg.stderr
@@ -22,6 +22,7 @@ LL | #[derive(Print)]
    |
    = 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 #79202 <https://github.com/rust-lang/rust/issues/79202>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 2 warnings emitted
 
diff --git a/tests/ui/proc-macro/macro-namespace-reserved-2.stderr b/tests/ui/proc-macro/macro-namespace-reserved-2.stderr
index b9effe7cf21..0471124061e 100644
--- a/tests/ui/proc-macro/macro-namespace-reserved-2.stderr
+++ b/tests/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -143,6 +143,7 @@ LL | #[derive(my_macro)]
    |          ^^^^^^^^
    |
    = note: `my_macro` is in scope, but it is a function-like macro
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 20 previous errors
 
diff --git a/tests/ui/proc-macro/pretty-print-hack-show.local.stderr b/tests/ui/proc-macro/pretty-print-hack-show.local.stderr
index 873054927c9..118882f73a3 100644
--- a/tests/ui/proc-macro/pretty-print-hack-show.local.stderr
+++ b/tests/ui/proc-macro/pretty-print-hack-show.local.stderr
@@ -18,6 +18,7 @@ LL | enum ProceduralMasqueradeDummyType {
    = 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 #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: using an old version of `rental`
   --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
@@ -28,6 +29,7 @@ LL | enum ProceduralMasqueradeDummyType {
    = 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 #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: using an old version of `rental`
   --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
@@ -38,6 +40,7 @@ LL | enum ProceduralMasqueradeDummyType {
    = 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 #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: using an old version of `rental`
   --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
@@ -58,6 +61,7 @@ LL | enum ProceduralMasqueradeDummyType {
    = 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 #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: using an old version of `rental`
   --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
@@ -68,6 +72,7 @@ LL | enum ProceduralMasqueradeDummyType {
    = 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 #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: using an old version of `rental`
   --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
@@ -78,6 +83,7 @@ LL | enum ProceduralMasqueradeDummyType {
    = 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 #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr
index 873054927c9..118882f73a3 100644
--- a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr
+++ b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr
@@ -18,6 +18,7 @@ LL | enum ProceduralMasqueradeDummyType {
    = 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 #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: using an old version of `rental`
   --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
@@ -28,6 +29,7 @@ LL | enum ProceduralMasqueradeDummyType {
    = 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 #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: using an old version of `rental`
   --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
@@ -38,6 +40,7 @@ LL | enum ProceduralMasqueradeDummyType {
    = 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 #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: using an old version of `rental`
   --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
@@ -58,6 +61,7 @@ LL | enum ProceduralMasqueradeDummyType {
    = 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 #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: using an old version of `rental`
   --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
@@ -68,6 +72,7 @@ LL | enum ProceduralMasqueradeDummyType {
    = 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 #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: using an old version of `rental`
   --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
@@ -78,6 +83,7 @@ LL | enum ProceduralMasqueradeDummyType {
    = 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 #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/proc-macro/resolve-error.stderr b/tests/ui/proc-macro/resolve-error.stderr
index 3c3f24d0ff2..e7639f474c7 100644
--- a/tests/ui/proc-macro/resolve-error.stderr
+++ b/tests/ui/proc-macro/resolve-error.stderr
@@ -44,6 +44,8 @@ error: cannot find derive macro `attr_proc_macra` in this scope
    |
 LL | #[derive(attr_proc_macra)]
    |          ^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: cannot find derive macro `Dlona` in this scope
   --> $DIR/resolve-error.rs:40:10
@@ -66,6 +68,8 @@ LL | #[derive(Dlona)]
    |
 LL | pub fn derive_clonea(input: TokenStream) -> TokenStream {
    | ------------------------------------------------------- similarly named derive macro `Clona` defined here
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: cannot find derive macro `Dlone` in this scope
   --> $DIR/resolve-error.rs:35:10
@@ -84,6 +88,8 @@ LL | #[derive(Dlone)]
   --> $SRC_DIR/core/src/clone.rs:LL:COL
    |
    = note: similarly named derive macro `Clone` defined here
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: cannot find attribute `FooWithLongNan` in this scope
   --> $DIR/resolve-error.rs:32:3
@@ -123,6 +129,8 @@ LL | #[derive(FooWithLongNan)]
    |
 LL | pub fn derive_foo(input: TokenStream) -> TokenStream {
    | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 14 previous errors
 
diff --git a/tests/ui/proc-macro/resolved-located-at.stderr b/tests/ui/proc-macro/resolved-located-at.stderr
index 0b4dbcba682..a4f838521fd 100644
--- a/tests/ui/proc-macro/resolved-located-at.stderr
+++ b/tests/ui/proc-macro/resolved-located-at.stderr
@@ -10,7 +10,7 @@ error[E0308]: mismatched types
   --> $DIR/resolved-located-at.rs:7:27
    |
 LL | fn main() {
-   |           - expected `()` because of default return type
+   |          - expected `()` because of default return type
 LL |     resolve_located_at!(a b)
    |                           ^ expected `()`, found `S`
    |
diff --git a/tests/ui/proc-macro/span-preservation.stderr b/tests/ui/proc-macro/span-preservation.stderr
index 8c15cb9de98..3ad9c539f84 100644
--- a/tests/ui/proc-macro/span-preservation.stderr
+++ b/tests/ui/proc-macro/span-preservation.stderr
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:39:5
    |
 LL | extern "C" fn bar() {
-   |                     - help: try adding a return type: `-> i32`
+   |                    - help: try adding a return type: `-> i32`
 LL |     0
    |     ^ expected `()`, found integer
 
@@ -46,7 +46,7 @@ error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:44:5
    |
 LL | extern "C" fn baz() {
-   |                     - help: try adding a return type: `-> i32`
+   |                    - help: try adding a return type: `-> i32`
 LL |     0
    |     ^ expected `()`, found integer
 
@@ -54,7 +54,7 @@ error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:49:5
    |
 LL | extern "Rust" fn rust_abi() {
-   |                             - help: try adding a return type: `-> i32`
+   |                            - help: try adding a return type: `-> i32`
 LL |     0
    |     ^ expected `()`, found integer
 
@@ -62,7 +62,7 @@ error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:54:5
    |
 LL | extern "\x43" fn c_abi_escaped() {
-   |                                  - help: try adding a return type: `-> i32`
+   |                                 - help: try adding a return type: `-> i32`
 LL |     0
    |     ^ expected `()`, found integer
 
diff --git a/tests/ui/recursion_limit/empty.stderr b/tests/ui/recursion_limit/empty.stderr
index cb5c0c35a5e..2f730677507 100644
--- a/tests/ui/recursion_limit/empty.stderr
+++ b/tests/ui/recursion_limit/empty.stderr
@@ -13,6 +13,8 @@ LL | #![recursion_limit = ""]
    | ^^^^^^^^^^^^^^^^^^^^^--^
    |                      |
    |                      `limit` must be a non-negative integer
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/recursion_limit/invalid_digit.stderr b/tests/ui/recursion_limit/invalid_digit.stderr
index 4dc93ad5f67..4fda3039032 100644
--- a/tests/ui/recursion_limit/invalid_digit.stderr
+++ b/tests/ui/recursion_limit/invalid_digit.stderr
@@ -13,6 +13,8 @@ LL | #![recursion_limit = "-100"]
    | ^^^^^^^^^^^^^^^^^^^^^------^
    |                      |
    |                      not a valid integer
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/recursion_limit/overflow.stderr b/tests/ui/recursion_limit/overflow.stderr
index 2f622d28b45..6057177deb2 100644
--- a/tests/ui/recursion_limit/overflow.stderr
+++ b/tests/ui/recursion_limit/overflow.stderr
@@ -13,6 +13,8 @@ LL | #![recursion_limit = "999999999999999999999999"]
    | ^^^^^^^^^^^^^^^^^^^^^--------------------------^
    |                      |
    |                      `limit` is too large
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/regions/regions-close-object-into-object-4.stderr b/tests/ui/regions/regions-close-object-into-object-4.stderr
index 7a9f1ab0001..3ff7f891c66 100644
--- a/tests/ui/regions/regions-close-object-into-object-4.stderr
+++ b/tests/ui/regions/regions-close-object-into-object-4.stderr
@@ -26,6 +26,7 @@ error[E0310]: the parameter type `U` may not live long enough
 LL |     Box::new(B(&*v)) as Box<dyn X>
    |     ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
    |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider adding an explicit lifetime bound...
    |
 LL | fn i<'a, T, U: 'static>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
diff --git a/tests/ui/regions/regions-close-object-into-object-5.stderr b/tests/ui/regions/regions-close-object-into-object-5.stderr
index 311e8868c09..88c13483263 100644
--- a/tests/ui/regions/regions-close-object-into-object-5.stderr
+++ b/tests/ui/regions/regions-close-object-into-object-5.stderr
@@ -26,6 +26,7 @@ error[E0310]: the parameter type `T` may not live long enough
 LL |     Box::new(B(&*v)) as Box<dyn X>
    |     ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider adding an explicit lifetime bound...
    |
 LL | fn f<'a, T: 'static, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
diff --git a/tests/ui/repr/repr-align-assign.stderr b/tests/ui/repr/repr-align-assign.stderr
index b878ae0d173..3606d02210b 100644
--- a/tests/ui/repr/repr-align-assign.stderr
+++ b/tests/ui/repr/repr-align-assign.stderr
@@ -15,12 +15,16 @@ error[E0693]: incorrect `repr(align)` attribute format
    |
 LL | #[repr(align=8)]
    |        ^^^^^^^ help: use parentheses instead: `align(8)`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0693]: incorrect `repr(align)` attribute format
   --> $DIR/repr-align-assign.rs:9:8
    |
 LL | #[repr(align="8")]
    |        ^^^^^^^^^ help: use parentheses instead: `align(8)`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/repr/repr-align.stderr b/tests/ui/repr/repr-align.stderr
index 900a811bb8a..84d33a08a6f 100644
--- a/tests/ui/repr/repr-align.stderr
+++ b/tests/ui/repr/repr-align.stderr
@@ -39,36 +39,48 @@ error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
    |
 LL | #[repr(align(16.0))]
    |        ^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0589]: invalid `repr(align)` attribute: not a power of two
   --> $DIR/repr-align.rs:7:8
    |
 LL | #[repr(align(15))]
    |        ^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0589]: invalid `repr(align)` attribute: larger than 2^29
   --> $DIR/repr-align.rs:11:8
    |
 LL | #[repr(align(4294967296))]
    |        ^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer
   --> $DIR/repr-align.rs:18:8
    |
 LL | #[repr(align(16.0))]
    |        ^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0589]: invalid `repr(align)` attribute: not a power of two
   --> $DIR/repr-align.rs:22:8
    |
 LL | #[repr(align(15))]
    |        ^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0589]: invalid `repr(align)` attribute: larger than 2^29
   --> $DIR/repr-align.rs:26:8
    |
 LL | #[repr(align(4294967296))]
    |        ^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 12 previous errors
 
diff --git a/tests/ui/resolve/issue-116164.rs b/tests/ui/resolve/issue-116164.rs
new file mode 100644
index 00000000000..d30c8f514b3
--- /dev/null
+++ b/tests/ui/resolve/issue-116164.rs
@@ -0,0 +1,19 @@
+#![allow(unused_imports)]
+
+mod inner {
+    pub enum Example {
+        ExOne,
+    }
+}
+
+mod reexports {
+    pub use crate::inner::Example as _;
+}
+
+use crate::reexports::*;
+//~^ SUGGESTION: use inner::Example::ExOne
+
+fn main() {
+    ExOne;
+    //~^ ERROR: cannot find value `ExOne` in this scope
+}
diff --git a/tests/ui/resolve/issue-116164.stderr b/tests/ui/resolve/issue-116164.stderr
new file mode 100644
index 00000000000..5820a189fd5
--- /dev/null
+++ b/tests/ui/resolve/issue-116164.stderr
@@ -0,0 +1,14 @@
+error[E0425]: cannot find value `ExOne` in this scope
+  --> $DIR/issue-116164.rs:17:5
+   |
+LL |     ExOne;
+   |     ^^^^^ not found in this scope
+   |
+help: consider importing this unit variant
+   |
+LL + use inner::Example::ExOne;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/resolve/resolve-inconsistent-names.stderr b/tests/ui/resolve/resolve-inconsistent-names.stderr
index 42b7281d7b0..d6240fb8f87 100644
--- a/tests/ui/resolve/resolve-inconsistent-names.stderr
+++ b/tests/ui/resolve/resolve-inconsistent-names.stderr
@@ -1,11 +1,3 @@
-error[E0408]: variable `a` is not bound in all patterns
-  --> $DIR/resolve-inconsistent-names.rs:13:12
-   |
-LL |        a | b => {}
-   |        -   ^ pattern doesn't bind `a`
-   |        |
-   |        variable not in all patterns
-
 error[E0408]: variable `b` is not bound in all patterns
   --> $DIR/resolve-inconsistent-names.rs:13:8
    |
@@ -14,6 +6,14 @@ LL |        a | b => {}
    |        |
    |        pattern doesn't bind `b`
 
+error[E0408]: variable `a` is not bound in all patterns
+  --> $DIR/resolve-inconsistent-names.rs:13:12
+   |
+LL |        a | b => {}
+   |        -   ^ pattern doesn't bind `a`
+   |        |
+   |        variable not in all patterns
+
 error[E0408]: variable `c` is not bound in all patterns
   --> $DIR/resolve-inconsistent-names.rs:19:9
    |
@@ -54,6 +54,19 @@ LL |         (A, B) | (ref B, c) | (c, A) => ()
    |             |
    |             first binding
 
+error[E0408]: variable `Const2` is not bound in all patterns
+  --> $DIR/resolve-inconsistent-names.rs:31:9
+   |
+LL |         (CONST1, _) | (_, Const2) => ()
+   |         ^^^^^^^^^^^       ------ variable not in all patterns
+   |         |
+   |         pattern doesn't bind `Const2`
+   |
+help: if you meant to match on constant `m::Const2`, use the full path in the pattern
+   |
+LL |         (CONST1, _) | (_, m::Const2) => ()
+   |                           ~~~~~~~~~
+
 error[E0408]: variable `CONST1` is not bound in all patterns
   --> $DIR/resolve-inconsistent-names.rs:31:23
    |
@@ -68,19 +81,6 @@ note: you might have meant to match on constant `m::CONST1`, which exists but is
 LL |     const CONST1: usize = 10;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ not accessible
 
-error[E0408]: variable `Const2` is not bound in all patterns
-  --> $DIR/resolve-inconsistent-names.rs:31:9
-   |
-LL |         (CONST1, _) | (_, Const2) => ()
-   |         ^^^^^^^^^^^       ------ variable not in all patterns
-   |         |
-   |         pattern doesn't bind `Const2`
-   |
-help: if you meant to match on constant `m::Const2`, use the full path in the pattern
-   |
-LL |         (CONST1, _) | (_, m::Const2) => ()
-   |                           ~~~~~~~~~
-
 error[E0308]: mismatched types
   --> $DIR/resolve-inconsistent-names.rs:19:19
    |
diff --git a/tests/ui/return/return-struct.stderr b/tests/ui/return/return-struct.stderr
index e6c0363e363..282e6498ebe 100644
--- a/tests/ui/return/return-struct.stderr
+++ b/tests/ui/return/return-struct.stderr
@@ -17,7 +17,7 @@ error[E0308]: mismatched types
   --> $DIR/return-struct.rs:15:5
    |
 LL | fn bar() {
-   |          - help: try adding a return type: `-> Age`
+   |         - help: try adding a return type: `-> Age`
 LL |     let mut age = 29;
 LL |     Age::Years(age, 55)
    |     ^^^^^^^^^^^^^^^^^^^ expected `()`, found `Age`
@@ -26,7 +26,7 @@ error[E0308]: mismatched types
   --> $DIR/return-struct.rs:20:5
    |
 LL | fn baz() {
-   |          - help: try adding a return type: `-> S`
+   |         - help: try adding a return type: `-> S`
 LL |     S
    |     ^ expected `()`, found `S`
 
diff --git a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr
index d183eaaa623..5f8c5dbe619 100644
--- a/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr
+++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-2.stderr
@@ -15,6 +15,7 @@ LL |     f: &id,
    |
    = note: expected trait `for<'a, 'b> Fn<(&'a Foo<'b>,)>`
               found trait `Fn<(&Foo<'_>,)>`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: implementation of `FnOnce` is not general enough
   --> $DIR/rfc1623-2.rs:28:8
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs
new file mode 100644
index 00000000000..1e22ddcea8d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs
@@ -0,0 +1,28 @@
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+trait MyTrait {
+    fn do_something(&self);
+}
+
+trait OtherTrait {
+    fn do_something_else() where Self: ~const MyTrait;
+    //~^ ERROR `~const` is not allowed here
+}
+
+struct MyStruct<T>(T);
+
+impl const MyTrait for u32 {
+    fn do_something(&self) {}
+}
+
+impl<T> MyStruct<T> {
+    pub fn foo(&self) where T: ~const MyTrait {
+        //~^ ERROR `~const` is not allowed here
+        self.0.do_something();
+    }
+}
+
+fn main() {
+    MyStruct(0u32).foo();
+}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr
new file mode 100644
index 00000000000..9210f642706
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr
@@ -0,0 +1,26 @@
+error: `~const` is not allowed here
+  --> $DIR/const-bound-on-not-const-associated-fn.rs:9:40
+   |
+LL |     fn do_something_else() where Self: ~const MyTrait;
+   |                                        ^^^^^^^^^^^^^^
+   |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+  --> $DIR/const-bound-on-not-const-associated-fn.rs:9:8
+   |
+LL |     fn do_something_else() where Self: ~const MyTrait;
+   |        ^^^^^^^^^^^^^^^^^
+
+error: `~const` is not allowed here
+  --> $DIR/const-bound-on-not-const-associated-fn.rs:20:32
+   |
+LL |     pub fn foo(&self) where T: ~const MyTrait {
+   |                                ^^^^^^^^^^^^^^
+   |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+  --> $DIR/const-bound-on-not-const-associated-fn.rs:20:12
+   |
+LL |     pub fn foo(&self) where T: ~const MyTrait {
+   |            ^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr
index 8bf00eaff1f..e8ae7e4e36c 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr
@@ -13,6 +13,7 @@ LL | use core::convert::{From, TryFrom};
    |     ^^^^ maybe a missing crate `core`?
    |
    = help: consider adding `extern crate core` to use the `core` crate
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr
index 97f346e8c1d..b60399c57dc 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr
@@ -9,6 +9,8 @@ error: ~const can only be applied to `#[const_trait]` traits
    |
 LL | trait Bar: ~const Foo {}
    |                   ^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr
index 97f346e8c1d..b60399c57dc 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr
@@ -9,6 +9,8 @@ error: ~const can only be applied to `#[const_trait]` traits
    |
 LL | trait Bar: ~const Foo {}
    |                   ^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
index 2897eabb081..eb12a236d8c 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
@@ -9,6 +9,8 @@ error: ~const can only be applied to `#[const_trait]` traits
    |
 LL | trait Bar: ~const Foo {}
    |                   ^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: ~const can only be applied to `#[const_trait]` traits
   --> $DIR/super-traits-fail-3.rs:17:24
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr
index 9839a4f2480..cd0ee73277d 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr
@@ -9,6 +9,8 @@ error: ~const can only be applied to `#[const_trait]` traits
    |
 LL | trait Bar: ~const Foo {}
    |                   ^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs
index 89d74cecfdb..4b720b534a4 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs
@@ -7,7 +7,8 @@ struct Foo<const N: usize>;
 
 impl<const N: usize> Foo<N> {
     fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
-        //~^ ERROR mismatched types
+        //~^ ERROR `~const` is not allowed here
+        //~| ERROR mismatched types
         Foo
     }
 }
@@ -30,7 +31,7 @@ fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
 }
 
 fn main() {
-   let foo = Foo::<0>;
-   let foo = bar::<(), _>(foo);
-   let _foo = bar::<(), _>(foo);
+    let foo = Foo::<0>;
+    let foo = bar::<(), _>(foo);
+    let _foo = bar::<(), _>(foo);
 }
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr
index ec5d21d33c6..be7a83dc184 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr
@@ -1,17 +1,29 @@
 error: `~const` is not allowed here
-  --> $DIR/tilde-const-and-const-params.rs:26:11
+  --> $DIR/tilde-const-and-const-params.rs:9:15
+   |
+LL |     fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
+   |               ^^^^^^^^^^^^
+   |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+  --> $DIR/tilde-const-and-const-params.rs:9:8
+   |
+LL |     fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
+   |        ^^^
+
+error: `~const` is not allowed here
+  --> $DIR/tilde-const-and-const-params.rs:27:11
    |
 LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
    |           ^^^^^^^^^^^^
    |
 note: this function is not `const`, so it cannot have `~const` trait bounds
-  --> $DIR/tilde-const-and-const-params.rs:26:4
+  --> $DIR/tilde-const-and-const-params.rs:27:4
    |
 LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
    |    ^^^
 
 error[E0308]: mismatched types
-  --> $DIR/tilde-const-and-const-params.rs:26:61
+  --> $DIR/tilde-const-and-const-params.rs:27:61
    |
 LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
    |                                                             ^^^^^^^^^ expected `false`, found `true`
@@ -28,6 +40,6 @@ LL |     fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
    = note: expected constant `false`
               found constant `true`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs
index 85ca5fc9048..11f353f3f8a 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs
@@ -6,7 +6,9 @@ trait Bar {}
 trait Foo {
     fn a();
     fn b() where Self: ~const Bar;
+    //~^ ERROR `~const` is not allowed here
     fn c<T: ~const Bar>();
+    //~^ ERROR `~const` is not allowed here
 }
 
 fn test1<T: Foo>() {
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr
index 255878e1775..3d6fedbabbf 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr
@@ -1,5 +1,29 @@
+error: `~const` is not allowed here
+  --> $DIR/trait-where-clause.rs:8:24
+   |
+LL |     fn b() where Self: ~const Bar;
+   |                        ^^^^^^^^^^
+   |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+  --> $DIR/trait-where-clause.rs:8:8
+   |
+LL |     fn b() where Self: ~const Bar;
+   |        ^
+
+error: `~const` is not allowed here
+  --> $DIR/trait-where-clause.rs:10:13
+   |
+LL |     fn c<T: ~const Bar>();
+   |             ^^^^^^^^^^
+   |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+  --> $DIR/trait-where-clause.rs:10:8
+   |
+LL |     fn c<T: ~const Bar>();
+   |        ^
+
 error[E0277]: the trait bound `T: Bar` is not satisfied
-  --> $DIR/trait-where-clause.rs:14:5
+  --> $DIR/trait-where-clause.rs:16:5
    |
 LL |     T::b();
    |     ^ the trait `Bar` is not implemented for `T`
@@ -15,13 +39,13 @@ LL | fn test1<T: Foo + Bar>() {
    |                 +++++
 
 error[E0277]: the trait bound `T: Bar` is not satisfied
-  --> $DIR/trait-where-clause.rs:16:12
+  --> $DIR/trait-where-clause.rs:18:12
    |
 LL |     T::c::<T>();
    |            ^ the trait `Bar` is not implemented for `T`
    |
 note: required by a bound in `Foo::c`
-  --> $DIR/trait-where-clause.rs:9:13
+  --> $DIR/trait-where-clause.rs:10:13
    |
 LL |     fn c<T: ~const Bar>();
    |             ^^^^^^^^^^ required by this bound in `Foo::c`
@@ -30,6 +54,6 @@ help: consider further restricting this bound
 LL | fn test1<T: Foo + Bar>() {
    |                 +++++
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
index 497ee440dfd..c0a322edcd6 100644
--- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
+++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
@@ -20,6 +20,7 @@ LL |     let _: <foo::Baz as ::foo::Foo>::Bar = ();
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
   --> $DIR/edition-lint-fully-qualified-paths.rs:25:13
diff --git a/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr b/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr
index 8769cbb35b0..041572be844 100644
--- a/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr
+++ b/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr
@@ -29,6 +29,7 @@ LL | use foo::{bar::{XX, baz::{}}};
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
   --> $DIR/edition-lint-nested-empty-paths.rs:27:5
@@ -47,6 +48,7 @@ LL | use foo::{bar::{baz::{}, baz1::{}}};
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/rust-2018/edition-lint-nested-paths.stderr b/tests/ui/rust-2018/edition-lint-nested-paths.stderr
index 354a6fe3252..4a70bb7e5c8 100644
--- a/tests/ui/rust-2018/edition-lint-nested-paths.stderr
+++ b/tests/ui/rust-2018/edition-lint-nested-paths.stderr
@@ -20,6 +20,7 @@ LL | use foo::{a, b};
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
   --> $DIR/edition-lint-nested-paths.rs:23:13
@@ -38,6 +39,7 @@ LL |         use foo::{self as x, c};
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/rust-2018/edition-lint-paths.stderr b/tests/ui/rust-2018/edition-lint-paths.stderr
index 42652be9401..fde17338d98 100644
--- a/tests/ui/rust-2018/edition-lint-paths.stderr
+++ b/tests/ui/rust-2018/edition-lint-paths.stderr
@@ -38,6 +38,7 @@ LL |     use {main, Bar as SomethingElse};
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
   --> $DIR/edition-lint-paths.rs:25:9
@@ -47,6 +48,7 @@ LL |     use {main, Bar as SomethingElse};
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
   --> $DIR/edition-lint-paths.rs:40:5
diff --git a/tests/ui/rust-2018/uniform-paths/cross-crate.stderr b/tests/ui/rust-2018/uniform-paths/cross-crate.stderr
index 45f77a0c9fe..8682c56d2a5 100644
--- a/tests/ui/rust-2018/uniform-paths/cross-crate.stderr
+++ b/tests/ui/rust-2018/uniform-paths/cross-crate.stderr
@@ -33,6 +33,7 @@ note: the tool module imported here
    |
 LL | use cross_crate::*;
    |     ^^^^^^^^^^^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/rust-2018/uniform-paths/prelude-fail-2.stderr b/tests/ui/rust-2018/uniform-paths/prelude-fail-2.stderr
index 908bb498586..3dacb796911 100644
--- a/tests/ui/rust-2018/uniform-paths/prelude-fail-2.stderr
+++ b/tests/ui/rust-2018/uniform-paths/prelude-fail-2.stderr
@@ -51,6 +51,7 @@ note: the tool module imported here
    |
 LL | use rustfmt as imported_rustfmt;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: cannot use a tool module through an import
   --> $DIR/prelude-fail-2.rs:19:13
@@ -63,6 +64,7 @@ note: the tool module imported here
    |
 LL |     pub use rustfmt as imported_rustfmt;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.aarch64.stderr b/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.aarch64.stderr
index 8328178e8d0..1006c3bc17e 100644
--- a/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.aarch64.stderr
+++ b/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.aarch64.stderr
@@ -3,6 +3,8 @@ error: cfi sanitizer is not supported for this target
 error: `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi`
 
 error: `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.x86_64.stderr b/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.x86_64.stderr
index 8328178e8d0..1006c3bc17e 100644
--- a/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.x86_64.stderr
+++ b/tests/ui/sanitize/sanitizer-cfi-is-incompatible-with-saniziter-kcfi.x86_64.stderr
@@ -3,6 +3,8 @@ error: cfi sanitizer is not supported for this target
 error: `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi`
 
 error: `-Zsanitizer=cfi` is incompatible with `-Zsanitizer=kcfi`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed b/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed
index ccd65ff4091..a400a1672a4 100644
--- a/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed
+++ b/tests/ui/self/arbitrary_self_types_needing_mut_pin.fixed
@@ -8,5 +8,6 @@ impl S {
 }
 
 fn main() {
-    Pin::new(&mut S).x(); //~ ERROR no method named `x` found
+    let mut pinned = std::pin::pin!(S);
+    pinned.as_mut().x(); //~ ERROR no method named `x` found
 }
diff --git a/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr b/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr
index f34ce4dce49..5dcb5861120 100644
--- a/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr
+++ b/tests/ui/self/arbitrary_self_types_needing_mut_pin.stderr
@@ -4,16 +4,14 @@ error[E0599]: no method named `x` found for struct `S` in the current scope
 LL | struct S;
    | -------- method `x` not found for this struct
 ...
-LL |     fn x(self: Pin<&mut Self>) {
-   |        - the method is available for `Pin<&mut S>` here
-...
 LL |     S.x();
    |       ^ method not found in `S`
    |
-help: consider wrapping the receiver expression with the appropriate type
+help: consider pinning the expression
+   |
+LL ~     let mut pinned = std::pin::pin!(S);
+LL ~     pinned.as_mut().x();
    |
-LL |     Pin::new(&mut S).x();
-   |     +++++++++++++  +
 
 error: aborting due to previous error
 
diff --git a/tests/ui/span/issue-39698.stderr b/tests/ui/span/issue-39698.stderr
index 81211b20a01..50008083211 100644
--- a/tests/ui/span/issue-39698.stderr
+++ b/tests/ui/span/issue-39698.stderr
@@ -1,3 +1,13 @@
+error[E0408]: variable `b` is not bound in all patterns
+  --> $DIR/issue-39698.rs:10:9
+   |
+LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
+   |         ^^^^^^^^^^^            -    ^^^^^^^^   ^^^^^^^^ pattern doesn't bind `b`
+   |         |                      |    |
+   |         |                      |    pattern doesn't bind `b`
+   |         |                      variable not in all patterns
+   |         pattern doesn't bind `b`
+
 error[E0408]: variable `c` is not bound in all patterns
   --> $DIR/issue-39698.rs:10:9
    |
@@ -8,16 +18,6 @@ LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}
    |         |             pattern doesn't bind `c`
    |         pattern doesn't bind `c`
 
-error[E0408]: variable `d` is not bound in all patterns
-  --> $DIR/issue-39698.rs:10:37
-   |
-LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
-   |                  -          -       ^^^^^^^^   ^^^^^^^^ pattern doesn't bind `d`
-   |                  |          |       |
-   |                  |          |       pattern doesn't bind `d`
-   |                  |          variable not in all patterns
-   |                  variable not in all patterns
-
 error[E0408]: variable `a` is not bound in all patterns
   --> $DIR/issue-39698.rs:10:23
    |
@@ -28,15 +28,15 @@ LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}
    |               |       pattern doesn't bind `a`
    |               variable not in all patterns
 
-error[E0408]: variable `b` is not bound in all patterns
-  --> $DIR/issue-39698.rs:10:9
+error[E0408]: variable `d` is not bound in all patterns
+  --> $DIR/issue-39698.rs:10:37
    |
 LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
-   |         ^^^^^^^^^^^            -    ^^^^^^^^   ^^^^^^^^ pattern doesn't bind `b`
-   |         |                      |    |
-   |         |                      |    pattern doesn't bind `b`
-   |         |                      variable not in all patterns
-   |         pattern doesn't bind `b`
+   |                  -          -       ^^^^^^^^   ^^^^^^^^ pattern doesn't bind `d`
+   |                  |          |       |
+   |                  |          |       pattern doesn't bind `d`
+   |                  |          variable not in all patterns
+   |                  variable not in all patterns
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr
index cb1a6fcacfc..e8bbb8058fa 100644
--- a/tests/ui/str/str-idx.stderr
+++ b/tests/ui/str/str-idx.stderr
@@ -7,7 +7,8 @@ LL |     let _: u8 = s[4];
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: for that trait implementation, expected `[_]`, found `str`
    = note: required for `str` to implement `Index<{integer}>`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
@@ -21,7 +22,8 @@ LL |     let _ = s.get(4);
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: for that trait implementation, expected `[_]`, found `str`
 note: required by a bound in `core::str::<impl str>::get`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
@@ -36,7 +38,8 @@ LL |     let _ = s.get_unchecked(4);
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: for that trait implementation, expected `[_]`, found `str`
 note: required by a bound in `core::str::<impl str>::get_unchecked`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr
index ca4b86ba306..e6835bb54fb 100644
--- a/tests/ui/str/str-mut-idx.stderr
+++ b/tests/ui/str/str-mut-idx.stderr
@@ -31,7 +31,8 @@ LL |     s[1usize] = bot();
    |       ^^^^^^ string indices are ranges of `usize`
    |
    = help: the trait `SliceIndex<str>` is not implemented for `usize`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: for that trait implementation, expected `[_]`, found `str`
    = note: required for `str` to implement `Index<usize>`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
@@ -45,7 +46,8 @@ LL |     s.get_mut(1);
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: for that trait implementation, expected `[_]`, found `str`
 note: required by a bound in `core::str::<impl str>::get_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
@@ -60,7 +62,8 @@ LL |     s.get_unchecked_mut(1);
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: for that trait implementation, expected `[_]`, found `str`
 note: required by a bound in `core::str::<impl str>::get_unchecked_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr
index b476d61017f..2c29cfa0b91 100644
--- a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr
+++ b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr
@@ -26,9 +26,9 @@ error: lifetime may not live long enough
   --> $DIR/impl-trait-missing-lifetime.rs:16:69
    |
 LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
-   |                                                    --------------   ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
-   |                                                    |
-   |                                                    return type `impl Future<Output = Option<&'static ()>>` contains a lifetime `'1`
+   | -----------------------------------------------------------------   ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+   | |
+   | return type `impl Future<Output = Option<&'static ()>>` contains a lifetime `'1`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/suggestions/issue-101623.stderr b/tests/ui/suggestions/issue-101623.stderr
index 361483cc08d..9f00de17484 100644
--- a/tests/ui/suggestions/issue-101623.stderr
+++ b/tests/ui/suggestions/issue-101623.stderr
@@ -7,7 +7,8 @@ LL |     Trait::do_stuff({ fun(&mut *inner) });
    |     |               the trait `Trait<'_>` is not implemented for `*mut ()`
    |     required by a bound introduced by this call
    |
-   = help: the trait `Trait<'a>` is implemented for `()`
+   = help: the trait `Trait<'_>` is implemented for `()`
+   = help: for that trait implementation, expected `()`, found `*mut ()`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/suggestions/issue-61963.stderr b/tests/ui/suggestions/issue-61963.stderr
index b99b1b0b9b3..ec62153b0a7 100644
--- a/tests/ui/suggestions/issue-61963.stderr
+++ b/tests/ui/suggestions/issue-61963.stderr
@@ -37,6 +37,7 @@ LL |     bar: Box<Bar>,
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL |     bar: Box<dyn Bar>,
@@ -50,6 +51,7 @@ LL |     bar: Box<Bar>,
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL |     bar: Box<dyn Bar>,
@@ -63,6 +65,7 @@ LL | pub struct Foo {
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | dyn pub struct Foo {
@@ -76,6 +79,7 @@ LL | pub struct Foo {
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | dyn pub struct Foo {
@@ -89,6 +93,7 @@ LL | pub struct Foo {
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: use `dyn`
    |
 LL | dyn pub struct Foo {
diff --git a/tests/ui/suggestions/issue-83892.stderr b/tests/ui/suggestions/issue-83892.stderr
index baf6b1447e6..5e471819b27 100644
--- a/tests/ui/suggestions/issue-83892.stderr
+++ b/tests/ui/suggestions/issue-83892.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-83892.rs:9:15
    |
 LL | fn main() {
-   |           - expected `()` because of default return type
+   |          - expected `()` because of default return type
 LL |     match () {
 LL |         () => func()
    |               ^^^^^^ expected `()`, found `u8`
diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr
index 21d2378382c..fa4bc2fa79d 100644
--- a/tests/ui/suggestions/missing-lifetime-specifier.stderr
+++ b/tests/ui/suggestions/missing-lifetime-specifier.stderr
@@ -164,6 +164,7 @@ note: union defined here, with 2 lifetime parameters: `'t`, `'k`
    |
 LL | pub union Qux<'t, 'k, I> {
    |           ^^^ --  --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -182,6 +183,7 @@ note: union defined here, with 2 lifetime parameters: `'t`, `'k`
    |
 LL | pub union Qux<'t, 'k, I> {
    |           ^^^ --  --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -200,6 +202,7 @@ note: union defined here, with 2 lifetime parameters: `'t`, `'k`
    |
 LL | pub union Qux<'t, 'k, I> {
    |           ^^^ --  --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -218,6 +221,7 @@ note: union defined here, with 2 lifetime parameters: `'t`, `'k`
    |
 LL | pub union Qux<'t, 'k, I> {
    |           ^^^ --  --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -254,6 +258,7 @@ note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
    |
 LL | trait Tar<'t, 'k, I> {}
    |       ^^^ --  --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -272,6 +277,7 @@ note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
    |
 LL | trait Tar<'t, 'k, I> {}
    |       ^^^ --  --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -290,6 +296,7 @@ note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
    |
 LL | trait Tar<'t, 'k, I> {}
    |       ^^^ --  --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -308,6 +315,7 @@ note: trait defined here, with 2 lifetime parameters: `'t`, `'k`
    |
 LL | trait Tar<'t, 'k, I> {}
    |       ^^^ --  --
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: add missing lifetime argument
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
diff --git a/tests/ui/suggestions/return-closures.stderr b/tests/ui/suggestions/return-closures.stderr
index f0810bbb254..97c13200ac3 100644
--- a/tests/ui/suggestions/return-closures.stderr
+++ b/tests/ui/suggestions/return-closures.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/return-closures.rs:3:5
    |
 LL | fn foo() {
-   |          - help: try adding a return type: `-> impl for<'a> Fn(&'a i32) -> i32`
+   |         - help: try adding a return type: `-> impl for<'a> Fn(&'a i32) -> i32`
 LL |
 LL |     |x: &i32| 1i32
    |     ^^^^^^^^^^^^^^ expected `()`, found closure
@@ -14,7 +14,7 @@ error[E0308]: mismatched types
   --> $DIR/return-closures.rs:9:5
    |
 LL | fn bar(i: impl Sized) {
-   |                       - help: a return type might be missing here: `-> _`
+   |                      - help: a return type might be missing here: `-> _`
 LL |
 LL |     || i
    |     ^^^^ expected `()`, found closure
diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr
index 147dc9234c5..adf01339972 100644
--- a/tests/ui/suggestions/suggest-dereferencing-index.stderr
+++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr
@@ -5,7 +5,8 @@ LL |     let one_item_please: i32 = [1, 2, 3][i];
    |                                          ^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `&usize`
    = note: required for `[{integer}]` to implement `Index<&usize>`
 help: dereference this index
    |
diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.fixed b/tests/ui/suggestions/suggest-ret-on-async-w-late.fixed
new file mode 100644
index 00000000000..0a08383317f
--- /dev/null
+++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.fixed
@@ -0,0 +1,14 @@
+// edition: 2021
+// run-rustfix
+
+#![allow(unused)]
+
+// Make sure we don't ICE when suggesting a return type
+// for an async fn that has late-bound vars...
+
+async fn ice(_: &i32) -> bool {
+    true
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.rs b/tests/ui/suggestions/suggest-ret-on-async-w-late.rs
index 459b94f943b..5c8f185bd4b 100644
--- a/tests/ui/suggestions/suggest-ret-on-async-w-late.rs
+++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.rs
@@ -1,4 +1,7 @@
 // edition: 2021
+// run-rustfix
+
+#![allow(unused)]
 
 // Make sure we don't ICE when suggesting a return type
 // for an async fn that has late-bound vars...
diff --git a/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr b/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr
index bff864b222b..352f6da3607 100644
--- a/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr
+++ b/tests/ui/suggestions/suggest-ret-on-async-w-late.stderr
@@ -1,8 +1,8 @@
 error[E0308]: mismatched types
-  --> $DIR/suggest-ret-on-async-w-late.rs:7:5
+  --> $DIR/suggest-ret-on-async-w-late.rs:10:5
    |
 LL | async fn ice(_: &i32) {
-   |                       - help: try adding a return type: `-> bool`
+   |                      - help: try adding a return type: `-> bool`
 LL |     true
    |     ^^^^ expected `()`, found `bool`
 
diff --git a/tests/ui/tool-attributes/tool-attributes-misplaced-1.stderr b/tests/ui/tool-attributes/tool-attributes-misplaced-1.stderr
index 71fd5f1d44a..2045dc6a36e 100644
--- a/tests/ui/tool-attributes/tool-attributes-misplaced-1.stderr
+++ b/tests/ui/tool-attributes/tool-attributes-misplaced-1.stderr
@@ -9,6 +9,8 @@ error: cannot find derive macro `rustfmt` in this scope
    |
 LL | #[derive(rustfmt)]
    |          ^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: cannot find attribute `rustfmt` in this scope
   --> $DIR/tool-attributes-misplaced-1.rs:9:3
diff --git a/tests/ui/tool_lints.stderr b/tests/ui/tool_lints.stderr
index d36cd193b15..f1d825caba1 100644
--- a/tests/ui/tool_lints.stderr
+++ b/tests/ui/tool_lints.stderr
@@ -13,6 +13,7 @@ LL | #[warn(foo::bar)]
    |        ^^^
    |
    = help: add `#![register_tool(foo)]` to the crate root
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/traits/associated_type_bound/impl-is-shadowed.rs b/tests/ui/traits/associated_type_bound/impl-is-shadowed.rs
new file mode 100644
index 00000000000..6c3125a9fc5
--- /dev/null
+++ b/tests/ui/traits/associated_type_bound/impl-is-shadowed.rs
@@ -0,0 +1,21 @@
+// check-pass
+trait Bar<'a> {
+    type Assoc: 'static;
+}
+
+impl<'a> Bar<'a> for () {
+    type Assoc = ();
+}
+
+struct ImplsStatic<CG: Bar<'static>> {
+    d: &'static <CG as Bar<'static>>::Assoc,
+}
+
+fn caller(b: ImplsStatic<()>)
+where
+    for<'a> (): Bar<'a>
+{
+    let _: &<() as Bar<'static>>::Assoc = b.d;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/coercion-generic-bad.stderr b/tests/ui/traits/coercion-generic-bad.stderr
index e7e8a796796..30a3c40db95 100644
--- a/tests/ui/traits/coercion-generic-bad.stderr
+++ b/tests/ui/traits/coercion-generic-bad.stderr
@@ -5,6 +5,7 @@ LL |     let s: Box<dyn Trait<isize>> = Box::new(Struct { person: "Fred" });
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<isize>` is not implemented for `Struct`
    |
    = help: the trait `Trait<&'static str>` is implemented for `Struct`
+   = help: for that trait implementation, expected `&'static str`, found `isize`
    = note: required for the cast from `Box<Struct>` to `Box<dyn Trait<isize>>`
 
 error: aborting due to previous error
diff --git a/tests/ui/traits/issue-38404.stderr b/tests/ui/traits/issue-38404.stderr
index f8625f53b78..a5c258eb36e 100644
--- a/tests/ui/traits/issue-38404.stderr
+++ b/tests/ui/traits/issue-38404.stderr
@@ -25,6 +25,7 @@ LL | trait A<T>: std::ops::Add<Self> + Sized {}
    |             ^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
 LL | trait B<T>: A<T> {}
    |       - this trait cannot be made into an object...
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/traits/issue-59029-1.stderr b/tests/ui/traits/issue-59029-1.stderr
index 203a8928530..51354bcc545 100644
--- a/tests/ui/traits/issue-59029-1.stderr
+++ b/tests/ui/traits/issue-59029-1.stderr
@@ -9,6 +9,8 @@ error[E0220]: associated type `Res` not found for `Self`
    |
 LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
    |                                                    ^^^ there is a similarly named associated type `Res` in the trait `Svc`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/traits/non_lifetime_binders/on-rpit.rs b/tests/ui/traits/non_lifetime_binders/on-rpit.rs
new file mode 100644
index 00000000000..c501e057e28
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-rpit.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Trait<T: ?Sized> {}
+
+impl<T: ?Sized> Trait<T> for i32 {}
+
+fn produce() -> impl for<T> Trait<T> {
+    16
+}
+
+fn main() {
+    let _ = produce();
+}
diff --git a/tests/ui/traits/non_lifetime_binders/on-rpit.stderr b/tests/ui/traits/non_lifetime_binders/on-rpit.stderr
new file mode 100644
index 00000000000..34c56068c5c
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-rpit.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/on-rpit.rs:3:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr
index e11c3f81003..b41bf86d3d9 100644
--- a/tests/ui/try-block/try-block-bad-type.stderr
+++ b/tests/ui/try-block/try-block-bad-type.stderr
@@ -6,6 +6,7 @@ LL |         Err("")?;
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = help: the trait `From<Infallible>` is implemented for `TryFromSliceError`
+   = help: for that trait implementation, expected `Infallible`, found `&str`
    = note: required for `Result<u32, TryFromSliceError>` to implement `FromResidual<Result<Infallible, &str>>`
 
 error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str`
diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr
index 7eb392faa66..d8b9431becc 100644
--- a/tests/ui/try-trait/bad-interconversion.stderr
+++ b/tests/ui/try-trait/bad-interconversion.stderr
@@ -73,7 +73,8 @@ LL |     ControlFlow::Continue(Err("hello")?)
    |                                       ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `ControlFlow<String>`
    |
    = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>`
-   = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>`
+   = help: the trait `FromResidual<ControlFlow<String, Infallible>>` is implemented for `ControlFlow<String>`
+   = help: for that trait implementation, expected `ControlFlow<String, Infallible>`, found `Result<Infallible, &str>`
 
 error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
   --> $DIR/bad-interconversion.rs:37:12
@@ -84,7 +85,8 @@ LL |     Some(3)?;
    |            ^ this `?` produces `Option<Infallible>`, which is incompatible with `ControlFlow<u64>`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>`
-   = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>`
+   = help: the trait `FromResidual<ControlFlow<u64, Infallible>>` is implemented for `ControlFlow<u64>`
+   = help: for that trait implementation, expected `ControlFlow<u64, Infallible>`, found `Option<Infallible>`
 
 error[E0277]: the `?` operator in a function that returns `ControlFlow<B, _>` can only be used on other `ControlFlow<B, _>`s (with the same Break type)
   --> $DIR/bad-interconversion.rs:43:29
@@ -96,7 +98,8 @@ LL |     ControlFlow::Break(4_u8)?;
    |
    = help: the trait `FromResidual<ControlFlow<u8, Infallible>>` is not implemented for `ControlFlow<i64>`
    = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
-   = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>`
+   = help: the trait `FromResidual<ControlFlow<i64, Infallible>>` is implemented for `ControlFlow<i64>`
+   = help: for that trait implementation, expected `i64`, found `u8`
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/tuple/tuple-struct-fields/test2.stderr b/tests/ui/tuple/tuple-struct-fields/test2.stderr
index 64a9ac13566..784411aba8f 100644
--- a/tests/ui/tuple/tuple-struct-fields/test2.stderr
+++ b/tests/ui/tuple/tuple-struct-fields/test2.stderr
@@ -22,6 +22,8 @@ error[E0412]: cannot find type `foo` in this scope
    |
 LL |     define_struct! { (foo) }
    |                       ^^^ not found in this scope
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/tuple/tuple-struct-fields/test3.stderr b/tests/ui/tuple/tuple-struct-fields/test3.stderr
index 75262ed5780..00b07c03152 100644
--- a/tests/ui/tuple/tuple-struct-fields/test3.stderr
+++ b/tests/ui/tuple/tuple-struct-fields/test3.stderr
@@ -22,6 +22,8 @@ error[E0412]: cannot find type `foo` in this scope
    |
 LL |     define_struct! { foo }
    |                      ^^^ not found in this scope
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr
index 0202a2fea49..359bd09ecd0 100644
--- a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr
+++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr
@@ -36,6 +36,7 @@ note: `V` could also refer to the associated type defined here
    |
 LL |     type V;
    |     ^^^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/normalize-alias-type.rs b/tests/ui/type-alias-impl-trait/normalize-alias-type.rs
new file mode 100644
index 00000000000..7c62002b931
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/normalize-alias-type.rs
@@ -0,0 +1,32 @@
+// check-pass
+// compile-flags: -Z mir-opt-level=3
+#![feature(type_alias_impl_trait)]
+#![crate_type = "lib"]
+pub trait Tr {
+    fn get(&self) -> u32;
+}
+
+impl Tr for (u32,) {
+    #[inline]
+    fn get(&self) -> u32 { self.0 }
+}
+
+pub fn tr1() -> impl Tr {
+    (32,)
+}
+
+pub fn tr2() -> impl Tr {
+    struct Inner {
+        x: X,
+    }
+    type X = impl Tr;
+    impl Tr for Inner {
+        fn get(&self) -> u32 {
+            self.x.get()
+        }
+    }
+
+    Inner {
+        x: tr1(),
+    }
+}
diff --git a/tests/ui/type-alias-impl-trait/tait-normalize.rs b/tests/ui/type-alias-impl-trait/tait-normalize.rs
new file mode 100644
index 00000000000..26d94dbb42a
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/tait-normalize.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+fn enum_upvar() {
+    type T = impl Copy;
+    let foo: T = Some((1u32, 2u32));
+    let x = move || match foo {
+        None => (),
+        Some((a, b)) => (),
+    };
+}
+
+fn main(){}
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs
index 857066c78c9..9796823a724 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs
@@ -4,7 +4,7 @@
 // FIXME: this is ruled out for now but should work
 
 type Foo = fn() -> impl Send;
-//~^ ERROR: `impl Trait` only allowed in function and inherent method return types
+//~^ ERROR: `impl Trait` only allowed in function and inherent method argument and return types
 
 fn make_foo() -> Foo {
     || 15
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr
index ff375b2ff86..e57c59d6165 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in `fn` pointer return types
   --> $DIR/type-alias-impl-trait-fn-type.rs:6:20
    |
 LL | type Foo = fn() -> impl Send;
diff --git a/tests/ui/type/subtyping-opaque-type.rs b/tests/ui/type/subtyping-opaque-type.rs
new file mode 100644
index 00000000000..beda232ea8b
--- /dev/null
+++ b/tests/ui/type/subtyping-opaque-type.rs
@@ -0,0 +1,19 @@
+// check-pass
+// compile-flags: -Zvalidate-mir
+trait Duh {}
+
+impl Duh for i32 {}
+
+trait Trait {
+    type Assoc: Duh;
+}
+
+impl<R: Duh, F: FnMut() -> R> Trait for F {
+    type Assoc = R;
+}
+
+fn foo() -> impl Trait<Assoc = impl Send> {
+    || 42
+}
+
+fn main() {}
diff --git a/tests/ui/type/type-check/point-at-inference-issue-116155.rs b/tests/ui/type/type-check/point-at-inference-issue-116155.rs
new file mode 100644
index 00000000000..1e9942d42e8
--- /dev/null
+++ b/tests/ui/type/type-check/point-at-inference-issue-116155.rs
@@ -0,0 +1,17 @@
+struct S<T>(T);
+
+impl<T> S<T> {
+    fn new() -> Self {
+        loop {}
+    }
+
+    fn constrain<F: Fn() -> T>(&self, _f: F) {}
+}
+
+fn main() {
+    let s = S::new();
+    let c = || true;
+    s.constrain(c);
+    let _: S<usize> = s;
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/type/type-check/point-at-inference-issue-116155.stderr b/tests/ui/type/type-check/point-at-inference-issue-116155.stderr
new file mode 100644
index 00000000000..c8c01603cb8
--- /dev/null
+++ b/tests/ui/type/type-check/point-at-inference-issue-116155.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/point-at-inference-issue-116155.rs:15:23
+   |
+LL |     s.constrain(c);
+   |     -           - this argument has type `{closure@$DIR/point-at-inference-issue-116155.rs:13:13: 13:15}`...
+   |     |
+   |     ... which causes `s` to have type `S<bool>`
+LL |     let _: S<usize> = s;
+   |            --------   ^ expected `S<usize>`, found `S<bool>`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `S<usize>`
+              found struct `S<bool>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/issue-104513-ice.rs b/tests/ui/typeck/issue-104513-ice.rs
index bcac0fa1e70..4968d3f51fe 100644
--- a/tests/ui/typeck/issue-104513-ice.rs
+++ b/tests/ui/typeck/issue-104513-ice.rs
@@ -1,6 +1,6 @@
 struct S;
 fn f() {
     let _: S<impl Oops> = S; //~ ERROR cannot find trait `Oops` in this scope
-    //~^ ERROR `impl Trait` only allowed in function and inherent method return types
+    //~^ ERROR `impl Trait` only allowed in function and inherent method argument and return types
 }
 fn main() {}
diff --git a/tests/ui/typeck/issue-104513-ice.stderr b/tests/ui/typeck/issue-104513-ice.stderr
index 09187d7863a..56c6b336154 100644
--- a/tests/ui/typeck/issue-104513-ice.stderr
+++ b/tests/ui/typeck/issue-104513-ice.stderr
@@ -4,7 +4,7 @@ error[E0405]: cannot find trait `Oops` in this scope
 LL |     let _: S<impl Oops> = S;
    |                   ^^^^ not found in this scope
 
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
+error[E0562]: `impl Trait` only allowed in function and inherent method argument and return types, not in variable bindings
   --> $DIR/issue-104513-ice.rs:3:14
    |
 LL |     let _: S<impl Oops> = S;
diff --git a/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
index dc4bc5b5f44..6c3302f29c2 100644
--- a/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
+++ b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-57673-ice-on-deref-of-boxed-trait.rs:5:5
    |
 LL | fn ice(x: Box<dyn Iterator<Item=()>>) {
-   |                                       - help: try adding a return type: `-> (dyn Iterator<Item = ()> + 'static)`
+   |                                      - help: try adding a return type: `-> (dyn Iterator<Item = ()> + 'static)`
 LL |     *x
    |     ^^ expected `()`, found `dyn Iterator`
    |
diff --git a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr
index 0d72ae118f3..c46f4ec1ec3 100644
--- a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr
+++ b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-90027-async-fn-return-suggestion.rs:4:5
    |
 LL | async fn hello() {
-   |                  - help: try adding a return type: `-> i32`
+   |                 - help: try adding a return type: `-> i32`
 LL |     0
    |     ^ expected `()`, found integer
 
diff --git a/tests/ui/typeck/issue-91267.stderr b/tests/ui/typeck/issue-91267.stderr
index 72acd9c673b..7e48b251980 100644
--- a/tests/ui/typeck/issue-91267.stderr
+++ b/tests/ui/typeck/issue-91267.stderr
@@ -14,7 +14,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-91267.rs:4:5
    |
 LL | fn main() {
-   |           - expected `()` because of default return type
+   |          - expected `()` because of default return type
 LL |     type_ascribe!(0, u8<e<5>=e>)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `u8`
 
diff --git a/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr
index a3517af877c..67ca2b061f9 100644
--- a/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr
+++ b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr
@@ -21,6 +21,8 @@ LL | trait Trait: Copy<dyn Send> {}
    |              ^^^^---------- help: remove these generics
    |              |
    |              expected 0 generic arguments
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:8:21
diff --git a/tests/ui/unknown-lint-tool-name.stderr b/tests/ui/unknown-lint-tool-name.stderr
index 5f8349ce6c3..72731ab1e3d 100644
--- a/tests/ui/unknown-lint-tool-name.stderr
+++ b/tests/ui/unknown-lint-tool-name.stderr
@@ -21,6 +21,7 @@ LL | #![deny(foo::bar)]
    |         ^^^
    |
    = help: add `#![register_tool(foo)]` to the crate root
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
   --> $DIR/unknown-lint-tool-name.rs:4:9
@@ -29,6 +30,7 @@ LL | #[allow(foo::bar)]
    |         ^^^
    |
    = help: add `#![register_tool(foo)]` to the crate root
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr
index 32f8d2f45dc..f0450aea49a 100644
--- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr
+++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr
@@ -8,11 +8,13 @@ error: unknown lint: `test_unstable_lint`
    |
    = note: the `test_unstable_lint` lint is unstable
    = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: unknown lint: `test_unstable_lint`
    |
    = note: the `test_unstable_lint` lint is unstable
    = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr
index 2a2a9811bfb..20a36b28dc6 100644
--- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr
+++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr
@@ -20,6 +20,7 @@ LL | #![allow(test_unstable_lint)]
    |
    = note: the `test_unstable_lint` lint is unstable
    = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: unknown lint: `test_unstable_lint`
   --> $DIR/deny-unstable-lint-inline.rs:4:1
@@ -29,6 +30,7 @@ LL | #![allow(test_unstable_lint)]
    |
    = note: the `test_unstable_lint` lint is unstable
    = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr
index dd9ecf02fa6..a2deecf1caf 100644
--- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr
+++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr
@@ -8,11 +8,13 @@ warning: unknown lint: `test_unstable_lint`
    |
    = note: the `test_unstable_lint` lint is unstable
    = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `test_unstable_lint`
    |
    = note: the `test_unstable_lint` lint is unstable
    = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr
index 0548cd226d8..12afb2e294a 100644
--- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr
+++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr
@@ -20,6 +20,7 @@ LL | #![allow(test_unstable_lint)]
    |
    = note: the `test_unstable_lint` lint is unstable
    = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: unknown lint: `test_unstable_lint`
   --> $DIR/warn-unknown-unstable-lint-inline.rs:4:1
@@ -29,6 +30,7 @@ LL | #![allow(test_unstable_lint)]
    |
    = note: the `test_unstable_lint` lint is unstable
    = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/use/use-super-global-path.stderr b/tests/ui/use/use-super-global-path.stderr
index 7014a12e9dd..00d172f4799 100644
--- a/tests/ui/use/use-super-global-path.stderr
+++ b/tests/ui/use/use-super-global-path.stderr
@@ -9,6 +9,8 @@ error[E0433]: failed to resolve: global paths cannot start with `super`
    |
 LL |     use ::super::{S, Z};
    |           ^^^^^ global paths cannot start with `super`
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0433]: failed to resolve: global paths cannot start with `super`
   --> $DIR/use-super-global-path.rs:11:15
diff --git a/triagebot.toml b/triagebot.toml
index 648997ad6f0..4b051db0d73 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -570,6 +570,11 @@ message = "`src/tools/x` was changed. Bump version of Cargo.toml in `src/tools/x
 message = "Third-party dependency whitelist may have been modified! You must ensure that any new dependencies have compatible licenses before merging."
 cc = ["@davidtwco", "@wesleywiser"]
 
+[mentions."src/bootstrap/config.rs"]
+message = "This PR changes `src/bootstrap/config.rs`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/lib.rs` and `change-id` in `config.example.toml`."
+[mentions."config.example.toml"]
+message = "This PR changes `config.example.toml`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/lib.rs` and `change-id` in `config.example.toml`."
+
 [mentions."src/bootstrap/defaults/config.compiler.toml"]
 message = "This PR changes src/bootstrap/defaults/config.compiler.toml. If appropriate, please also update `config.codegen.toml` so the defaults are in sync."
 [mentions."src/bootstrap/defaults/config.codegen.toml"]
@@ -589,7 +594,7 @@ cc = ["@nnethercote"]
 [assign]
 warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
-users_on_vacation = ["jyn514", "jackh726"]
+users_on_vacation = ["jyn514", "jackh726", "WaffleLapkin"]
 
 [assign.adhoc_groups]
 compiler-team = [
diff --git a/x b/x
index d967988e1c4..ef3eb8b04b4 100755
--- a/x
+++ b/x
@@ -8,7 +8,7 @@
 set -eu
 
 # syntax check
-sh -n $0
+sh -n "$0"
 
 realpath() {
     if [ -d "$1" ]; then