about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/pull_request_template.md4
-rw-r--r--.github/workflows/ci.yml2
-rw-r--r--.mailmap1
-rw-r--r--Cargo.lock31
-rw-r--r--compiler/rustc_borrowck/src/constraints/mod.rs16
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs27
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs17
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs372
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs4
-rw-r--r--compiler/rustc_borrowck/src/renumber.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs18
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs40
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs100
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs5
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs6
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs16
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs24
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs32
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs16
-rw-r--r--compiler/rustc_const_eval/src/interpret/discriminant.rs5
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs35
-rw-r--r--compiler/rustc_const_eval/src/interpret/intern.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs40
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs16
-rw-r--r--compiler/rustc_const_eval/src/lib.rs1
-rw-r--r--compiler/rustc_const_eval/src/util/caller_location.rs4
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs4
-rw-r--r--compiler/rustc_data_structures/Cargo.toml6
-rw-r--r--compiler/rustc_data_structures/src/graph/scc/mod.rs401
-rw-r--r--compiler/rustc_data_structures/src/graph/scc/tests.rs214
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs93
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs25
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs56
-rw-r--r--compiler/rustc_feature/src/accepted.rs4
-rw-r--r--compiler/rustc_feature/src/unstable.rs12
-rw-r--r--compiler/rustc_hir/src/hir.rs38
-rw-r--r--compiler/rustc_hir/src/lang_items.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs71
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs17
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl4
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs57
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs26
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs54
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs22
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs65
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs60
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs135
-rw-r--r--compiler/rustc_infer/Cargo.toml1
-rw-r--r--compiler/rustc_infer/src/infer/at.rs89
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs38
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs6
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs105
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/outlives/for_liveness.rs4
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs18
-rw-r--r--compiler/rustc_infer/src/infer/relate/glb.rs7
-rw-r--r--compiler/rustc_infer/src/infer/relate/lub.rs7
-rw-r--r--compiler/rustc_infer/src/infer/relate/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/relate/type_relating.rs10
-rw-r--r--compiler/rustc_infer/src/traits/util.rs3
-rw-r--r--compiler/rustc_lint/messages.ftl1
-rw-r--r--compiler/rustc_lint/src/deref_into_dyn_supertrait.rs4
-rw-r--r--compiler/rustc_lint/src/lints.rs14
-rw-r--r--compiler/rustc_lint/src/non_fmt_panic.rs8
-rw-r--r--compiler/rustc_lint/src/non_local_def.rs8
-rw-r--r--compiler/rustc_lint/src/shadowed_into_iter.rs4
-rw-r--r--compiler/rustc_lint/src/traits.rs4
-rw-r--r--compiler/rustc_lint/src/unused.rs4
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs58
-rw-r--r--compiler/rustc_log/Cargo.toml2
-rw-r--r--compiler/rustc_log/src/lib.rs8
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs2
-rw-r--r--compiler/rustc_middle/src/middle/lang_items.rs4
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs14
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs4
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs6
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs14
-rw-r--r--compiler/rustc_middle/src/traits/query.rs2
-rw-r--r--compiler/rustc_middle/src/traits/util.rs2
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs27
-rw-r--r--compiler/rustc_middle/src/ty/context.rs84
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs2
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs9
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs5
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs3
-rw-r--r--compiler/rustc_middle/src/ty/predicate.rs15
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs6
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs4
-rw-r--r--compiler/rustc_middle/src/util/call_kind.rs8
-rw-r--r--compiler/rustc_middle/src/values.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs3
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs2
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs3
-rw-r--r--compiler/rustc_mir_build/src/errors.rs5
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs3
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/block.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs3
-rw-r--r--compiler/rustc_mir_transform/src/add_retag.rs3
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs3
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs27
-rw-r--r--compiler/rustc_mir_transform/src/known_panics_lint.rs6
-rw-r--r--compiler/rustc_mir_transform/src/promote_consts.rs2
-rw-r--r--compiler/rustc_mir_transform/src/required_consts.rs2
-rw-r--r--compiler/rustc_mir_transform/src/reveal_all.rs4
-rw-r--r--compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs2
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs3
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs3
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs6
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs3
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs2
-rw-r--r--compiler/rustc_passes/src/dead.rs6
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs46
-rw-r--r--compiler/rustc_resolve/src/late.rs24
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs24
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs2
-rw-r--r--compiler/rustc_smir/src/rustc_smir/builder.rs8
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs19
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/mir.rs6
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs8
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs21
-rw-r--r--compiler/rustc_span/src/lib.rs21
-rw-r--r--compiler/rustc_span/src/span_encoding.rs270
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_target/src/asm/mod.rs12
-rw-r--r--compiler/rustc_target/src/asm/x86.rs22
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/alias_relate.rs12
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs137
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs260
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs296
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs83
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs37
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs22
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/build.rs7
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs11
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs72
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs85
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs32
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs191
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs38
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/_match.rs (renamed from compiler/rustc_infer/src/infer/relate/_match.rs)6
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs57
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs44
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs2
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs75
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs12
-rw-r--r--compiler/rustc_type_ir/src/infcx.rs76
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs134
-rw-r--r--compiler/rustc_type_ir/src/interner.rs61
-rw-r--r--compiler/rustc_type_ir/src/lang_items.rs8
-rw-r--r--compiler/rustc_type_ir/src/lib.rs2
-rw-r--r--compiler/rustc_type_ir/src/relate.rs20
-rw-r--r--compiler/stable_mir/src/compiler_interface.rs4
-rw-r--r--compiler/stable_mir/src/crate_def.rs37
-rw-r--r--compiler/stable_mir/src/lib.rs8
-rw-r--r--compiler/stable_mir/src/mir/body.rs27
-rw-r--r--compiler/stable_mir/src/mir/pretty.rs2
-rw-r--r--compiler/stable_mir/src/mir/visit.rs12
-rw-r--r--compiler/stable_mir/src/ty.rs37
-rw-r--r--library/alloc/src/boxed.rs27
-rw-r--r--library/alloc/src/collections/binary_heap/mod.rs7
-rw-r--r--library/alloc/src/ffi/c_str.rs2
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/rc.rs99
-rw-r--r--library/alloc/src/rc/tests.rs26
-rw-r--r--library/alloc/src/sync.rs6
-rw-r--r--library/alloc/src/vec/mod.rs2
-rw-r--r--library/core/src/cell.rs2
-rw-r--r--library/core/src/cell/lazy.rs14
-rw-r--r--library/core/src/future/async_drop.rs1
-rw-r--r--library/core/src/future/future.rs2
-rw-r--r--library/core/src/intrinsics.rs14
-rw-r--r--library/core/src/intrinsics/simd.rs1
-rw-r--r--library/core/src/iter/traits/collect.rs3
-rw-r--r--library/core/src/iter/traits/iterator.rs21
-rw-r--r--library/core/src/net/ip_addr.rs20
-rw-r--r--library/core/src/num/int_macros.rs18
-rw-r--r--library/core/src/num/nonzero.rs2
-rw-r--r--library/core/src/num/uint_macros.rs4
-rw-r--r--library/core/src/ops/async_function.rs8
-rw-r--r--library/core/src/ops/coroutine.rs2
-rw-r--r--library/core/src/option.rs28
-rw-r--r--library/core/src/prelude/common.rs2
-rw-r--r--library/core/src/ptr/metadata.rs40
-rw-r--r--library/core/src/ptr/non_null.rs66
-rw-r--r--library/core/src/slice/ascii.rs12
-rw-r--r--library/core/src/slice/iter.rs2
-rw-r--r--library/core/src/slice/mod.rs10
-rw-r--r--library/core/src/str/mod.rs16
-rw-r--r--library/core/src/time.rs4
-rw-r--r--library/proc_macro/src/escape.rs57
-rw-r--r--library/proc_macro/src/lib.rs51
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/alloc.rs4
-rw-r--r--library/std/src/env.rs16
-rw-r--r--library/std/src/fs.rs2
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--library/std/src/path.rs65
-rw-r--r--library/std/src/prelude/common.rs2
-rw-r--r--library/std/src/process.rs19
-rw-r--r--library/std/src/sync/lazy_lock.rs22
-rw-r--r--library/std/src/sync/mod.rs5
-rw-r--r--library/std/src/sync/once.rs15
-rw-r--r--library/std/src/sys/pal/hermit/fd.rs39
-rw-r--r--library/std/src/sys/pal/hermit/fs.rs45
-rw-r--r--library/std/src/sys/pal/hermit/futex.rs2
-rw-r--r--library/std/src/sys/pal/hermit/io.rs82
-rw-r--r--library/std/src/sys/pal/hermit/mod.rs1
-rw-r--r--library/std/src/sys/pal/hermit/net.rs13
-rw-r--r--library/std/src/sys/pal/hermit/os.rs2
-rw-r--r--library/std/src/sys/pal/hermit/stdio.rs67
-rw-r--r--library/std/src/sys/pal/hermit/thread.rs2
-rw-r--r--library/std/src/sys/pal/hermit/time.rs18
-rw-r--r--library/std/src/sys/pal/unix/fs.rs21
-rw-r--r--library/std/src/sys/pal/windows/c/windows_sys.rs483
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs9
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs6
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/format.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/run.rs8
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs6
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs35
-rw-r--r--src/bootstrap/src/core/builder.rs1
-rw-r--r--src/bootstrap/src/core/config/config.rs4
-rw-r--r--src/bootstrap/src/core/sanity.rs30
-rw-r--r--src/bootstrap/src/lib.rs2
-rw-r--r--src/bootstrap/src/utils/helpers.rs109
-rw-r--r--src/bootstrap/src/utils/helpers/tests.rs21
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile28
-rwxr-xr-xsrc/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh2
-rwxr-xr-xsrc/ci/docker/scripts/build-fuchsia-toolchain.sh8
-rwxr-xr-xsrc/ci/docker/scripts/fuchsia-test-runner.py2
-rw-r--r--src/ci/github-actions/jobs.yml6
-rw-r--r--src/doc/rustc/src/check-cfg.md7
-rw-r--r--src/doc/rustc/src/platform-support.md8
-rw-r--r--src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md12
-rw-r--r--src/doc/rustc/src/platform-support/wasm32-wasip1.md11
-rw-r--r--src/doc/rustc/src/platform-support/wasm32-wasip2.md8
-rw-r--r--src/stage0856
-rw-r--r--src/tools/build-manifest/src/main.rs2
-rw-r--r--src/tools/build_helper/src/git.rs26
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/CHANGELOG.md65
-rw-r--r--src/tools/clippy/Cargo.toml2
-rw-r--r--src/tools/clippy/README.md4
-rw-r--r--src/tools/clippy/book/src/configuration.md2
-rw-r--r--src/tools/clippy/book/src/development/basics.md2
-rw-r--r--src/tools/clippy/book/src/development/defining_lints.md4
-rw-r--r--src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md12
-rw-r--r--src/tools/clippy/clippy_config/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_dummy/PUBLISH.md2
-rw-r--r--src/tools/clippy/clippy_dummy/crates-readme.md4
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/maybe_misused_cfg.rs51
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/mismatched_target_os.rs90
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/mod.rs73
-rw-r--r--src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs54
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs60
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/collection_is_never_read.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/deprecated_lints.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/missing_headers.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/float_literal.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_return.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/indexing_slicing.rs50
-rw-r--r--src/tools/clippy/clippy_lints/src/integer_division_remainder_used.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs34
-rw-r--r--src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.deprecated.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs62
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs124
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/search_is_some.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs47
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs64
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs46
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_splitn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/utils.rs63
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/zero_prefixed_literal.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_bool.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_late_init.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs164
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/non_canonical_impls.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_async_block.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/reference.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs50
-rw-r--r--src/tools/clippy/clippy_lints/src/string_patterns.rs227
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_self.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap_in_result.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs6
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs14
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs12
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs24
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/ptr.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/source.rs45
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs43
-rw-r--r--src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs14
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs14
-rw-r--r--src/tools/clippy/declare_clippy_lint/Cargo.toml2
-rw-r--r--src/tools/clippy/lintcheck/README.md4
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr49
-rw-r--r--src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml4
-rw-r--r--src/tools/clippy/tests/ui-cargo/lint_groups_priority/pass/Cargo.toml7
-rw-r--r--src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.rs1
-rw-r--r--src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.stderr2
-rw-r--r--src/tools/clippy/tests/ui/author.stdout2
-rw-r--r--src/tools/clippy/tests/ui/author/blocks.stdout6
-rw-r--r--src/tools/clippy/tests/ui/author/call.stdout2
-rw-r--r--src/tools/clippy/tests/ui/author/if.stdout2
-rw-r--r--src/tools/clippy/tests/ui/author/issue_3849.stdout2
-rw-r--r--src/tools/clippy/tests/ui/author/loop.stdout2
-rw-r--r--src/tools/clippy/tests/ui/author/macro_in_closure.stdout2
-rw-r--r--src/tools/clippy/tests/ui/author/matches.stdout4
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs13
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macros.rs6
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions.fixed13
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions.rs13
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions_closure.rs89
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions_closure.stderr39
-rw-r--r--src/tools/clippy/tests/ui/cfg_features.fixed29
-rw-r--r--src/tools/clippy/tests/ui/cfg_features.rs29
-rw-r--r--src/tools/clippy/tests/ui/cfg_features.stderr53
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6252.stderr4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-9445.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-9445.stderr7
-rw-r--r--src/tools/clippy/tests/ui/crashes/mut_mut_macro.rs33
-rw-r--r--src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.stderr43
-rw-r--r--src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr27
-rw-r--r--src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr26
-rw-r--r--src/tools/clippy/tests/ui/deprecated.rs2
-rw-r--r--src/tools/clippy/tests/ui/deprecated.stderr14
-rw-r--r--src/tools/clippy/tests/ui/deref_addrof.fixed4
-rw-r--r--src/tools/clippy/tests/ui/deref_addrof.rs4
-rw-r--r--src/tools/clippy/tests/ui/deref_addrof.stderr12
-rw-r--r--src/tools/clippy/tests/ui/doc_unsafe.stderr10
-rw-r--r--src/tools/clippy/tests/ui/double_neg.rs2
-rw-r--r--src/tools/clippy/tests/ui/eta.fixed11
-rw-r--r--src/tools/clippy/tests/ui/eta.rs11
-rw-r--r--src/tools/clippy/tests/ui/eta.stderr14
-rw-r--r--src/tools/clippy/tests/ui/floating_point_log.fixed15
-rw-r--r--src/tools/clippy/tests/ui/floating_point_log.rs15
-rw-r--r--src/tools/clippy/tests/ui/format_args.fixed1
-rw-r--r--src/tools/clippy/tests/ui/format_args.rs1
-rw-r--r--src/tools/clippy/tests/ui/format_args.stderr16
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_index.rs20
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_index.stderr32
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_slice.rs129
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_slice.stderr58
-rw-r--r--src/tools/clippy/tests/ui/infinite_loops.rs2
-rw-r--r--src/tools/clippy/tests/ui/iter_over_hash_type.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_pattern_char_comparison.fixed49
-rw-r--r--src/tools/clippy/tests/ui/manual_pattern_char_comparison.rs49
-rw-r--r--src/tools/clippy/tests/ui/manual_pattern_char_comparison.stderr59
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed6
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or_default.rs15
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or_default.stderr25
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.fixed17
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.rs18
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.stderr18
-rw-r--r--src/tools/clippy/tests/ui/mismatched_target_os_non_unix.fixed25
-rw-r--r--src/tools/clippy/tests/ui/mismatched_target_os_non_unix.rs25
-rw-r--r--src/tools/clippy/tests/ui/mismatched_target_os_non_unix.stderr37
-rw-r--r--src/tools/clippy/tests/ui/mismatched_target_os_unix.fixed60
-rw-r--r--src/tools/clippy/tests/ui/mismatched_target_os_unix.rs60
-rw-r--r--src/tools/clippy/tests/ui/mismatched_target_os_unix.stderr184
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs30
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr27
-rw-r--r--src/tools/clippy/tests/ui/missing_fields_in_debug.rs18
-rw-r--r--src/tools/clippy/tests/ui/missing_fields_in_debug.stderr16
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.fixed12
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.rs12
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.stderr20
-rw-r--r--src/tools/clippy/tests/ui/needless_character_iteration.fixed57
-rw-r--r--src/tools/clippy/tests/ui/needless_character_iteration.rs65
-rw-r--r--src/tools/clippy/tests/ui/needless_character_iteration.stderr67
-rw-r--r--src/tools/clippy/tests/ui/needless_maybe_sized.fixed116
-rw-r--r--src/tools/clippy/tests/ui/needless_maybe_sized.rs119
-rw-r--r--src/tools/clippy/tests/ui/needless_maybe_sized.stderr353
-rw-r--r--src/tools/clippy/tests/ui/new_ret_no_self.rs5
-rw-r--r--src/tools/clippy/tests/ui/new_ret_no_self.stderr3
-rw-r--r--src/tools/clippy/tests/ui/non_canonical_clone_impl.fixed20
-rw-r--r--src/tools/clippy/tests/ui/non_canonical_clone_impl.rs20
-rw-r--r--src/tools/clippy/tests/ui/non_canonical_clone_impl.stderr8
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed2
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool_methods.rs2
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr32
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.fixed7
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.rs7
-rw-r--r--src/tools/clippy/tests/ui/overly_complex_bool_expr.fixed10
-rw-r--r--src/tools/clippy/tests/ui/overly_complex_bool_expr.rs10
-rw-r--r--src/tools/clippy/tests/ui/panic_in_result_fn.rs5
-rw-r--r--src/tools/clippy/tests/ui/panic_in_result_fn.stderr18
-rw-r--r--src/tools/clippy/tests/ui/search_is_some.rs1
-rw-r--r--src/tools/clippy/tests/ui/search_is_some.stderr16
-rw-r--r--src/tools/clippy/tests/ui/single_char_add_str.fixed10
-rw-r--r--src/tools/clippy/tests/ui/single_char_add_str.rs10
-rw-r--r--src/tools/clippy/tests/ui/single_char_add_str.stderr58
-rw-r--r--src/tools/clippy/tests/ui/str_to_string.fixed9
-rw-r--r--src/tools/clippy/tests/ui/str_to_string.stderr7
-rw-r--r--src/tools/clippy/tests/ui/type_repetition_in_bounds.rs6
-rw-r--r--src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr10
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_clippy_cfg.rs8
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr28
-rw-r--r--src/tools/clippy/tests/ui/unwrap_in_result.rs5
-rw-r--r--src/tools/clippy/tests/ui/unwrap_in_result.stderr18
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion_try.rs6
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion_try.stderr18
-rw-r--r--src/tools/clippy/util/gh-pages/script.js2
-rw-r--r--src/tools/compiletest/src/common.rs2
-rw-r--r--src/tools/compiletest/src/header.rs75
-rw-r--r--src/tools/compiletest/src/header/cfg.rs2
-rw-r--r--src/tools/compiletest/src/header/tests.rs66
-rw-r--r--src/tools/compiletest/src/lib.rs2
-rw-r--r--src/tools/compiletest/src/read2.rs5
-rw-r--r--src/tools/compiletest/src/read2/tests.rs6
-rw-r--r--src/tools/compiletest/src/runtest.rs68
-rw-r--r--src/tools/compiletest/src/runtest/coverage.rs3
-rw-r--r--src/tools/compiletest/src/runtest/debugger.rs2
-rw-r--r--src/tools/compiletest/src/tests.rs10
-rw-r--r--src/tools/compiletest/src/util.rs8
-rw-r--r--src/tools/generate-windows-sys/Cargo.toml2
-rw-r--r--src/tools/jsondoclint/src/validator.rs12
-rw-r--r--src/tools/lint-docs/src/groups.rs8
-rw-r--r--src/tools/lint-docs/src/lib.rs12
-rw-r--r--src/tools/miri/README.md32
-rw-r--r--src/tools/miri/cargo-miri/src/phases.rs202
-rw-r--r--src/tools/miri/cargo-miri/src/util.rs36
-rw-r--r--src/tools/miri/miri-script/src/main.rs11
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/concurrency/sync.rs10
-rw-r--r--src/tools/miri/src/helpers.rs8
-rw-r--r--src/tools/miri/src/intrinsics/simd.rs6
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/os_str.rs4
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs4
-rw-r--r--src/tools/miri/src/shims/unix/linux/epoll.rs11
-rw-r--r--src/tools/miri/src/shims/unix/socket.rs201
-rw-r--r--src/tools/miri/src/shims/x86/avx.rs8
-rw-r--r--src/tools/miri/src/shims/x86/mod.rs6
-rw-r--r--src/tools/miri/src/shims/x86/sse42.rs500
-rw-r--r--src/tools/miri/tests/fail-dep/libc/socketpair_read_blocking.rs12
-rw-r--r--src/tools/miri/tests/fail-dep/libc/socketpair_read_blocking.stderr14
-rw-r--r--src/tools/miri/tests/fail-dep/libc/socketpair_write_blocking.rs16
-rw-r--r--src/tools/miri/tests/fail-dep/libc/socketpair_write_blocking.stderr14
-rw-r--r--src/tools/miri/tests/fail/validity/invalid_enum_cast.rs14
-rw-r--r--src/tools/miri/tests/fail/validity/invalid_enum_cast.stderr4
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs124
-rw-r--r--src/tools/miri/tests/pass/float.rs149
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse42.rs443
-rw-r--r--src/tools/opt-dist/src/training.rs8
-rw-r--r--src/tools/remote-test-client/src/main.rs10
-rw-r--r--src/tools/remote-test-server/src/main.rs2
-rw-r--r--src/tools/run-make-support/CHANGELOG.md16
-rw-r--r--src/tools/run-make-support/Cargo.toml2
-rw-r--r--src/tools/run-make-support/src/cc.rs1
-rw-r--r--src/tools/run-make-support/src/clang.rs1
-rw-r--r--src/tools/run-make-support/src/command.rs13
-rw-r--r--src/tools/run-make-support/src/diff/mod.rs23
-rw-r--r--src/tools/run-make-support/src/lib.rs65
-rw-r--r--src/tools/run-make-support/src/llvm.rs127
-rw-r--r--src/tools/run-make-support/src/llvm_readobj.rs1
-rw-r--r--src/tools/run-make-support/src/run.rs23
-rw-r--r--src/tools/run-make-support/src/rustc.rs25
-rw-r--r--src/tools/run-make-support/src/rustdoc.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs1
-rw-r--r--src/tools/tidy/config/requirements.in6
-rw-r--r--src/tools/tidy/config/requirements.txt47
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt9
-rw-r--r--src/tools/tidy/src/alphabetical.rs2
-rw-r--r--src/tools/tidy/src/bins.rs6
-rw-r--r--src/tools/tidy/src/deps.rs8
-rw-r--r--src/tools/tidy/src/error_codes.rs8
-rw-r--r--src/tools/tidy/src/ext_tool_checks.rs36
-rw-r--r--src/tools/tidy/src/issues.txt3
-rw-r--r--src/tools/tidy/src/style.rs61
-rw-r--r--src/tools/tidy/src/walk.rs18
-rw-r--r--src/tools/tidy/src/x_version.rs2
-rw-r--r--tests/assembly/asm/x86-types.rs244
-rw-r--r--tests/assembly/issue-83585-small-pod-struct-equality.rs27
-rw-r--r--tests/codegen/instrument-coverage/instrument-coverage-off.rs1
-rw-r--r--tests/codegen/instrument-coverage/instrument-coverage.rs6
-rw-r--r--tests/codegen/instrument-coverage/testprog.rs2
-rw-r--r--tests/codegen/issues/issue-109328-split_first.rs16
-rw-r--r--tests/codegen/issues/issue-110797-enum-jump-same.rs26
-rw-r--r--tests/codegen/issues/issue-111508-vec-tryinto-array.rs22
-rw-r--r--tests/codegen/issues/issue-112509-slice-get-andthen-get.rs12
-rw-r--r--tests/codegen/issues/issue-113757-bounds-check-after-cmp-max.rs18
-rw-r--r--tests/codegen/issues/issue-118392.rs11
-rw-r--r--tests/codegen/issues/issue-36010-some-box-is_some.rs28
-rw-r--r--tests/codegen/issues/issue-68667-unwrap-combinators.rs15
-rw-r--r--tests/codegen/issues/issue-74938-array-split-at.rs14
-rw-r--r--tests/codegen/issues/issue-93036-assert-index.rs14
-rw-r--r--tests/codegen/naked-fn/naked-nocoverage.rs2
-rw-r--r--tests/codegen/pgo-counter-bias.rs2
-rw-r--r--tests/codegen/pgo-instrumentation.rs2
-rw-r--r--tests/codegen/slice-pointer-nonnull-unwrap.rs19
-rw-r--r--tests/crashes/109812.rs22
-rw-r--r--tests/crashes/124583.rs5
-rw-r--r--tests/crashes/125811.rs34
-rw-r--r--tests/crashes/125914.rs20
-rw-r--r--tests/run-make/allow-non-lint-warnings-cmdline/Makefile12
-rw-r--r--tests/run-make/codegen-options-parsing/Makefile34
-rw-r--r--tests/run-make/codegen-options-parsing/rmake.rs56
-rw-r--r--tests/run-make/const_fn_mir/Makefile6
-rw-r--r--tests/run-make/const_fn_mir/rmake.rs8
-rw-r--r--tests/run-make/dep-graph/Makefile12
-rw-r--r--tests/run-make/dep-graph/rmake.rs18
-rw-r--r--tests/run-make/optimization-remarks-dir-pgo/Makefile4
-rw-r--r--tests/run-make/pgo-branch-weights/Makefile35
-rw-r--r--tests/run-make/pgo-branch-weights/rmake.rs41
-rw-r--r--tests/run-make/pgo-gen-lto/Makefile4
-rw-r--r--tests/run-make/pgo-gen-no-imp-symbols/Makefile4
-rw-r--r--tests/run-make/pgo-gen/Makefile4
-rw-r--r--tests/run-make/pgo-indirect-call-promotion/Makefile4
-rw-r--r--tests/run-make/pgo-use/Makefile4
-rw-r--r--tests/run-make/short-ice/Makefile10
-rw-r--r--tests/run-make/short-ice/check.sh36
-rw-r--r--tests/run-make/short-ice/rmake.rs42
-rw-r--r--tests/run-make/symlinked-extern/Makefile12
-rw-r--r--tests/run-make/symlinked-extern/rmake.rs21
-rw-r--r--tests/run-make/symlinked-libraries/Makefile11
-rw-r--r--tests/run-make/symlinked-libraries/rmake.rs16
-rw-r--r--tests/run-make/symlinked-rlib/Makefile10
-rw-r--r--tests/run-make/symlinked-rlib/rmake.rs16
-rw-r--r--tests/run-make/track-pgo-dep-info/Makefile1
-rw-r--r--tests/rustdoc-gui/help-page.goml69
-rw-r--r--tests/ui-fulldeps/stable-mir/check_def_ty.rs114
-rw-r--r--tests/ui-fulldeps/stable-mir/check_intrinsics.rs19
-rw-r--r--tests/ui-fulldeps/stable-mir/check_transform.rs8
-rw-r--r--tests/ui/allow-non-lint-warnings.rs (renamed from tests/run-make/allow-non-lint-warnings-cmdline/foo.rs)3
-rw-r--r--tests/ui/asm/x86_64/type-check-3.stderr10
-rw-r--r--tests/ui/associated-type-bounds/no-gat-position.rs1
-rw-r--r--tests/ui/associated-type-bounds/no-gat-position.stderr5
-rw-r--r--tests/ui/associated-types/associated-types-eq-2.rs2
-rw-r--r--tests/ui/associated-types/associated-types-eq-2.stderr62
-rw-r--r--tests/ui/associated-types/defaults-unsound-62211-1.next.stderr21
-rw-r--r--tests/ui/associated-types/defaults-unsound-62211-1.rs1
-rw-r--r--tests/ui/associated-types/defaults-unsound-62211-2.next.stderr21
-rw-r--r--tests/ui/associated-types/defaults-unsound-62211-2.rs1
-rw-r--r--tests/ui/associated-types/issue-54108.next.stderr21
-rw-r--r--tests/ui/associated-types/issue-54108.rs1
-rw-r--r--tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr5
-rw-r--r--tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr2
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr2
-rw-r--r--tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr4
-rw-r--r--tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs2
-rw-r--r--tests/ui/coherence/occurs-check/associated-type.next.stderr4
-rw-r--r--tests/ui/coherence/occurs-check/associated-type.rs2
-rw-r--r--tests/ui/const-generics/issues/issue-82956.stderr2
-rw-r--r--tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs3
-rw-r--r--tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr22
-rw-r--r--tests/ui/const-generics/parser-error-recovery/issue-89013.rs1
-rw-r--r--tests/ui/const-generics/parser-error-recovery/issue-89013.stderr22
-rw-r--r--tests/ui/consts/const_refs_to_static-ice-121413.rs4
-rw-r--r--tests/ui/consts/const_refs_to_static-ice-121413.stderr8
-rw-r--r--tests/ui/consts/dangling-alloc-id-ice.rs2
-rw-r--r--tests/ui/consts/dangling-alloc-id-ice.stderr10
-rw-r--r--tests/ui/consts/dangling-zst-ice-issue-126393.rs15
-rw-r--r--tests/ui/consts/dangling-zst-ice-issue-126393.stderr14
-rw-r--r--tests/ui/delegation/macro-inside-list.rs4
-rw-r--r--tests/ui/delegation/not-supported.rs4
-rw-r--r--tests/ui/delegation/not-supported.stderr61
-rw-r--r--tests/ui/delegation/self-hygiene.rs20
-rw-r--r--tests/ui/delegation/self-hygiene.stderr31
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr2
-rw-r--r--tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr2
-rw-r--r--tests/ui/editions/never-type-fallback-breaking.e2021.stderr33
-rw-r--r--tests/ui/editions/never-type-fallback-breaking.e2024.stderr6
-rw-r--r--tests/ui/editions/never-type-fallback-breaking.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.rs9
-rw-r--r--tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.stderr13
-rw-r--r--tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr2
-rw-r--r--tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.rs26
-rw-r--r--tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr110
-rw-r--r--tests/ui/generics/impl-block-params-declared-in-wrong-spot-issue-113073.rs33
-rw-r--r--tests/ui/generics/impl-block-params-declared-in-wrong-spot-issue-113073.stderr96
-rw-r--r--tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr4
-rw-r--r--tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr7
-rw-r--r--tests/ui/impl-trait/associated-type-undefine.rs28
-rw-r--r--tests/ui/impl-trait/associated-type-undefine.stderr20
-rw-r--r--tests/ui/impl-trait/call_method_ambiguous.next.stderr17
-rw-r--r--tests/ui/impl-trait/call_method_ambiguous.rs39
-rw-r--r--tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr17
-rw-r--r--tests/ui/impl-trait/call_method_on_inherent_impl.rs25
-rw-r--r--tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr16
-rw-r--r--tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr17
-rw-r--r--tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs22
-rw-r--r--tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr40
-rw-r--r--tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr31
-rw-r--r--tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs35
-rw-r--r--tests/ui/impl-trait/call_method_without_import.no_import.stderr37
-rw-r--r--tests/ui/impl-trait/call_method_without_import.rs42
-rw-r--r--tests/ui/impl-trait/method-resolution.rs26
-rw-r--r--tests/ui/impl-trait/method-resolution2.next.stderr20
-rw-r--r--tests/ui/impl-trait/method-resolution2.rs31
-rw-r--r--tests/ui/impl-trait/method-resolution3.current.stderr20
-rw-r--r--tests/ui/impl-trait/method-resolution3.next.stderr20
-rw-r--r--tests/ui/impl-trait/method-resolution3.rs27
-rw-r--r--tests/ui/impl-trait/method-resolution4.next.stderr22
-rw-r--r--tests/ui/impl-trait/method-resolution4.rs20
-rw-r--r--tests/ui/impl-trait/nested_impl_trait.stderr4
-rw-r--r--tests/ui/impl-trait/recursive-parent-trait-method-call.rs42
-rw-r--r--tests/ui/imports/cycle-import-in-std-1.stderr3
-rw-r--r--tests/ui/imports/cycle-import-in-std-2.stderr3
-rw-r--r--tests/ui/imports/import-alias-issue-121168.edition2018.stderr2
-rw-r--r--tests/ui/imports/import-alias-issue-121168.edition2021.stderr2
-rw-r--r--tests/ui/imports/issue-56125.stderr10
-rw-r--r--tests/ui/instrument-coverage/coverage-options.rs3
-rw-r--r--tests/ui/instrument-coverage/on-values.rs2
-rw-r--r--tests/ui/kindck/kindck-send-object.stderr2
-rw-r--r--tests/ui/kindck/kindck-send-object1.stderr2
-rw-r--r--tests/ui/kindck/kindck-send-object2.stderr2
-rw-r--r--tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs33
-rw-r--r--tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs52
-rw-r--r--tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr26
-rw-r--r--tests/ui/lint/non-local-defs/cargo-update.stderr3
-rw-r--r--tests/ui/lint/non-local-defs/inside-macro_rules.stderr1
-rw-r--r--tests/ui/lint/non-snake-case/allow-snake-case-field-destructuring-issue-89469.rs (renamed from tests/ui/lint/issue-89469.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin.rs (renamed from tests/ui/lint/lint-non-snake-case-crate-bin.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin2.rs (renamed from tests/ui/lint/lint-non-snake-case-crate-bin2.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin3.rs (renamed from tests/ui/lint/lint-non-snake-case-crate-bin3.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.rs (renamed from tests/ui/lint/lint-non-snake-case-crate-cdylib.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.stderr (renamed from tests/ui/lint/lint-non-snake-case-crate-cdylib.stderr)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.rs (renamed from tests/ui/lint/lint-non-snake-case-crate-dylib.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.stderr (renamed from tests/ui/lint/lint-non-snake-case-crate-dylib.stderr)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.rs (renamed from tests/ui/lint/lint-non-snake-case-crate-lib.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.stderr (renamed from tests/ui/lint/lint-non-snake-case-crate-lib.stderr)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.rs (renamed from tests/ui/lint/lint-non-snake-case-crate-proc-macro.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.stderr (renamed from tests/ui/lint/lint-non-snake-case-crate-proc-macro.stderr)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.rs (renamed from tests/ui/lint/lint-non-snake-case-crate-rlib.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.stderr (renamed from tests/ui/lint/lint-non-snake-case-crate-rlib.stderr)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.rs (renamed from tests/ui/lint/lint-non-snake-case-crate-staticlib.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.stderr (renamed from tests/ui/lint/lint-non-snake-case-crate-staticlib.stderr)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-functions.rs (renamed from tests/ui/lint/lint-non-snake-case-functions.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-functions.stderr (renamed from tests/ui/lint/lint-non-snake-case-functions.stderr)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-identifiers-suggestion-reserved.rs (renamed from tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-identifiers-suggestion-reserved.stderr (renamed from tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-lifetimes.rs (renamed from tests/ui/lint/lint-non-snake-case-lifetimes.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-lifetimes.stderr (renamed from tests/ui/lint/lint-non-snake-case-lifetimes.stderr)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-modules.rs (renamed from tests/ui/lint/lint-non-snake-case-modules.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-modules.stderr (renamed from tests/ui/lint/lint-non-snake-case-modules.stderr)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-no-lowercase-equivalent.rs (renamed from tests/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-nonstandard-style-unicode-2.rs (renamed from tests/ui/lint/lint-nonstandard-style-unicode-2.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-nonstandard-style-unicode-2.stderr (renamed from tests/ui/lint/lint-nonstandard-style-unicode-2.stderr)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-uppercase-variables.rs (renamed from tests/ui/lint/lint-uppercase-variables.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/lint-uppercase-variables.stderr (renamed from tests/ui/lint/lint-uppercase-variables.stderr)0
-rw-r--r--tests/ui/lint/non-snake-case/no-snake-case-warning-for-field-puns-issue-66362.rs (renamed from tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs)0
-rw-r--r--tests/ui/lint/non-snake-case/no-snake-case-warning-for-field-puns-issue-66362.stderr (renamed from tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr)10
-rw-r--r--tests/ui/lint/non-snake-case/non-snake-ffi-issue-31924.rs (renamed from tests/ui/lint/issue-31924-non-snake-ffi.rs)0
-rw-r--r--tests/ui/lint/use_suggestion_json.stderr4
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs58
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/hygiene.rs13
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/hygiene.stderr14
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.rs81
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.stderr95
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs50
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr68
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr4
-rw-r--r--tests/ui/methods/opaque_param_in_ufc.rs6
-rw-r--r--tests/ui/methods/opaque_param_in_ufc.stderr36
-rw-r--r--tests/ui/namespace/namespace-mix.stderr8
-rw-r--r--tests/ui/never_type/defaulted-never-note.fallback.stderr2
-rw-r--r--tests/ui/never_type/defaulted-never-note.nofallback.stderr18
-rw-r--r--tests/ui/never_type/defaulted-never-note.rs2
-rw-r--r--tests/ui/never_type/dependency-on-fallback-to-unit.rs28
-rw-r--r--tests/ui/never_type/dependency-on-fallback-to-unit.stderr33
-rw-r--r--tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr33
-rw-r--r--tests/ui/never_type/diverging-fallback-control-flow.rs4
-rw-r--r--tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr2
-rw-r--r--tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr18
-rw-r--r--tests/ui/never_type/diverging-fallback-no-leak.rs3
-rw-r--r--tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr18
-rw-r--r--tests/ui/never_type/diverging-fallback-unconstrained-return.rs3
-rw-r--r--tests/ui/never_type/fallback-closure-ret.nofallback.stderr18
-rw-r--r--tests/ui/never_type/fallback-closure-ret.rs8
-rw-r--r--tests/ui/never_type/impl_trait_fallback.rs2
-rw-r--r--tests/ui/never_type/impl_trait_fallback.stderr18
-rw-r--r--tests/ui/numbers-arithmetic/f16-f128-lit.rs4
-rw-r--r--tests/ui/pattern/box-pattern-type-mismatch.rs (renamed from tests/crashes/124004.rs)3
-rw-r--r--tests/ui/pattern/box-pattern-type-mismatch.stderr19
-rw-r--r--tests/ui/pattern/missing_lifetime.rs25
-rw-r--r--tests/ui/pattern/missing_lifetime.stderr25
-rw-r--r--tests/ui/pattern/type_mismatch.rs30
-rw-r--r--tests/ui/pattern/type_mismatch.stderr11
-rw-r--r--tests/ui/proc-macro/auxiliary/api/literal.rs83
-rw-r--r--tests/ui/proc-macro/auxiliary/api/mod.rs4
-rw-r--r--tests/ui/proc-macro/auxiliary/api/parse.rs58
-rw-r--r--tests/ui/resolve/issue-16058.stderr2
-rw-r--r--tests/ui/resolve/issue-21221-1.stderr12
-rw-r--r--tests/ui/resolve/issue-21221-2.stderr2
-rw-r--r--tests/ui/resolve/issue-50599.stderr2
-rw-r--r--tests/ui/resolve/issue-73427.stderr2
-rw-r--r--tests/ui/resolve/privacy-enum-ctor.stderr4
-rw-r--r--tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr4
-rw-r--r--tests/ui/rust-2018/issue-52202-use-suggestions.stderr2
-rw-r--r--tests/ui/rust-2024/unsafe-env-suggestion.fixed2
-rw-r--r--tests/ui/rust-2024/unsafe-env-suggestion.stderr10
-rw-r--r--tests/ui/suggestions/core-std-import-order-issue-83564.no_std.fixed22
-rw-r--r--tests/ui/suggestions/core-std-import-order-issue-83564.no_std.stderr (renamed from tests/ui/suggestions/core-std-import-order-issue-83564.stderr)6
-rw-r--r--tests/ui/suggestions/core-std-import-order-issue-83564.rs12
-rw-r--r--tests/ui/suggestions/core-std-import-order-issue-83564.std.fixed22
-rw-r--r--tests/ui/suggestions/core-std-import-order-issue-83564.std.stderr14
-rw-r--r--tests/ui/suggestions/crate-or-module-typo.stderr4
-rw-r--r--tests/ui/suggestions/suggest-remove-refs-5.stderr4
-rw-r--r--tests/ui/suggestions/suggest-tryinto-edition-change.rs5
-rw-r--r--tests/ui/suggestions/suggest-tryinto-edition-change.stderr19
-rw-r--r--tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs1
-rw-r--r--tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr11
-rw-r--r--tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr2
-rw-r--r--tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr4
-rw-r--r--tests/ui/traits/next-solver/coroutine.fail.stderr47
-rw-r--r--tests/ui/traits/next-solver/coroutine.rs2
-rw-r--r--tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr5
-rw-r--r--tests/ui/traits/next-solver/diagnostics/projection-trait-ref.rs17
-rw-r--r--tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr26
-rw-r--r--tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr5
-rw-r--r--tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr7
-rw-r--r--tests/ui/traits/next-solver/fn-trait.rs4
-rw-r--r--tests/ui/traits/next-solver/fn-trait.stderr67
-rw-r--r--tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs2
-rw-r--r--tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr4
-rw-r--r--tests/ui/traits/next-solver/specialization-transmute.stderr12
-rw-r--r--tests/ui/traits/next-solver/specialization-unconstrained.rs2
-rw-r--r--tests/ui/traits/next-solver/specialization-unconstrained.stderr4
-rw-r--r--tests/ui/traits/suggest-dereferences/root-obligation.stderr2
-rw-r--r--tests/ui/transmutability/enums/uninhabited_optimization.rs26
-rw-r--r--tests/ui/transmutability/references/unsafecell.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution.current.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution.next.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution.rs30
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution2.rs28
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution3.current.stderr21
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution3.next.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution3.rs36
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution4.current.stderr21
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution4.next.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution4.rs39
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution5.rs33
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs31
-rw-r--r--tests/ui/typeck/suggest-similar-impls-for-root-obligation.rs16
-rw-r--r--tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr20
821 files changed, 13396 insertions, 6566 deletions
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index ca704082a3f..fd54a153a16 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,3 +1,4 @@
+<!-- homu-ignore:start -->
 <!--
 If this PR is related to an unstable feature or an otherwise tracked effort,
 please link to the relevant tracking issue here. If you don't know of a related
@@ -7,4 +8,5 @@ This PR will get automatically assigned to a reviewer. In case you would like
 a specific user to review your work, you can assign it to them by using
 
     r​? <reviewer name>
--->
\ No newline at end of file
+-->
+<!-- homu-ignore:end -->
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 521f8ef0f5a..4cf0e5fba53 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -95,8 +95,6 @@ jobs:
           path-type: inherit
           install: >
             make
-            dos2unix
-            diffutils
 
       - name: disable git crlf conversion
         run: git config --global core.autocrlf false
diff --git a/.mailmap b/.mailmap
index 0bd16a797ca..33673244be6 100644
--- a/.mailmap
+++ b/.mailmap
@@ -379,6 +379,7 @@ Markus Westerlind <marwes91@gmail.com> Markus <marwes91@gmail.com>
 Martin Carton <cartonmartin+git@gmail.com>
 Martin Habovštiak <martin.habovstiak@gmail.com>
 Martin Hafskjold Thoresen <martinhath@gmail.com>
+Martin Nordholts <martin.nordholts@codetale.se> <enselic@gmail.com>
 Matej Lach <matej.lach@gmail.com> Matej Ľach <matej.lach@gmail.com>
 Mateusz Mikuła <mati865@gmail.com>
 Mateusz Mikuła <mati865@gmail.com> <mati865@users.noreply.github.com>
diff --git a/Cargo.lock b/Cargo.lock
index e5ea9fee8a6..138e00adc49 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -628,7 +628,7 @@ checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
 
 [[package]]
 name = "clippy"
-version = "0.1.80"
+version = "0.1.81"
 dependencies = [
  "anstream",
  "clippy_config",
@@ -655,7 +655,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_config"
-version = "0.1.80"
+version = "0.1.81"
 dependencies = [
  "rustc-semver",
  "serde",
@@ -678,7 +678,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_lints"
-version = "0.1.80"
+version = "0.1.81"
 dependencies = [
  "arrayvec",
  "cargo_metadata 0.18.1",
@@ -703,7 +703,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_utils"
-version = "0.1.80"
+version = "0.1.81"
 dependencies = [
  "arrayvec",
  "clippy_config",
@@ -1023,7 +1023,7 @@ dependencies = [
 
 [[package]]
 name = "declare_clippy_lint"
-version = "0.1.80"
+version = "0.1.81"
 dependencies = [
  "itertools 0.12.1",
  "quote",
@@ -1694,6 +1694,12 @@ name = "hermit-abi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
+[[package]]
+name = "hermit-abi"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-alloc",
@@ -2636,7 +2642,7 @@ version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.3.9",
  "libc",
 ]
 
@@ -3452,7 +3458,7 @@ dependencies = [
 
 [[package]]
 name = "run_make_support"
-version = "0.1.0"
+version = "0.2.0"
 dependencies = [
  "gimli 0.28.1",
  "object 0.34.0",
@@ -4205,7 +4211,6 @@ dependencies = [
  "rustc_middle",
  "rustc_span",
  "rustc_target",
- "rustc_type_ir",
  "smallvec",
  "tracing",
 ]
@@ -5346,7 +5351,7 @@ dependencies = [
  "dlmalloc",
  "fortanix-sgx-abi",
  "hashbrown",
- "hermit-abi",
+ "hermit-abi 0.4.0",
  "libc",
  "miniz_oxide",
  "object 0.36.0",
@@ -6380,9 +6385,9 @@ dependencies = [
 
 [[package]]
 name = "windows-bindgen"
-version = "0.56.0"
+version = "0.57.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a28e3ea6330cf17fdcdce8bf08d0549ce93769dca9bedc6c39c36c8c0e17db46"
+checksum = "1ccb96113d6277ba543c0f77e1c5494af8094bf9daf9b85acdc3f1b620e7c7b4"
 dependencies = [
  "proc-macro2",
  "rayon",
@@ -6403,9 +6408,9 @@ dependencies = [
 
 [[package]]
 name = "windows-metadata"
-version = "0.56.0"
+version = "0.57.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3993f7827fff10c454e3a24847075598c7c08108304b8b07943c2c73d78f3b34"
+checksum = "8308d076825b9d9e5abc64f8113e96d02b2aeeba869b20fdd65c7e70cda13dfc"
 
 [[package]]
 name = "windows-sys"
diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs
index 97408fa20d7..b54e05b2b34 100644
--- a/compiler/rustc_borrowck/src/constraints/mod.rs
+++ b/compiler/rustc_borrowck/src/constraints/mod.rs
@@ -1,4 +1,4 @@
-use rustc_data_structures::graph::scc::Sccs;
+use crate::type_check::Locations;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::{RegionVid, TyCtxt, VarianceDiagInfo};
@@ -6,8 +6,6 @@ use rustc_span::Span;
 use std::fmt;
 use std::ops::Index;
 
-use crate::type_check::Locations;
-
 pub(crate) mod graph;
 
 /// A set of NLL region constraints. These include "outlives"
@@ -45,18 +43,6 @@ impl<'tcx> OutlivesConstraintSet<'tcx> {
         graph::ConstraintGraph::new(graph::Reverse, self, num_region_vars)
     }
 
-    /// Computes cycles (SCCs) in the graph of regions. In particular,
-    /// find all regions R1, R2 such that R1: R2 and R2: R1 and group
-    /// them into an SCC, and find the relationships between SCCs.
-    pub(crate) fn compute_sccs(
-        &self,
-        constraint_graph: &graph::NormalConstraintGraph,
-        static_region: RegionVid,
-    ) -> Sccs<RegionVid, ConstraintSccIndex> {
-        let region_graph = &constraint_graph.region_graph(self, static_region);
-        Sccs::new(region_graph)
-    }
-
     pub(crate) fn outlives(
         &self,
     ) -> &IndexSlice<OutlivesConstraintIndex, OutlivesConstraint<'tcx>> {
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index f32ff57fe88..6bc340e44f5 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -100,12 +100,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             move_site_vec.iter().map(|move_site| move_site.moi).collect();
 
         if move_out_indices.is_empty() {
-            let root_place = PlaceRef { projection: &[], ..used_place };
+            let root_local = used_place.local;
 
-            if !self.uninitialized_error_reported.insert(root_place) {
+            if !self.uninitialized_error_reported.insert(root_local) {
                 debug!(
                     "report_use_of_moved_or_uninitialized place: error about {:?} suppressed",
-                    root_place
+                    root_local
                 );
                 return;
             }
@@ -284,7 +284,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     && let CallKind::FnCall { fn_trait_id, self_ty } = kind
                     && let ty::Param(_) = self_ty.kind()
                     && ty == self_ty
-                    && Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait()
+                    && self.infcx.tcx.is_lang_item(fn_trait_id, LangItem::FnOnce)
                 {
                     // this is a type parameter `T: FnOnce()`, don't suggest `T: FnOnce() + Clone`.
                     true
@@ -708,9 +708,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             if let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
                 && pred.self_ty() == ty
             {
-                if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
+                if tcx.is_lang_item(pred.def_id(), LangItem::Fn) {
                     return Some(hir::Mutability::Not);
-                } else if Some(pred.def_id()) == tcx.lang_items().fn_mut_trait() {
+                } else if tcx.is_lang_item(pred.def_id(), LangItem::FnMut) {
                     return Some(hir::Mutability::Mut);
                 }
             }
@@ -1832,7 +1832,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 if let hir::ExprKind::MethodCall(..) = ex.kind
                     && let Some(method_def_id) =
                         self.typeck_results.type_dependent_def_id(ex.hir_id)
-                    && self.tcx.lang_items().clone_trait() == Some(self.tcx.parent(method_def_id))
+                    && self.tcx.is_lang_item(self.tcx.parent(method_def_id), LangItem::Clone)
                 {
                     self.clones.push(ex);
                 }
@@ -2888,7 +2888,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             ..
         } = explanation
         {
-            if let Some(diag) = self.try_report_cannot_return_reference_to_local(
+            if let Err(diag) = self.try_report_cannot_return_reference_to_local(
                 borrow,
                 borrow_span,
                 span,
@@ -3075,7 +3075,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
             explanation
         {
-            if let Some(diag) = self.try_report_cannot_return_reference_to_local(
+            if let Err(diag) = self.try_report_cannot_return_reference_to_local(
                 borrow,
                 proper_span,
                 span,
@@ -3159,8 +3159,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         let is_format_arguments_item = if let Some(expr_ty) = expr_ty
                             && let ty::Adt(adt, _) = expr_ty.kind()
                         {
-                            self.infcx.tcx.lang_items().get(LangItem::FormatArguments)
-                                == Some(adt.did())
+                            self.infcx.tcx.is_lang_item(adt.did(), LangItem::FormatArguments)
                         } else {
                             false
                         };
@@ -3237,11 +3236,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         return_span: Span,
         category: ConstraintCategory<'tcx>,
         opt_place_desc: Option<&String>,
-    ) -> Option<Diag<'tcx>> {
+    ) -> Result<(), Diag<'tcx>> {
         let return_kind = match category {
             ConstraintCategory::Return(_) => "return",
             ConstraintCategory::Yield => "yield",
-            _ => return None,
+            _ => return Ok(()),
         };
 
         // FIXME use a better heuristic than Spans
@@ -3317,7 +3316,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
         }
 
-        Some(err)
+        Err(err)
     }
 
     #[instrument(level = "debug", skip(self))]
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 1eb67ea367c..abb0b5afbd8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -6,9 +6,9 @@ use crate::session_diagnostics::{
 };
 use rustc_errors::{Applicability, Diag};
 use rustc_errors::{DiagCtxt, MultiSpan};
-use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::CoroutineKind;
+use rustc_hir::{self as hir, LangItem};
 use rustc_index::IndexSlice;
 use rustc_infer::infer::BoundRegionConversionTime;
 use rustc_infer::traits::SelectionError;
@@ -116,7 +116,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         {
             if let ty::FnDef(id, _) = *const_.ty().kind() {
                 debug!("add_moved_or_invoked_closure_note: id={:?}", id);
-                if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() {
+                if self.infcx.tcx.is_lang_item(self.infcx.tcx.parent(id), LangItem::FnOnce) {
                     let closure = match args.first() {
                         Some(Spanned {
                             node: Operand::Copy(place) | Operand::Move(place), ..
@@ -767,13 +767,12 @@ impl<'tcx> BorrowedContentSource<'tcx> {
             ty::FnDef(def_id, args) => {
                 let trait_id = tcx.trait_of_item(def_id)?;
 
-                let lang_items = tcx.lang_items();
-                if Some(trait_id) == lang_items.deref_trait()
-                    || Some(trait_id) == lang_items.deref_mut_trait()
+                if tcx.is_lang_item(trait_id, LangItem::Deref)
+                    || tcx.is_lang_item(trait_id, LangItem::DerefMut)
                 {
                     Some(BorrowedContentSource::OverloadedDeref(args.type_at(0)))
-                } else if Some(trait_id) == lang_items.index_trait()
-                    || Some(trait_id) == lang_items.index_mut_trait()
+                } else if tcx.is_lang_item(trait_id, LangItem::Index)
+                    || tcx.is_lang_item(trait_id, LangItem::IndexMut)
                 {
                     Some(BorrowedContentSource::OverloadedIndex(args.type_at(0)))
                 } else {
@@ -1041,7 +1040,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 .unwrap_or_else(|| "value".to_owned());
             match kind {
                 CallKind::FnCall { fn_trait_id, self_ty }
-                    if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
+                    if self.infcx.tcx.is_lang_item(fn_trait_id, LangItem::FnOnce) =>
                 {
                     err.subdiagnostic(
                         self.dcx(),
@@ -1268,7 +1267,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         let ty = moved_place.ty(self.body, tcx).ty;
 
                         if let ty::Adt(def, args) = ty.peel_refs().kind()
-                            && Some(def.did()) == tcx.lang_items().pin_type()
+                            && tcx.is_lang_item(def.did(), LangItem::Pin)
                             && let ty::Ref(_, _, hir::Mutability::Mut) = args.type_at(0).kind()
                             && let self_ty = self.infcx.instantiate_binder_with_fresh_vars(
                                 fn_call_span,
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 5c9826ecca7..b3b53e9cb79 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -566,7 +566,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
     fn_self_span_reported: FxIndexSet<Span>,
     /// This field keeps track of errors reported in the checking of uninitialized variables,
     /// so that we don't report seemingly duplicate errors.
-    uninitialized_error_reported: FxIndexSet<PlaceRef<'tcx>>,
+    uninitialized_error_reported: FxIndexSet<Local>,
     /// This field keeps track of all the local variables that are declared mut and are mutated.
     /// Used for the warning issued by an unused mutable local variable.
     used_mut: FxIndexSet<Local>,
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 0e3140ca98b..40b58500598 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -4,10 +4,10 @@ use std::rc::Rc;
 use rustc_data_structures::binary_search_util;
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
-use rustc_data_structures::graph::scc::Sccs;
+use rustc_data_structures::graph::scc::{self, Sccs};
 use rustc_errors::Diag;
 use rustc_hir::def_id::CRATE_DEF_ID;
-use rustc_index::{IndexSlice, IndexVec};
+use rustc_index::IndexVec;
 use rustc_infer::infer::outlives::test_type_match;
 use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
@@ -19,7 +19,7 @@ use rustc_middle::mir::{
 };
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex};
 use rustc_mir_dataflow::points::DenseLocationMap;
 use rustc_span::Span;
 
@@ -46,6 +46,97 @@ mod reverse_sccs;
 
 pub mod values;
 
+pub type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex, RegionTracker>;
+
+/// An annotation for region graph SCCs that tracks
+/// the values of its elements.
+#[derive(Copy, Debug, Clone)]
+pub struct RegionTracker {
+    /// The largest universe of a placeholder reached from this SCC.
+    /// This includes placeholders within this SCC.
+    max_placeholder_universe_reached: UniverseIndex,
+
+    /// The smallest universe index reachable form the nodes of this SCC.
+    min_reachable_universe: UniverseIndex,
+
+    /// The representative Region Variable Id for this SCC. We prefer
+    /// placeholders over existentially quantified variables, otherwise
+    ///  it's the one with the smallest Region Variable ID.
+    representative: RegionVid,
+
+    /// Is the current representative a placeholder?
+    representative_is_placeholder: bool,
+
+    /// Is the current representative existentially quantified?
+    representative_is_existential: bool,
+}
+
+impl scc::Annotation for RegionTracker {
+    fn merge_scc(mut self, mut other: Self) -> Self {
+        // Prefer any placeholder over any existential
+        if other.representative_is_placeholder && self.representative_is_existential {
+            other.merge_min_max_seen(&self);
+            return other;
+        }
+
+        if self.representative_is_placeholder && other.representative_is_existential
+            || (self.representative <= other.representative)
+        {
+            self.merge_min_max_seen(&other);
+            return self;
+        }
+        other.merge_min_max_seen(&self);
+        other
+    }
+
+    fn merge_reached(mut self, other: Self) -> Self {
+        // No update to in-component values, only add seen values.
+        self.merge_min_max_seen(&other);
+        self
+    }
+}
+
+impl RegionTracker {
+    fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
+        let (representative_is_placeholder, representative_is_existential) = match definition.origin
+        {
+            rustc_infer::infer::NllRegionVariableOrigin::FreeRegion => (false, false),
+            rustc_infer::infer::NllRegionVariableOrigin::Placeholder(_) => (true, false),
+            rustc_infer::infer::NllRegionVariableOrigin::Existential { .. } => (false, true),
+        };
+
+        let placeholder_universe =
+            if representative_is_placeholder { definition.universe } else { UniverseIndex::ROOT };
+
+        Self {
+            max_placeholder_universe_reached: placeholder_universe,
+            min_reachable_universe: definition.universe,
+            representative: rvid,
+            representative_is_placeholder,
+            representative_is_existential,
+        }
+    }
+    fn universe(self) -> UniverseIndex {
+        self.min_reachable_universe
+    }
+
+    fn merge_min_max_seen(&mut self, other: &Self) {
+        self.max_placeholder_universe_reached = std::cmp::max(
+            self.max_placeholder_universe_reached,
+            other.max_placeholder_universe_reached,
+        );
+
+        self.min_reachable_universe =
+            std::cmp::min(self.min_reachable_universe, other.min_reachable_universe);
+    }
+
+    /// Returns `true` if during the annotated SCC reaches a placeholder
+    /// with a universe larger than the smallest reachable one, `false` otherwise.
+    pub fn has_incompatible_universes(&self) -> bool {
+        self.universe().cannot_name(self.max_placeholder_universe_reached)
+    }
+}
+
 pub struct RegionInferenceContext<'tcx> {
     pub var_infos: VarInfos,
 
@@ -72,7 +163,7 @@ pub struct RegionInferenceContext<'tcx> {
     /// The SCC computed from `constraints` and the constraint
     /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
     /// compute the values of each region.
-    constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
+    constraint_sccs: Rc<ConstraintSccs>,
 
     /// Reverse of the SCC constraint graph --  i.e., an edge `A -> B` exists if
     /// `B: A`. This is used to compute the universal regions that are required
@@ -91,22 +182,6 @@ pub struct RegionInferenceContext<'tcx> {
     /// Map universe indexes to information on why we created it.
     universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
 
-    /// Contains the minimum universe of any variable within the same
-    /// SCC. We will ensure that no SCC contains values that are not
-    /// visible from this index.
-    scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
-
-    /// Contains the "representative" region of each SCC.
-    /// It is defined as the one with the minimal RegionVid, favoring
-    /// free regions, then placeholders, then existential regions.
-    ///
-    /// It is a hacky way to manage checking regions for equality,
-    /// since we can 'canonicalize' each region to the representative
-    /// of its SCC and be sure that -- if they have the same repr --
-    /// they *must* be equal (though not having the same repr does not
-    /// mean they are unequal).
-    scc_representatives: IndexVec<ConstraintSccIndex, ty::RegionVid>,
-
     /// The final inferred values of the region variables; we compute
     /// one value per SCC. To get the value for any given *region*,
     /// you first find which scc it is a part of.
@@ -151,7 +226,7 @@ pub(crate) struct AppliedMemberConstraint {
 }
 
 #[derive(Debug)]
-pub(crate) struct RegionDefinition<'tcx> {
+pub struct RegionDefinition<'tcx> {
     /// What kind of variable is this -- a free region? existential
     /// variable? etc. (See the `NllRegionVariableOrigin` for more
     /// info.)
@@ -250,7 +325,7 @@ pub enum ExtraConstraintInfo {
 }
 
 #[instrument(skip(infcx, sccs), level = "debug")]
-fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>) {
+fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) {
     use crate::renumber::RegionCtxt;
 
     let var_to_origin = infcx.reg_var_to_origin.borrow();
@@ -264,7 +339,7 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: Rc<Sccs<RegionVid, Con
     }
     debug!("{}", reg_vars_to_origins_str);
 
-    let num_components = sccs.scc_data().ranges().len();
+    let num_components = sccs.num_sccs();
     let mut components = vec![FxIndexSet::default(); num_components];
 
     for (reg_var_idx, scc_idx) in sccs.scc_indices().iter().enumerate() {
@@ -301,10 +376,11 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: Rc<Sccs<RegionVid, Con
 
     let mut scc_node_to_edges = FxIndexMap::default();
     for (scc_idx, repr) in components_representatives.iter() {
-        let edges_range = sccs.scc_data().ranges()[*scc_idx].clone();
-        let edges = &sccs.scc_data().all_successors()[edges_range];
-        let edge_representatives =
-            edges.iter().map(|scc_idx| components_representatives[scc_idx]).collect::<Vec<_>>();
+        let edge_representatives = sccs
+            .successors(*scc_idx)
+            .iter()
+            .map(|scc_idx| components_representatives[scc_idx])
+            .collect::<Vec<_>>();
         scc_node_to_edges.insert((scc_idx, repr), edge_representatives);
     }
 
@@ -320,7 +396,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// The `outlives_constraints` and `type_tests` are an initial set
     /// of constraints produced by the MIR type check.
     pub(crate) fn new(
-        _infcx: &BorrowckInferCtxt<'tcx>,
+        infcx: &BorrowckInferCtxt<'tcx>,
         var_infos: VarInfos,
         universal_regions: Rc<UniversalRegions<'tcx>>,
         placeholder_indices: Rc<PlaceholderIndices>,
@@ -343,13 +419,20 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             .map(|info| RegionDefinition::new(info.universe, info.origin))
             .collect();
 
+        let fr_static = universal_regions.fr_static;
         let constraints = Frozen::freeze(outlives_constraints);
         let constraint_graph = Frozen::freeze(constraints.graph(definitions.len()));
-        let fr_static = universal_regions.fr_static;
-        let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph, fr_static));
+        let constraint_sccs = {
+            let constraint_graph = constraints.graph(definitions.len());
+            let region_graph = &constraint_graph.region_graph(&constraints, fr_static);
+            let sccs = ConstraintSccs::new_with_annotation(&region_graph, |r| {
+                RegionTracker::new(r, &definitions[r])
+            });
+            Rc::new(sccs)
+        };
 
         if cfg!(debug_assertions) {
-            sccs_info(_infcx, constraint_sccs.clone());
+            sccs_info(infcx, &constraint_sccs);
         }
 
         let mut scc_values =
@@ -360,10 +443,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             scc_values.merge_liveness(scc, region, &liveness_constraints);
         }
 
-        let scc_universes = Self::compute_scc_universes(&constraint_sccs, &definitions);
-
-        let scc_representatives = Self::compute_scc_representatives(&constraint_sccs, &definitions);
-
         let member_constraints =
             Rc::new(member_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
 
@@ -378,8 +457,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             member_constraints,
             member_constraints_applied: Vec::new(),
             universe_causes,
-            scc_universes,
-            scc_representatives,
             scc_values,
             type_tests,
             universal_regions,
@@ -391,123 +468,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         result
     }
 
-    /// Each SCC is the combination of many region variables which
-    /// have been equated. Therefore, we can associate a universe with
-    /// each SCC which is minimum of all the universes of its
-    /// constituent regions -- this is because whatever value the SCC
-    /// takes on must be a value that each of the regions within the
-    /// SCC could have as well. This implies that the SCC must have
-    /// the minimum, or narrowest, universe.
-    fn compute_scc_universes(
-        constraint_sccs: &Sccs<RegionVid, ConstraintSccIndex>,
-        definitions: &IndexSlice<RegionVid, RegionDefinition<'tcx>>,
-    ) -> IndexVec<ConstraintSccIndex, ty::UniverseIndex> {
-        let num_sccs = constraint_sccs.num_sccs();
-        let mut scc_universes = IndexVec::from_elem_n(ty::UniverseIndex::MAX, num_sccs);
-
-        debug!("compute_scc_universes()");
-
-        // For each region R in universe U, ensure that the universe for the SCC
-        // that contains R is "no bigger" than U. This effectively sets the universe
-        // for each SCC to be the minimum of the regions within.
-        for (region_vid, region_definition) in definitions.iter_enumerated() {
-            let scc = constraint_sccs.scc(region_vid);
-            let scc_universe = &mut scc_universes[scc];
-            let scc_min = std::cmp::min(region_definition.universe, *scc_universe);
-            if scc_min != *scc_universe {
-                *scc_universe = scc_min;
-                debug!(
-                    "compute_scc_universes: lowered universe of {scc:?} to {scc_min:?} \
-                    because it contains {region_vid:?} in {region_universe:?}",
-                    scc = scc,
-                    scc_min = scc_min,
-                    region_vid = region_vid,
-                    region_universe = region_definition.universe,
-                );
-            }
-        }
-
-        // Walk each SCC `A` and `B` such that `A: B`
-        // and ensure that universe(A) can see universe(B).
-        //
-        // This serves to enforce the 'empty/placeholder' hierarchy
-        // (described in more detail on `RegionKind`):
-        //
-        // ```
-        // static -----+
-        //   |         |
-        // empty(U0) placeholder(U1)
-        //   |      /
-        // empty(U1)
-        // ```
-        //
-        // In particular, imagine we have variables R0 in U0 and R1
-        // created in U1, and constraints like this;
-        //
-        // ```
-        // R1: !1 // R1 outlives the placeholder in U1
-        // R1: R0 // R1 outlives R0
-        // ```
-        //
-        // Here, we wish for R1 to be `'static`, because it
-        // cannot outlive `placeholder(U1)` and `empty(U0)` any other way.
-        //
-        // Thanks to this loop, what happens is that the `R1: R0`
-        // constraint lowers the universe of `R1` to `U0`, which in turn
-        // means that the `R1: !1` constraint will (later) cause
-        // `R1` to become `'static`.
-        for scc_a in constraint_sccs.all_sccs() {
-            for &scc_b in constraint_sccs.successors(scc_a) {
-                let scc_universe_a = scc_universes[scc_a];
-                let scc_universe_b = scc_universes[scc_b];
-                let scc_universe_min = std::cmp::min(scc_universe_a, scc_universe_b);
-                if scc_universe_a != scc_universe_min {
-                    scc_universes[scc_a] = scc_universe_min;
-
-                    debug!(
-                        "compute_scc_universes: lowered universe of {scc_a:?} to {scc_universe_min:?} \
-                        because {scc_a:?}: {scc_b:?} and {scc_b:?} is in universe {scc_universe_b:?}",
-                        scc_a = scc_a,
-                        scc_b = scc_b,
-                        scc_universe_min = scc_universe_min,
-                        scc_universe_b = scc_universe_b
-                    );
-                }
-            }
-        }
-
-        debug!("compute_scc_universes: scc_universe = {:#?}", scc_universes);
-
-        scc_universes
-    }
-
-    /// For each SCC, we compute a unique `RegionVid`. See the
-    /// `scc_representatives` field of `RegionInferenceContext` for
-    /// more details.
-    fn compute_scc_representatives(
-        constraints_scc: &Sccs<RegionVid, ConstraintSccIndex>,
-        definitions: &IndexSlice<RegionVid, RegionDefinition<'tcx>>,
-    ) -> IndexVec<ConstraintSccIndex, ty::RegionVid> {
-        let num_sccs = constraints_scc.num_sccs();
-        let mut scc_representatives = IndexVec::from_elem_n(RegionVid::MAX, num_sccs);
-
-        // Iterate over all RegionVids *in-order* and pick the least RegionVid as the
-        // representative of its SCC. This naturally prefers free regions over others.
-        for (vid, def) in definitions.iter_enumerated() {
-            let repr = &mut scc_representatives[constraints_scc.scc(vid)];
-            if *repr == ty::RegionVid::MAX {
-                *repr = vid;
-            } else if matches!(def.origin, NllRegionVariableOrigin::Placeholder(_))
-                && matches!(definitions[*repr].origin, NllRegionVariableOrigin::Existential { .. })
-            {
-                // Pick placeholders over existentials even if they have a greater RegionVid.
-                *repr = vid;
-            }
-        }
-
-        scc_representatives
-    }
-
     /// Initializes the region variables for each universally
     /// quantified region (lifetime parameter). The first N variables
     /// always correspond to the regions appearing in the function
@@ -528,12 +488,45 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// and (b) any universally quantified regions that it outlives,
     /// which in this case is just itself. R1 (`'b`) in contrast also
     /// outlives `'a` and hence contains R0 and R1.
+    ///
+    /// This bit of logic also handles invalid universe relations
+    /// for higher-kinded types.
+    ///
+    /// We Walk each SCC `A` and `B` such that `A: B`
+    /// and ensure that universe(A) can see universe(B).
+    ///
+    /// This serves to enforce the 'empty/placeholder' hierarchy
+    /// (described in more detail on `RegionKind`):
+    ///
+    /// ```ignore (illustrative)
+    /// static -----+
+    ///   |         |
+    /// empty(U0) placeholder(U1)
+    ///   |      /
+    /// empty(U1)
+    /// ```
+    ///
+    /// In particular, imagine we have variables R0 in U0 and R1
+    /// created in U1, and constraints like this;
+    ///
+    /// ```ignore (illustrative)
+    /// R1: !1 // R1 outlives the placeholder in U1
+    /// R1: R0 // R1 outlives R0
+    /// ```
+    ///
+    /// Here, we wish for R1 to be `'static`, because it
+    /// cannot outlive `placeholder(U1)` and `empty(U0)` any other way.
+    ///
+    /// Thanks to this loop, what happens is that the `R1: R0`
+    /// constraint has lowered the universe of `R1` to `U0`, which in turn
+    /// means that the `R1: !1` constraint here will cause
+    /// `R1` to become `'static`.
     fn init_free_and_bound_regions(&mut self) {
         // Update the names (if any)
         // This iterator has unstable order but we collect it all into an IndexVec
         for (external_name, variable) in self.universal_regions.named_universal_regions() {
             debug!(
-                "init_universal_regions: region {:?} has external name {:?}",
+                "init_free_and_bound_regions: region {:?} has external name {:?}",
                 variable, external_name
             );
             self.definitions[variable].external_name = Some(external_name);
@@ -559,7 +552,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     // its universe `ui` and its extensions. So we
                     // can't just add it into `scc` unless the
                     // universe of the scc can name this region.
-                    let scc_universe = self.scc_universes[scc];
+                    let scc_universe = self.scc_universe(scc);
                     if scc_universe.can_name(placeholder.universe) {
                         self.scc_values.add_element(scc, placeholder);
                     } else {
@@ -640,8 +633,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
     /// Returns access to the value of `r` for debugging purposes.
     pub(crate) fn region_universe(&self, r: RegionVid) -> ty::UniverseIndex {
-        let scc = self.constraint_sccs.scc(r);
-        self.scc_universes[scc]
+        self.scc_universe(self.constraint_sccs.scc(r))
     }
 
     /// Once region solving has completed, this function will return the member constraints that
@@ -737,8 +729,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // SCC. For each SCC, we visit its successors and compute
         // their values, then we union all those values to get our
         // own.
-        let constraint_sccs = self.constraint_sccs.clone();
-        for scc in constraint_sccs.all_sccs() {
+        for scc in self.constraint_sccs.all_sccs() {
             self.compute_value_for_scc(scc);
         }
 
@@ -817,20 +808,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // if one exists.
         for c_r in &mut choice_regions {
             let scc = self.constraint_sccs.scc(*c_r);
-            *c_r = self.scc_representatives[scc];
+            *c_r = self.scc_representative(scc);
         }
 
         // If the member region lives in a higher universe, we currently choose
         // the most conservative option by leaving it unchanged.
-        if self.scc_universes[scc] != ty::UniverseIndex::ROOT {
+
+        if !self.constraint_sccs().annotation(scc).universe().is_root() {
             return;
         }
-        debug_assert!(
-            self.scc_values.placeholders_contained_in(scc).next().is_none(),
-            "scc {:?} in a member constraint has placeholder value: {:?}",
-            scc,
-            self.scc_values.region_value_str(scc),
-        );
 
         // The existing value for `scc` is a lower-bound. This will
         // consist of some set `{P} + {LB}` of points `{P}` and
@@ -900,12 +886,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// in `scc_a`. Used during constraint propagation, and only once
     /// the value of `scc_b` has been computed.
     fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccIndex) -> bool {
-        let universe_a = self.scc_universes[scc_a];
+        let universe_a = self.constraint_sccs().annotation(scc_a).universe();
+        let universe_b = self.constraint_sccs().annotation(scc_b).universe();
 
         // Quick check: if scc_b's declared universe is a subset of
         // scc_a's declared universe (typically, both are ROOT), then
         // it cannot contain any problematic universe elements.
-        if universe_a.can_name(self.scc_universes[scc_b]) {
+        if universe_a.can_name(universe_b) {
             return true;
         }
 
@@ -1033,7 +1020,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         debug!(
             "lower_bound = {:?} r_scc={:?} universe={:?}",
-            lower_bound, r_scc, self.scc_universes[r_scc]
+            lower_bound,
+            r_scc,
+            self.constraint_sccs.annotation(r_scc).universe()
         );
 
         // If the type test requires that `T: 'a` where `'a` is a
@@ -1321,7 +1310,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         tcx.fold_regions(value, |r, _db| {
             let vid = self.to_region_vid(r);
             let scc = self.constraint_sccs.scc(vid);
-            let repr = self.scc_representatives[scc];
+            let repr = self.scc_representative(scc);
             ty::Region::new_var(tcx, repr)
         })
     }
@@ -1547,6 +1536,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
     }
 
+    /// The minimum universe of any variable reachable from this
+    /// SCC, inside or outside of it.
+    fn scc_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex {
+        self.constraint_sccs().annotation(scc).universe()
+    }
     /// Checks the final value for the free region `fr` to see if it
     /// grew too large. In particular, examine what `end(X)` points
     /// wound up in `fr`'s final value; for each `end(X)` where `X !=
@@ -1566,8 +1560,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         // Because this free region must be in the ROOT universe, we
         // know it cannot contain any bound universes.
-        assert!(self.scc_universes[longer_fr_scc].is_root());
-        debug_assert!(self.scc_values.placeholders_contained_in(longer_fr_scc).next().is_none());
+        assert!(self.scc_universe(longer_fr_scc).is_root());
 
         // Only check all of the relations for the main representative of each
         // SCC, otherwise just check that we outlive said representative. This
@@ -1575,7 +1568,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // closures.
         // Note that the representative will be a universal region if there is
         // one in this SCC, so we will always check the representative here.
-        let representative = self.scc_representatives[longer_fr_scc];
+        let representative = self.scc_representative(longer_fr_scc);
         if representative != longer_fr {
             if let RegionRelationCheckResult::Error = self.check_universal_region_relation(
                 longer_fr,
@@ -1796,16 +1789,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// `true` if `r1` cannot name that placeholder in its
     /// value; otherwise, returns `false`.
     pub(crate) fn cannot_name_placeholder(&self, r1: RegionVid, r2: RegionVid) -> bool {
-        debug!("cannot_name_value_of(r1={:?}, r2={:?})", r1, r2);
-
         match self.definitions[r2].origin {
             NllRegionVariableOrigin::Placeholder(placeholder) => {
-                let universe1 = self.definitions[r1].universe;
+                let r1_universe = self.definitions[r1].universe;
                 debug!(
-                    "cannot_name_value_of: universe1={:?} placeholder={:?}",
-                    universe1, placeholder
+                    "cannot_name_value_of: universe1={r1_universe:?} placeholder={:?}",
+                    placeholder
                 );
-                universe1.cannot_name(placeholder.universe)
+                r1_universe.cannot_name(placeholder.universe)
             }
 
             NllRegionVariableOrigin::FreeRegion | NllRegionVariableOrigin::Existential { .. } => {
@@ -1835,6 +1826,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///
     /// Returns: a series of constraints as well as the region `R`
     /// that passed the target test.
+    #[instrument(skip(self, target_test), ret)]
     pub(crate) fn find_constraint_paths_between_regions(
         &self,
         from_region: RegionVid,
@@ -1932,7 +1924,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     #[instrument(skip(self), level = "trace", ret)]
     pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid {
         trace!(scc = ?self.constraint_sccs.scc(fr1));
-        trace!(universe = ?self.scc_universes[self.constraint_sccs.scc(fr1)]);
+        trace!(universe = ?self.region_universe(fr1));
         self.find_constraint_paths_between_regions(fr1, |r| {
             // First look for some `r` such that `fr1: r` and `r` is live at `location`
             trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r));
@@ -2252,8 +2244,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// This can be used to quickly under-approximate the regions which are equal to each other
     /// and their relative orderings.
     // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`.
-    pub fn constraint_sccs(&self) -> &Sccs<RegionVid, ConstraintSccIndex> {
-        self.constraint_sccs.as_ref()
+    pub fn constraint_sccs(&self) -> &ConstraintSccs {
+        &self.constraint_sccs
     }
 
     /// Access to the region graph, built from the outlives constraints.
@@ -2282,6 +2274,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let point = self.liveness_constraints.point_from_location(location);
         self.liveness_constraints.is_loan_live_at(loan_idx, point)
     }
+
+    /// Returns the representative `RegionVid` for a given SCC.
+    /// See `RegionTracker` for how a region variable ID is chosen.
+    ///
+    /// It is a hacky way to manage checking regions for equality,
+    /// since we can 'canonicalize' each region to the representative
+    /// of its SCC and be sure that -- if they have the same repr --
+    /// they *must* be equal (though not having the same repr does not
+    /// mean they are unequal).
+    fn scc_representative(&self, scc: ConstraintSccIndex) -> RegionVid {
+        self.constraint_sccs.annotation(scc).representative
+    }
 }
 
 impl<'tcx> RegionDefinition<'tcx> {
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 06adb686ed4..51c3648d730 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -85,7 +85,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     // Use the SCC representative instead of directly using `region`.
                     // See [rustc-dev-guide chapter] § "Strict lifetime equality".
                     let scc = self.constraint_sccs.scc(region.as_var());
-                    let vid = self.scc_representatives[scc];
+                    let vid = self.scc_representative(scc);
                     let named = match self.definitions[vid].origin {
                         // Iterate over all universal regions in a consistent order and find the
                         // *first* equal region. This makes sure that equal lifetimes will have
@@ -213,7 +213,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 let scc = self.constraint_sccs.scc(vid);
 
                 // Special handling of higher-ranked regions.
-                if !self.scc_universes[scc].is_root() {
+                if !self.scc_universe(scc).is_root() {
                     match self.scc_values.placeholders_contained_in(scc).enumerate().last() {
                         // If the region contains a single placeholder then they're equal.
                         Some((0, placeholder)) => {
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index d382f264c37..2858a407e09 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -113,7 +113,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) {
+    fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) {
         let const_ = constant.const_;
         constant.const_ = self.renumber_regions(const_, || RegionCtxt::Location(location));
         debug!("constant: {:#?}", constant);
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index fcfb297d50a..c7c1b2af6a7 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -301,10 +301,10 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
         self.sanitize_place(place, location, context);
     }
 
-    fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
-        debug!(?constant, ?location, "visit_constant");
+    fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
+        debug!(?constant, ?location, "visit_const_operand");
 
-        self.super_constant(constant, location);
+        self.super_const_operand(constant, location);
         let ty = self.sanitize_type(constant, constant.const_.ty());
 
         self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
@@ -328,7 +328,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
         if let Some(annotation_index) = constant.user_ty {
             if let Err(terr) = self.cx.relate_type_and_user_type(
                 constant.const_.ty(),
-                ty::Variance::Invariant,
+                ty::Invariant,
                 &UserTypeProjection { base: annotation_index, projs: vec![] },
                 locations,
                 ConstraintCategory::Boring,
@@ -451,7 +451,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
 
                 if let Err(terr) = self.cx.relate_type_and_user_type(
                     ty,
-                    ty::Variance::Invariant,
+                    ty::Invariant,
                     user_ty,
                     Locations::All(*span),
                     ConstraintCategory::TypeAnnotation,
@@ -1095,7 +1095,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     ) -> Result<(), NoSolution> {
         // Use this order of parameters because the sup type is usually the
         // "expected" type in diagnostics.
-        self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
+        self.relate_types(sup, ty::Contravariant, sub, locations, category)
     }
 
     #[instrument(skip(self, category), level = "debug")]
@@ -1106,7 +1106,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         locations: Locations,
         category: ConstraintCategory<'tcx>,
     ) -> Result<(), NoSolution> {
-        self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
+        self.relate_types(expected, ty::Invariant, found, locations, category)
     }
 
     #[instrument(skip(self), level = "debug")]
@@ -1146,7 +1146,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         trace!(?curr_projected_ty);
 
         let ty = curr_projected_ty.ty;
-        self.relate_types(ty, v.xform(ty::Variance::Contravariant), a, locations, category)?;
+        self.relate_types(ty, v.xform(ty::Contravariant), a, locations, category)?;
 
         Ok(())
     }
@@ -1248,7 +1248,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 if let Some(annotation_index) = self.rvalue_user_ty(rv) {
                     if let Err(terr) = self.relate_type_and_user_type(
                         rv_ty,
-                        ty::Variance::Invariant,
+                        ty::Invariant,
                         &UserTypeProjection { base: annotation_index, projs: vec![] },
                         location.to_locations(),
                         ConstraintCategory::Boring,
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index c531c9b209b..b9a82046e59 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -50,14 +50,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         locations: Locations,
         category: ConstraintCategory<'tcx>,
     ) -> Result<(), NoSolution> {
-        NllTypeRelating::new(
-            self,
-            locations,
-            category,
-            UniverseInfo::other(),
-            ty::Variance::Invariant,
-        )
-        .relate(a, b)?;
+        NllTypeRelating::new(self, locations, category, UniverseInfo::other(), ty::Invariant)
+            .relate(a, b)?;
         Ok(())
     }
 }
@@ -106,15 +100,15 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
 
     fn ambient_covariance(&self) -> bool {
         match self.ambient_variance {
-            ty::Variance::Covariant | ty::Variance::Invariant => true,
-            ty::Variance::Contravariant | ty::Variance::Bivariant => false,
+            ty::Covariant | ty::Invariant => true,
+            ty::Contravariant | ty::Bivariant => false,
         }
     }
 
     fn ambient_contravariance(&self) -> bool {
         match self.ambient_variance {
-            ty::Variance::Contravariant | ty::Variance::Invariant => true,
-            ty::Variance::Covariant | ty::Variance::Bivariant => false,
+            ty::Contravariant | ty::Invariant => true,
+            ty::Covariant | ty::Bivariant => false,
         }
     }
 
@@ -336,11 +330,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
 
         debug!(?self.ambient_variance);
         // In a bivariant context this always succeeds.
-        let r = if self.ambient_variance == ty::Variance::Bivariant {
-            Ok(a)
-        } else {
-            self.relate(a, b)
-        };
+        let r = if self.ambient_variance == ty::Bivariant { Ok(a) } else { self.relate(a, b) };
 
         self.ambient_variance = old_ambient_variance;
 
@@ -474,7 +464,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
         }
 
         match self.ambient_variance {
-            ty::Variance::Covariant => {
+            ty::Covariant => {
                 // Covariance, so we want `for<..> A <: for<..> B` --
                 // therefore we compare any instantiation of A (i.e., A
                 // instantiated with existentials) against every
@@ -489,7 +479,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
                 })?;
             }
 
-            ty::Variance::Contravariant => {
+            ty::Contravariant => {
                 // Contravariance, so we want `for<..> A :> for<..> B` --
                 // therefore we compare every instantiation of A (i.e., A
                 // instantiated with universals) against any
@@ -504,7 +494,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
                 })?;
             }
 
-            ty::Variance::Invariant => {
+            ty::Invariant => {
                 // Invariant, so we want `for<..> A == for<..> B` --
                 // therefore we want `exists<..> A == for<..> B` and
                 // `exists<..> B == for<..> A`.
@@ -525,7 +515,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
                 })?;
             }
 
-            ty::Variance::Bivariant => {}
+            ty::Bivariant => {}
         }
 
         Ok(a)
@@ -584,23 +574,23 @@ impl<'bccx, 'tcx> PredicateEmittingRelation<'tcx> for NllTypeRelating<'_, 'bccx,
 
     fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
         self.register_predicates([ty::Binder::dummy(match self.ambient_variance {
-            ty::Variance::Covariant => ty::PredicateKind::AliasRelate(
+            ty::Covariant => ty::PredicateKind::AliasRelate(
                 a.into(),
                 b.into(),
                 ty::AliasRelationDirection::Subtype,
             ),
             // a :> b is b <: a
-            ty::Variance::Contravariant => ty::PredicateKind::AliasRelate(
+            ty::Contravariant => ty::PredicateKind::AliasRelate(
                 b.into(),
                 a.into(),
                 ty::AliasRelationDirection::Subtype,
             ),
-            ty::Variance::Invariant => ty::PredicateKind::AliasRelate(
+            ty::Invariant => ty::PredicateKind::AliasRelate(
                 a.into(),
                 b.into(),
                 ty::AliasRelationDirection::Equate,
             ),
-            ty::Variance::Bivariant => {
+            ty::Bivariant => {
                 unreachable!("cannot defer an alias-relate goal with Bivariant variance (yet?)")
             }
         })]);
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 2de804f5e04..c6b26dd873b 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -4,6 +4,7 @@ use std::fmt::Write;
 
 use cranelift_codegen::isa::CallConv;
 use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_hir::LangItem;
 use rustc_span::sym;
 use rustc_target::asm::*;
 use target_lexicon::BinaryFormat;
@@ -927,7 +928,7 @@ fn call_inline_asm<'tcx>(
 fn asm_clif_type<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> Option<types::Type> {
     match ty.kind() {
         // Adapted from https://github.com/rust-lang/rust/blob/f3c66088610c1b80110297c2d9a8b5f9265b013f/compiler/rustc_hir_analysis/src/check/intrinsicck.rs#L136-L151
-        ty::Adt(adt, args) if Some(adt.did()) == fx.tcx.lang_items().maybe_uninit() => {
+        ty::Adt(adt, args) if fx.tcx.is_lang_item(adt.did(), LangItem::MaybeUninit) => {
             let fields = &adt.non_enum_variant().fields;
             let ty = fields[FieldIdx::from_u32(1)].ty(fx.tcx, args);
             let ty::Adt(ty, args) = ty.kind() else {
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index db28c6857b7..60e63b956db 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -960,6 +960,43 @@ fn llvm_fixup_input<'ll, 'tcx>(
             Abi::Vector { .. },
         ) if layout.size.bytes() == 64 => bx.bitcast(value, bx.cx.type_vector(bx.cx.type_f64(), 8)),
         (
+            InlineAsmRegClass::X86(
+                X86InlineAsmRegClass::xmm_reg
+                | X86InlineAsmRegClass::ymm_reg
+                | X86InlineAsmRegClass::zmm_reg,
+            ),
+            Abi::Scalar(s),
+        ) if bx.sess().asm_arch == Some(InlineAsmArch::X86)
+            && s.primitive() == Primitive::Float(Float::F128) =>
+        {
+            bx.bitcast(value, bx.type_vector(bx.type_i32(), 4))
+        }
+        (
+            InlineAsmRegClass::X86(
+                X86InlineAsmRegClass::xmm_reg
+                | X86InlineAsmRegClass::ymm_reg
+                | X86InlineAsmRegClass::zmm_reg,
+            ),
+            Abi::Scalar(s),
+        ) if s.primitive() == Primitive::Float(Float::F16) => {
+            let value = bx.insert_element(
+                bx.const_undef(bx.type_vector(bx.type_f16(), 8)),
+                value,
+                bx.const_usize(0),
+            );
+            bx.bitcast(value, bx.type_vector(bx.type_i16(), 8))
+        }
+        (
+            InlineAsmRegClass::X86(
+                X86InlineAsmRegClass::xmm_reg
+                | X86InlineAsmRegClass::ymm_reg
+                | X86InlineAsmRegClass::zmm_reg,
+            ),
+            Abi::Vector { element, count: count @ (8 | 16) },
+        ) if element.primitive() == Primitive::Float(Float::F16) => {
+            bx.bitcast(value, bx.type_vector(bx.type_i16(), count))
+        }
+        (
             InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
             Abi::Scalar(s),
         ) => {
@@ -1037,6 +1074,39 @@ fn llvm_fixup_output<'ll, 'tcx>(
             Abi::Vector { .. },
         ) if layout.size.bytes() == 64 => bx.bitcast(value, layout.llvm_type(bx.cx)),
         (
+            InlineAsmRegClass::X86(
+                X86InlineAsmRegClass::xmm_reg
+                | X86InlineAsmRegClass::ymm_reg
+                | X86InlineAsmRegClass::zmm_reg,
+            ),
+            Abi::Scalar(s),
+        ) if bx.sess().asm_arch == Some(InlineAsmArch::X86)
+            && s.primitive() == Primitive::Float(Float::F128) =>
+        {
+            bx.bitcast(value, bx.type_f128())
+        }
+        (
+            InlineAsmRegClass::X86(
+                X86InlineAsmRegClass::xmm_reg
+                | X86InlineAsmRegClass::ymm_reg
+                | X86InlineAsmRegClass::zmm_reg,
+            ),
+            Abi::Scalar(s),
+        ) if s.primitive() == Primitive::Float(Float::F16) => {
+            let value = bx.bitcast(value, bx.type_vector(bx.type_f16(), 8));
+            bx.extract_element(value, bx.const_usize(0))
+        }
+        (
+            InlineAsmRegClass::X86(
+                X86InlineAsmRegClass::xmm_reg
+                | X86InlineAsmRegClass::ymm_reg
+                | X86InlineAsmRegClass::zmm_reg,
+            ),
+            Abi::Vector { element, count: count @ (8 | 16) },
+        ) if element.primitive() == Primitive::Float(Float::F16) => {
+            bx.bitcast(value, bx.type_vector(bx.type_f16(), count))
+        }
+        (
             InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
             Abi::Scalar(s),
         ) => {
@@ -1110,6 +1180,36 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
             Abi::Vector { .. },
         ) if layout.size.bytes() == 64 => cx.type_vector(cx.type_f64(), 8),
         (
+            InlineAsmRegClass::X86(
+                X86InlineAsmRegClass::xmm_reg
+                | X86InlineAsmRegClass::ymm_reg
+                | X86InlineAsmRegClass::zmm_reg,
+            ),
+            Abi::Scalar(s),
+        ) if cx.sess().asm_arch == Some(InlineAsmArch::X86)
+            && s.primitive() == Primitive::Float(Float::F128) =>
+        {
+            cx.type_vector(cx.type_i32(), 4)
+        }
+        (
+            InlineAsmRegClass::X86(
+                X86InlineAsmRegClass::xmm_reg
+                | X86InlineAsmRegClass::ymm_reg
+                | X86InlineAsmRegClass::zmm_reg,
+            ),
+            Abi::Scalar(s),
+        ) if s.primitive() == Primitive::Float(Float::F16) => cx.type_vector(cx.type_i16(), 8),
+        (
+            InlineAsmRegClass::X86(
+                X86InlineAsmRegClass::xmm_reg
+                | X86InlineAsmRegClass::ymm_reg
+                | X86InlineAsmRegClass::zmm_reg,
+            ),
+            Abi::Vector { element, count: count @ (8 | 16) },
+        ) if element.primitive() == Primitive::Float(Float::F16) => {
+            cx.type_vector(cx.type_i16(), count)
+        }
+        (
             InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
             Abi::Scalar(s),
         ) => {
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 53a098d178e..7d92888feee 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -142,6 +142,14 @@ pub unsafe fn create_module<'ll>(
         }
     }
 
+    if llvm_version < (19, 0, 0) {
+        if sess.target.arch == "loongarch64" {
+            // LLVM 19 updates the LoongArch64 data layout.
+            // See https://github.com/llvm/llvm-project/pull/93814
+            target_data_layout = target_data_layout.replace("-n32:64", "-n64");
+        }
+    }
+
     // Ensure the data-layout values hardcoded remain the defaults.
     {
         let tm = crate::back::write::create_informational_target_machine(tcx.sess);
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 53b9b530e9b..7e0f264a4ae 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -394,10 +394,15 @@ fn print_target_features(out: &mut dyn PrintBackendInfo, sess: &Session, tm: &ll
             (*feature, desc)
         })
         .collect::<Vec<_>>();
+
+    // Since we add this at the end ...
     rustc_target_features.extend_from_slice(&[(
         "crt-static",
         "Enables C Run-time Libraries to be statically linked",
     )]);
+    // ... we need to sort the list again.
+    rustc_target_features.sort();
+
     llvm_target_features.retain(|(f, _d)| !known_llvm_target_features.contains(f));
 
     let max_feature_len = llvm_target_features
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index 9e01c59a96f..0818d9425e2 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -1,8 +1,8 @@
 //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
 
 use rustc_errors::{Diag, ErrorGuaranteed};
-use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::{self as hir, LangItem};
 use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::ObligationCause;
@@ -801,7 +801,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 // const-eval.
 
                 // const-eval of the `begin_panic` fn assumes the argument is `&str`
-                if Some(callee) == tcx.lang_items().begin_panic_fn() {
+                if tcx.is_lang_item(callee, LangItem::BeginPanic) {
                     match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() {
                         ty::Ref(_, ty, _) if ty.is_str() => return,
                         _ => self.check_op(ops::PanicNonStr),
@@ -819,7 +819,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                     }
                 }
 
-                if Some(callee) == tcx.lang_items().exchange_malloc_fn() {
+                if tcx.is_lang_item(callee, LangItem::ExchangeMalloc) {
                     self.check_op(ops::HeapAllocation);
                     return;
                 }
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index feab5b929ac..eb9a83fb9cf 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -218,7 +218,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                 } else {
                     let mut sugg = None;
 
-                    if Some(trait_id) == ccx.tcx.lang_items().eq_trait() {
+                    if ccx.tcx.is_lang_item(trait_id, LangItem::PartialEq) {
                         match (args[0].unpack(), args[1].unpack()) {
                             (GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
                                 if self_ty == rhs_ty
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 923b9ddf9af..b17dc7f3ddd 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -1,7 +1,6 @@
 use std::mem;
 
 use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, Diagnostic, IntoDiagArg};
-use rustc_hir::CRATE_HIR_ID;
 use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo};
 use rustc_middle::mir::AssertKind;
 use rustc_middle::query::TyCtxtAt;
@@ -9,7 +8,7 @@ use rustc_middle::ty::TyCtxt;
 use rustc_middle::ty::{layout::LayoutError, ConstInt};
 use rustc_span::{Span, Symbol};
 
-use super::CompileTimeInterpreter;
+use super::CompileTimeMachine;
 use crate::errors::{self, FrameNote, ReportErrorExt};
 use crate::interpret::{err_inval, err_machine_stop};
 use crate::interpret::{ErrorHandled, Frame, InterpError, InterpErrorInfo, MachineStopType};
@@ -156,11 +155,11 @@ where
     }
 }
 
-/// Emit a lint from a const-eval situation.
+/// Emit a lint from a const-eval situation, with a backtrace.
 // Even if this is unused, please don't remove it -- chances are we will need to emit a lint during const-eval again in the future!
 pub(super) fn lint<'tcx, L>(
     tcx: TyCtxtAt<'tcx>,
-    machine: &CompileTimeInterpreter<'tcx>,
+    machine: &CompileTimeMachine<'tcx>,
     lint: &'static rustc_session::lint::Lint,
     decorator: impl FnOnce(Vec<errors::FrameNote>) -> L,
 ) where
@@ -168,12 +167,5 @@ pub(super) fn lint<'tcx, L>(
 {
     let (span, frames) = get_span_and_frames(tcx, &machine.stack);
 
-    tcx.emit_node_span_lint(
-        lint,
-        // We use the root frame for this so the crate that defines the const defines whether the
-        // lint is emitted.
-        machine.stack.first().and_then(|frame| frame.lint_root()).unwrap_or(CRATE_HIR_ID),
-        span,
-        decorator(frames),
-    );
+    tcx.emit_node_span_lint(lint, machine.best_lint_scope(*tcx), span, decorator(frames));
 }
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 36f468d3308..4b8145eb485 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -17,7 +17,7 @@ use rustc_span::def_id::LocalDefId;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{self, Abi};
 
-use super::{CanAccessMutGlobal, CompileTimeEvalContext, CompileTimeInterpreter};
+use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
 use crate::const_eval::CheckAlignment;
 use crate::errors::ConstEvalError;
 use crate::errors::{self, DanglingPtrInFinal};
@@ -32,7 +32,7 @@ use crate::CTRL_C_RECEIVED;
 // Returns a pointer to where the result lives
 #[instrument(level = "trace", skip(ecx, body))]
 fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
-    ecx: &mut CompileTimeEvalContext<'tcx>,
+    ecx: &mut CompileTimeInterpCx<'tcx>,
     cid: GlobalId<'tcx>,
     body: &'tcx mir::Body<'tcx>,
 ) -> InterpResult<'tcx, R> {
@@ -114,7 +114,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
             let err_diag = errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind };
             ecx.tcx.emit_node_span_lint(
                 lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
-                ecx.best_lint_scope(),
+                ecx.machine.best_lint_scope(*ecx.tcx),
                 err_diag.span,
                 err_diag,
             )
@@ -139,13 +139,13 @@ pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
     root_span: Span,
     param_env: ty::ParamEnv<'tcx>,
     can_access_mut_global: CanAccessMutGlobal,
-) -> CompileTimeEvalContext<'tcx> {
+) -> CompileTimeInterpCx<'tcx> {
     debug!("mk_eval_cx: {:?}", param_env);
     InterpCx::new(
         tcx,
         root_span,
         param_env,
-        CompileTimeInterpreter::new(can_access_mut_global, CheckAlignment::No),
+        CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No),
     )
 }
 
@@ -156,7 +156,7 @@ pub fn mk_eval_cx_for_const_val<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     val: mir::ConstValue<'tcx>,
     ty: Ty<'tcx>,
-) -> Option<(CompileTimeEvalContext<'tcx>, OpTy<'tcx>)> {
+) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> {
     let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No);
     let op = ecx.const_val_to_op(val, ty, None).ok()?;
     Some((ecx, op))
@@ -170,7 +170,7 @@ pub fn mk_eval_cx_for_const_val<'tcx>(
 /// encounter an `Indirect` they cannot handle.
 #[instrument(skip(ecx), level = "debug")]
 pub(super) fn op_to_const<'tcx>(
-    ecx: &CompileTimeEvalContext<'tcx>,
+    ecx: &CompileTimeInterpCx<'tcx>,
     op: &OpTy<'tcx>,
     for_diagnostics: bool,
 ) -> ConstValue<'tcx> {
@@ -328,14 +328,14 @@ pub trait InterpretationResult<'tcx> {
     /// evaluation query.
     fn make_result(
         mplace: MPlaceTy<'tcx>,
-        ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
+        ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
     ) -> Self;
 }
 
 impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> {
     fn make_result(
         mplace: MPlaceTy<'tcx>,
-        _ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
+        _ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
     ) -> Self {
         ConstAlloc { alloc_id: mplace.ptr().provenance.unwrap().alloc_id(), ty: mplace.layout.ty }
     }
@@ -383,7 +383,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
         // they do not have to behave "as if" they were evaluated at runtime.
         // For consts however we want to ensure they behave "as if" they were evaluated at runtime,
         // so we have to reject reading mutable global memory.
-        CompileTimeInterpreter::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
+        CompileTimeMachine::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
     );
     let res = ecx.load_mir(cid.instance.def, cid.promoted);
     res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, body)).map_err(|error| {
@@ -417,7 +417,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
 
 #[inline(always)]
 fn const_validate_mplace<'tcx>(
-    ecx: &InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
+    ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
     mplace: &MPlaceTy<'tcx>,
     cid: GlobalId<'tcx>,
 ) -> Result<(), ErrorHandled> {
@@ -447,7 +447,7 @@ fn const_validate_mplace<'tcx>(
 
 #[inline(always)]
 fn report_validation_error<'tcx>(
-    ecx: &InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
+    ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
     error: InterpErrorInfo<'tcx>,
     alloc_id: AllocId,
 ) -> ErrorHandled {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 79a161d3f03..d3631e0d723 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -9,12 +9,13 @@ use rustc_data_structures::fx::IndexEntry;
 use rustc_hir::def_id::DefId;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::LangItem;
+use rustc_hir::{self as hir, CRATE_HIR_ID};
 use rustc_middle::bug;
 use rustc_middle::mir;
 use rustc_middle::mir::AssertMessage;
 use rustc_middle::query::TyCtxtAt;
-use rustc_middle::ty;
 use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::builtin::WRITES_THROUGH_IMMUTABLE_POINTER;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
@@ -44,7 +45,7 @@ const TINY_LINT_TERMINATOR_LIMIT: usize = 20;
 const PROGRESS_INDICATOR_START: usize = 4_000_000;
 
 /// Extra machine state for CTFE, and the Machine instance
-pub struct CompileTimeInterpreter<'tcx> {
+pub struct CompileTimeMachine<'tcx> {
     /// The number of terminators that have been evaluated.
     ///
     /// This is used to produce lints informing the user that the compiler is not stuck.
@@ -89,12 +90,12 @@ impl From<bool> for CanAccessMutGlobal {
     }
 }
 
-impl<'tcx> CompileTimeInterpreter<'tcx> {
+impl<'tcx> CompileTimeMachine<'tcx> {
     pub(crate) fn new(
         can_access_mut_global: CanAccessMutGlobal,
         check_alignment: CheckAlignment,
     ) -> Self {
-        CompileTimeInterpreter {
+        CompileTimeMachine {
             num_evaluated_steps: 0,
             stack: Vec::new(),
             can_access_mut_global,
@@ -163,7 +164,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxIndexMap<K, V> {
     }
 }
 
-pub(crate) type CompileTimeEvalContext<'tcx> = InterpCx<'tcx, CompileTimeInterpreter<'tcx>>;
+pub(crate) type CompileTimeInterpCx<'tcx> = InterpCx<'tcx, CompileTimeMachine<'tcx>>;
 
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
 pub enum MemoryKind {
@@ -195,7 +196,7 @@ impl interpret::MayLeak for ! {
     }
 }
 
-impl<'tcx> CompileTimeEvalContext<'tcx> {
+impl<'tcx> CompileTimeInterpCx<'tcx> {
     fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
         let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
         let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
@@ -229,7 +230,7 @@ impl<'tcx> CompileTimeEvalContext<'tcx> {
         let def_id = instance.def_id();
 
         if self.tcx.has_attr(def_id, sym::rustc_const_panic_str)
-            || Some(def_id) == self.tcx.lang_items().begin_panic_fn()
+            || self.tcx.is_lang_item(def_id, LangItem::BeginPanic)
         {
             let args = self.copy_fn_args(args);
             // &str or &&str
@@ -244,7 +245,7 @@ impl<'tcx> CompileTimeEvalContext<'tcx> {
             let span = self.find_closest_untracked_caller_location();
             let (file, line, col) = self.location_triple_for_span(span);
             return Err(ConstEvalErrKind::Panic { msg, file, line, col }.into());
-        } else if Some(def_id) == self.tcx.lang_items().panic_fmt() {
+        } else if self.tcx.is_lang_item(def_id, LangItem::PanicFmt) {
             // For panic_fmt, call const_panic_fmt instead.
             let const_def_id = self.tcx.require_lang_item(LangItem::ConstPanicFmt, None);
             let new_instance = ty::Instance::expect_resolve(
@@ -255,7 +256,7 @@ impl<'tcx> CompileTimeEvalContext<'tcx> {
             );
 
             return Ok(Some(new_instance));
-        } else if Some(def_id) == self.tcx.lang_items().align_offset_fn() {
+        } else if self.tcx.is_lang_item(def_id, LangItem::AlignOffset) {
             let args = self.copy_fn_args(args);
             // For align_offset, we replace the function call if the pointer has no address.
             match self.align_offset(instance, &args, dest, ret)? {
@@ -369,7 +370,16 @@ impl<'tcx> CompileTimeEvalContext<'tcx> {
     }
 }
 
-impl<'tcx> interpret::Machine<'tcx> for CompileTimeInterpreter<'tcx> {
+impl<'tcx> CompileTimeMachine<'tcx> {
+    #[inline(always)]
+    /// Find the first stack frame that is within the current crate, if any.
+    /// Otherwise, return the crate's HirId
+    pub fn best_lint_scope(&self, tcx: TyCtxt<'tcx>) -> hir::HirId {
+        self.stack.iter().find_map(|frame| frame.lint_root(tcx)).unwrap_or(CRATE_HIR_ID)
+    }
+}
+
+impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
     compile_time_machine!(<'tcx>);
 
     type MemoryKind = MemoryKind;
@@ -600,7 +610,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeInterpreter<'tcx> {
                 // By default, we stop after a million steps, but the user can disable this lint
                 // to be able to run until the heat death of the universe or power loss, whichever
                 // comes first.
-                let hir_id = ecx.best_lint_scope();
+                let hir_id = ecx.machine.best_lint_scope(*ecx.tcx);
                 let is_error = ecx
                     .tcx
                     .lint_level_at_node(
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 66993476bef..2e8ad445cf5 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -9,7 +9,7 @@ use rustc_target::abi::{Abi, VariantIdx};
 use tracing::{debug, instrument, trace};
 
 use super::eval_queries::{mk_eval_cx_to_read_const_val, op_to_const};
-use super::machine::CompileTimeEvalContext;
+use super::machine::CompileTimeInterpCx;
 use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES};
 use crate::const_eval::CanAccessMutGlobal;
 use crate::errors::MaxNumNodesInConstErr;
@@ -21,7 +21,7 @@ use crate::interpret::{
 
 #[instrument(skip(ecx), level = "debug")]
 fn branches<'tcx>(
-    ecx: &CompileTimeEvalContext<'tcx>,
+    ecx: &CompileTimeInterpCx<'tcx>,
     place: &MPlaceTy<'tcx>,
     n: usize,
     variant: Option<VariantIdx>,
@@ -59,7 +59,7 @@ fn branches<'tcx>(
 
 #[instrument(skip(ecx), level = "debug")]
 fn slice_branches<'tcx>(
-    ecx: &CompileTimeEvalContext<'tcx>,
+    ecx: &CompileTimeInterpCx<'tcx>,
     place: &MPlaceTy<'tcx>,
     num_nodes: &mut usize,
 ) -> ValTreeCreationResult<'tcx> {
@@ -77,7 +77,7 @@ fn slice_branches<'tcx>(
 
 #[instrument(skip(ecx), level = "debug")]
 fn const_to_valtree_inner<'tcx>(
-    ecx: &CompileTimeEvalContext<'tcx>,
+    ecx: &CompileTimeInterpCx<'tcx>,
     place: &MPlaceTy<'tcx>,
     num_nodes: &mut usize,
 ) -> ValTreeCreationResult<'tcx> {
@@ -219,7 +219,7 @@ fn reconstruct_place_meta<'tcx>(
 
 #[instrument(skip(ecx), level = "debug", ret)]
 fn create_valtree_place<'tcx>(
-    ecx: &mut CompileTimeEvalContext<'tcx>,
+    ecx: &mut CompileTimeInterpCx<'tcx>,
     layout: TyAndLayout<'tcx>,
     valtree: ty::ValTree<'tcx>,
 ) -> MPlaceTy<'tcx> {
@@ -364,7 +364,7 @@ pub fn valtree_to_const_value<'tcx>(
 
 /// Put a valtree into memory and return a reference to that.
 fn valtree_to_ref<'tcx>(
-    ecx: &mut CompileTimeEvalContext<'tcx>,
+    ecx: &mut CompileTimeInterpCx<'tcx>,
     valtree: ty::ValTree<'tcx>,
     pointee_ty: Ty<'tcx>,
 ) -> Immediate {
@@ -380,7 +380,7 @@ fn valtree_to_ref<'tcx>(
 
 #[instrument(skip(ecx), level = "debug")]
 fn valtree_into_mplace<'tcx>(
-    ecx: &mut CompileTimeEvalContext<'tcx>,
+    ecx: &mut CompileTimeInterpCx<'tcx>,
     place: &MPlaceTy<'tcx>,
     valtree: ty::ValTree<'tcx>,
 ) {
@@ -457,6 +457,6 @@ fn valtree_into_mplace<'tcx>(
     }
 }
 
-fn dump_place<'tcx>(ecx: &CompileTimeEvalContext<'tcx>, place: &MPlaceTy<'tcx>) {
+fn dump_place<'tcx>(ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>) {
     trace!("{:?}", ecx.dump_place(&PlaceTy::from(place.clone())));
 }
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 0dbee8c1d94..a50b50d231d 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -241,10 +241,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         variant_index: VariantIdx,
     ) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> {
         match self.layout_of(ty)?.variants {
-            abi::Variants::Single { index } => {
-                assert_eq!(index, variant_index);
-                Ok(None)
-            }
+            abi::Variants::Single { .. } => Ok(None),
 
             abi::Variants::Multiple {
                 tag_encoding: TagEncoding::Direct,
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index e28cc05cc2a..4d93038a81e 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -4,7 +4,6 @@ use std::{fmt, mem};
 use either::{Either, Left, Right};
 use tracing::{debug, info, info_span, instrument, trace};
 
-use hir::CRATE_HIR_ID;
 use rustc_errors::DiagCtxt;
 use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
 use rustc_index::IndexVec;
@@ -250,7 +249,7 @@ impl<'tcx, Prov: Provenance> Frame<'tcx, Prov> {
 impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
     /// Get the current location within the Frame.
     ///
-    /// If this is `Left`, we are not currently executing any particular statement in
+    /// If this is `Right`, we are not currently executing any particular statement in
     /// this frame (can happen e.g. during frame initialization, and during unwinding on
     /// frames without cleanup code).
     ///
@@ -271,13 +270,18 @@ impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
         }
     }
 
-    pub fn lint_root(&self) -> Option<hir::HirId> {
-        self.current_source_info().and_then(|source_info| {
-            match &self.body.source_scopes[source_info.scope].local_data {
+    pub fn lint_root(&self, tcx: TyCtxt<'tcx>) -> Option<hir::HirId> {
+        // We first try to get a HirId via the current source scope,
+        // and fall back to `body.source`.
+        self.current_source_info()
+            .and_then(|source_info| match &self.body.source_scopes[source_info.scope].local_data {
                 mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
                 mir::ClearCrossCrate::Clear => None,
-            }
-        })
+            })
+            .or_else(|| {
+                let def_id = self.body.source.def_id().as_local();
+                def_id.map(|def_id| tcx.local_def_id_to_hir_id(def_id))
+            })
     }
 
     /// Returns the address of the buffer where the locals are stored. This is used by `Place` as a
@@ -500,6 +504,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         }
     }
 
+    /// Returns the span of the currently executed statement/terminator.
+    /// This is the span typically used for error reporting.
     #[inline(always)]
     pub fn cur_span(&self) -> Span {
         // This deliberately does *not* honor `requires_caller_location` since it is used for much
@@ -507,16 +513,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         self.stack().last().map_or(self.tcx.span, |f| f.current_span())
     }
 
-    #[inline(always)]
-    /// Find the first stack frame that is within the current crate, if any, otherwise return the crate's HirId
-    pub fn best_lint_scope(&self) -> hir::HirId {
-        self.stack()
-            .iter()
-            .find_map(|frame| frame.body.source.def_id().as_local())
-            .map_or(CRATE_HIR_ID, |def_id| self.tcx.local_def_id_to_hir_id(def_id))
-    }
-
-    #[inline(always)]
     pub(crate) fn stack(&self) -> &[Frame<'tcx, M::Provenance, M::FrameExtra>] {
         M::stack(self)
     }
@@ -632,7 +628,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     }
 
     /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
-    /// frame which is not `#[track_caller]`. This is the fancy version of `cur_span`.
+    /// frame which is not `#[track_caller]`. This matches the `caller_location` intrinsic,
+    /// and is primarily intended for the panic machinery.
     pub(crate) fn find_closest_untracked_caller_location(&self) -> Span {
         for frame in self.stack().iter().rev() {
             debug!("find_closest_untracked_caller_location: checking frame {:?}", frame.instance);
@@ -1057,7 +1054,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
                 ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false,
 
-                ty::Tuple(tys) => tys.last().iter().all(|ty| is_very_trivially_sized(**ty)),
+                ty::Tuple(tys) => tys.last().is_none_or(|ty| is_very_trivially_sized(*ty)),
 
                 ty::Pat(ty, ..) => is_very_trivially_sized(*ty),
 
diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index 3066e0933d9..8b0a2afa4d6 100644
--- a/compiler/rustc_const_eval/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -45,7 +45,7 @@ pub trait HasStaticRootDefId {
     fn static_def_id(&self) -> Option<LocalDefId>;
 }
 
-impl HasStaticRootDefId for const_eval::CompileTimeInterpreter<'_> {
+impl HasStaticRootDefId for const_eval::CompileTimeMachine<'_> {
     fn static_def_id(&self) -> Option<LocalDefId> {
         Some(self.static_root_ids?.1)
     }
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 5461e9c6ad3..9a26ac04b85 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -446,7 +446,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let (alloc_size, _alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?;
                 // Test bounds.
                 // It is sufficient to check this for the end pointer. Also check for overflow!
-                if offset.checked_add(size, &self.tcx).map_or(true, |end| end > alloc_size) {
+                if offset.checked_add(size, &self.tcx).is_none_or(|end| end > alloc_size) {
                     throw_ub!(PointerOutOfBounds {
                         alloc_id,
                         alloc_size,
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index a6eef9f5662..73bdf96627a 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -112,25 +112,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
         // Shift ops can have an RHS with a different numeric type.
         if matches!(bin_op, Shl | ShlUnchecked | Shr | ShrUnchecked) {
-            let size = left.layout.size.bits();
+            let l_bits = left.layout.size.bits();
             // Compute the equivalent shift modulo `size` that is in the range `0..size`. (This is
             // the one MIR operator that does *not* directly map to a single LLVM operation.)
             let (shift_amount, overflow) = if right.layout.abi.is_signed() {
                 let shift_amount = r_signed();
-                let overflow = shift_amount < 0 || shift_amount >= i128::from(size);
-                // Deliberately wrapping `as` casts: shift_amount *can* be negative, but the result
-                // of the `as` will be equal modulo `size` (since it is a power of two).
-                let masked_amount = (shift_amount as u128) % u128::from(size);
-                assert_eq!(overflow, shift_amount != i128::try_from(masked_amount).unwrap());
-                (masked_amount, overflow)
+                let rem = shift_amount.rem_euclid(l_bits.into());
+                // `rem` is guaranteed positive, so the `unwrap` cannot fail
+                (u128::try_from(rem).unwrap(), rem != shift_amount)
             } else {
                 let shift_amount = r_unsigned();
-                let overflow = shift_amount >= u128::from(size);
-                let masked_amount = shift_amount % u128::from(size);
-                assert_eq!(overflow, shift_amount != masked_amount);
-                (masked_amount, overflow)
+                let rem = shift_amount.rem_euclid(l_bits.into());
+                (rem, rem != shift_amount)
             };
-            let shift_amount = u32::try_from(shift_amount).unwrap(); // we masked so this will always fit
+            let shift_amount = u32::try_from(shift_amount).unwrap(); // we brought this in the range `0..size` so this will always fit
             // Compute the shifted result.
             let result = if left.layout.abi.is_signed() {
                 let l = l_signed();
@@ -362,14 +357,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let left = left.to_scalar();
                 let right = right.to_scalar();
                 Ok(match fty {
-                    FloatTy::F16 => unimplemented!("f16_f128"),
+                    FloatTy::F16 => {
+                        self.binary_float_op(bin_op, layout, left.to_f16()?, right.to_f16()?)
+                    }
                     FloatTy::F32 => {
                         self.binary_float_op(bin_op, layout, left.to_f32()?, right.to_f32()?)
                     }
                     FloatTy::F64 => {
                         self.binary_float_op(bin_op, layout, left.to_f64()?, right.to_f64()?)
                     }
-                    FloatTy::F128 => unimplemented!("f16_f128"),
+                    FloatTy::F128 => {
+                        self.binary_float_op(bin_op, layout, left.to_f128()?, right.to_f128()?)
+                    }
                 })
             }
             _ if left.layout.ty.is_integral() => {
@@ -429,11 +428,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             }
             ty::Float(fty) => {
                 let val = val.to_scalar();
+                if un_op != Neg {
+                    span_bug!(self.cur_span(), "Invalid float op {:?}", un_op);
+                }
+
                 // No NaN adjustment here, `-` is a bitwise operation!
-                let res = match (un_op, fty) {
-                    (Neg, FloatTy::F32) => Scalar::from_f32(-val.to_f32()?),
-                    (Neg, FloatTy::F64) => Scalar::from_f64(-val.to_f64()?),
-                    _ => span_bug!(self.cur_span(), "Invalid float op {:?}", un_op),
+                let res = match fty {
+                    FloatTy::F16 => Scalar::from_f16(-val.to_f16()?),
+                    FloatTy::F32 => Scalar::from_f32(-val.to_f32()?),
+                    FloatTy::F64 => Scalar::from_f64(-val.to_f64()?),
+                    FloatTy::F128 => Scalar::from_f128(-val.to_f128()?),
                 };
                 Ok(ImmTy::from_scalar(res, layout))
             }
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index 09e1a59dfa1..efa01b54342 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -300,7 +300,7 @@ where
     ) -> InterpResult<'tcx, P> {
         let len = base.len(self)?; // also asserts that we have a type where this makes sense
         let actual_to = if from_end {
-            if from.checked_add(to).map_or(true, |to| to > len) {
+            if from.checked_add(to).is_none_or(|to| to > len) {
                 // This can only be reached in ConstProp and non-rustc-MIR.
                 throw_ub!(BoundsCheckFailed { len: len, index: from.saturating_add(to) });
             }
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index 10fd6399b9a..f6537ed6ea9 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -1,4 +1,4 @@
-use crate::const_eval::{CompileTimeEvalContext, CompileTimeInterpreter, InterpretationResult};
+use crate::const_eval::{CompileTimeInterpCx, CompileTimeMachine, InterpretationResult};
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{Allocation, InterpResult, Pointer};
@@ -84,7 +84,7 @@ where
 impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx> {
     fn make_result(
         mplace: MPlaceTy<'tcx>,
-        ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
+        ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
     ) -> Self {
         let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
         let alloc = ecx.memory.alloc_map.swap_remove(&alloc_id).unwrap().1;
@@ -93,7 +93,7 @@ impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx>
 }
 
 pub(crate) fn create_static_alloc<'tcx>(
-    ecx: &mut CompileTimeEvalContext<'tcx>,
+    ecx: &mut CompileTimeInterpCx<'tcx>,
     static_def_id: LocalDefId,
     layout: TyAndLayout<'tcx>,
 ) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 6f75bc2af4e..ca8b9884933 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -29,7 +29,7 @@ use rustc_target::abi::{
 use std::hash::Hash;
 
 use super::{
-    err_ub, format_interp_error, machine::AllocMap, throw_ub, AllocId, CheckInAllocMsg,
+    err_ub, format_interp_error, machine::AllocMap, throw_ub, AllocId, AllocKind, CheckInAllocMsg,
     GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
     Pointer, Projectable, Scalar, ValueVisitor,
 };
@@ -413,8 +413,6 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
             Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds {
                 ptr_kind
             },
-            // This cannot happen during const-eval (because interning already detects
-            // dangling pointers), but it can happen in Miri.
             Ub(PointerUseAfterFree(..)) => DanglingPtrUseAfterFree {
                 ptr_kind,
             },
@@ -493,9 +491,17 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                     }
                 }
 
-                // Mutability check.
+                // Dangling and Mutability check.
+                let (size, _align, alloc_kind) = self.ecx.get_alloc_info(alloc_id);
+                if alloc_kind == AllocKind::Dead {
+                    // This can happen for zero-sized references. We can't have *any* references to non-existing
+                    // allocations though, interning rejects them all as the rest of rustc isn't happy with them...
+                    // so we throw an error, even though this isn't really UB.
+                    // A potential future alternative would be to resurrect this as a zero-sized allocation
+                    // (which codegen will then compile to an aligned dummy pointer anyway).
+                    throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind });
+                }
                 // If this allocation has size zero, there is no actual mutability here.
-                let (size, _align, _alloc_kind) = self.ecx.get_alloc_info(alloc_id);
                 if size != Size::ZERO {
                     let alloc_actual_mutbl = mutability(self.ecx, alloc_id);
                     // Mutable pointer to immutable memory is no good.
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 45ea3ec08f8..50a4d0612cc 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(box_patterns)]
 #![feature(decl_macro)]
 #![feature(if_let_guard)]
+#![feature(is_none_or)]
 #![feature(let_chains)]
 #![feature(never_type)]
 #![feature(rustdoc_internals)]
diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs
index 62c5f8734a2..3b07bee2d9c 100644
--- a/compiler/rustc_const_eval/src/util/caller_location.rs
+++ b/compiler/rustc_const_eval/src/util/caller_location.rs
@@ -7,12 +7,12 @@ use rustc_middle::ty::{self, Mutability};
 use rustc_span::symbol::Symbol;
 use tracing::trace;
 
-use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, CompileTimeEvalContext};
+use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, CompileTimeInterpCx};
 use crate::interpret::*;
 
 /// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
 fn alloc_caller_location<'tcx>(
-    ecx: &mut CompileTimeEvalContext<'tcx>,
+    ecx: &mut CompileTimeInterpCx<'tcx>,
     filename: Symbol,
     line: u32,
     col: u32,
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index 68fb122a765..daf57285ebe 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -3,7 +3,7 @@ use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, Val
 use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
 use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
 
-use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeInterpreter};
+use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
 use crate::interpret::{InterpCx, MemoryKind, OpTy};
 
 /// Determines if this type permits "raw" initialization by just transmuting some memory into an
@@ -45,7 +45,7 @@ fn might_permit_raw_init_strict<'tcx>(
     tcx: TyCtxt<'tcx>,
     kind: ValidityRequirement,
 ) -> Result<bool, &'tcx LayoutError<'tcx>> {
-    let machine = CompileTimeInterpreter::new(CanAccessMutGlobal::No, CheckAlignment::Error);
+    let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
 
     let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);
 
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 6876046a583..ff0a94f8e9b 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -12,7 +12,6 @@ elsa = "=1.7.1"
 ena = "0.14.3"
 indexmap = { version = "2.0.0" }
 jobserver_crate = { version = "0.1.28", package = "jobserver" }
-libc = "0.2"
 measureme = "11"
 rustc-hash = "1.1.0"
 rustc-rayon = { version = "0.5.0", optional = true }
@@ -41,6 +40,11 @@ features = [
     "Win32_System_Threading",
 ]
 
+[target.'cfg(unix)'.dependencies]
+# tidy-alphabetical-start
+libc = "0.2"
+# tidy-alphabetical-end
+
 [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
 # tidy-alphabetical-start
 memmap2 = "0.2.1"
diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs
index 7f36e4ca16d..8b96b36a851 100644
--- a/compiler/rustc_data_structures/src/graph/scc/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs
@@ -4,52 +4,119 @@
 //! node in the graph. This uses [Tarjan's algorithm](
 //! https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm)
 //! that completes in *O*(*n*) time.
+//! Optionally, also annotate the SCC nodes with some commutative data.
+//! Typical examples would include: minimum element in SCC, maximum element
+//! reachable from it, etc.
 
 use crate::fx::FxHashSet;
 use crate::graph::vec_graph::VecGraph;
 use crate::graph::{DirectedGraph, NumEdges, Successors};
 use rustc_index::{Idx, IndexSlice, IndexVec};
+use std::fmt::Debug;
 use std::ops::Range;
 use tracing::{debug, instrument};
 
 #[cfg(test)]
 mod tests;
 
+/// An annotation for an SCC. This can be a representative,
+/// the max/min element of the SCC, or all of the above.
+///
+/// Concretely, the both merge operations must commute, e.g. where `merge`
+/// is `merge_scc` and `merge_reached`: `a.merge(b) == b.merge(a)`
+///
+/// In general, what you want is probably always min/max according
+/// to some ordering, potentially with side constraints (min x such
+/// that P holds).
+pub trait Annotation: Debug + Copy {
+    /// Merge two existing annotations into one during
+    /// path compression.o
+    fn merge_scc(self, other: Self) -> Self;
+
+    /// Merge a successor into this annotation.
+    fn merge_reached(self, other: Self) -> Self;
+
+    fn update_scc(&mut self, other: Self) {
+        *self = self.merge_scc(other)
+    }
+
+    fn update_reachable(&mut self, other: Self) {
+        *self = self.merge_reached(other)
+    }
+}
+
+/// The empty annotation, which does nothing.
+impl Annotation for () {
+    fn merge_reached(self, _other: Self) -> Self {
+        ()
+    }
+    fn merge_scc(self, _other: Self) -> Self {
+        ()
+    }
+}
+
 /// Strongly connected components (SCC) of a graph. The type `N` is
 /// the index type for the graph nodes and `S` is the index type for
 /// the SCCs. We can map from each node to the SCC that it
 /// participates in, and we also have the successors of each SCC.
-pub struct Sccs<N: Idx, S: Idx> {
+pub struct Sccs<N: Idx, S: Idx, A: Annotation = ()> {
     /// For each node, what is the SCC index of the SCC to which it
     /// belongs.
     scc_indices: IndexVec<N, S>,
 
-    /// Data about each SCC.
-    scc_data: SccData<S>,
+    /// Data about all the SCCs.
+    scc_data: SccData<S, A>,
 }
 
-pub struct SccData<S: Idx> {
-    /// For each SCC, the range of `all_successors` where its
+/// Information about an invidividual SCC node.
+struct SccDetails<A: Annotation> {
+    /// For this SCC, the range of `all_successors` where its
     /// successors can be found.
-    ranges: IndexVec<S, Range<usize>>,
+    range: Range<usize>,
+
+    /// User-specified metadata about the SCC.
+    annotation: A,
+}
+
+// The name of this struct should discourage you from making it public and leaking
+// its representation. This message was left here by one who came before you,
+// who learnt the hard way that making even small changes in representation
+// is difficult when it's publicly inspectable.
+//
+// Obey the law of Demeter!
+struct SccData<S: Idx, A: Annotation> {
+    /// Maps SCC indices to their metadata, including
+    /// offsets into `all_successors`.
+    scc_details: IndexVec<S, SccDetails<A>>,
 
     /// Contains the successors for all the Sccs, concatenated. The
     /// range of indices corresponding to a given SCC is found in its
-    /// SccData.
+    /// `scc_details.range`.
     all_successors: Vec<S>,
 }
 
-impl<N: Idx, S: Idx + Ord> Sccs<N, S> {
+impl<N: Idx, S: Idx + Ord> Sccs<N, S, ()> {
+    /// Compute SCCs without annotations.
     pub fn new(graph: &impl Successors<Node = N>) -> Self {
-        SccsConstruction::construct(graph)
+        Self::new_with_annotation(graph, |_| ())
     }
+}
 
-    pub fn scc_indices(&self) -> &IndexSlice<N, S> {
-        &self.scc_indices
+impl<N: Idx, S: Idx + Ord, A: Annotation> Sccs<N, S, A> {
+    /// Compute SCCs and annotate them with a user-supplied annotation
+    pub fn new_with_annotation<F: Fn(N) -> A>(
+        graph: &impl Successors<Node = N>,
+        to_annotation: F,
+    ) -> Self {
+        SccsConstruction::construct(graph, to_annotation)
     }
 
-    pub fn scc_data(&self) -> &SccData<S> {
-        &self.scc_data
+    pub fn annotation(&self, scc: S) -> A {
+        self.scc_data.annotation(scc)
+    }
+
+    pub fn scc_indices(&self) -> &IndexSlice<N, S> {
+        &self.scc_indices
     }
 
     /// Returns the number of SCCs in the graph.
@@ -90,7 +157,7 @@ impl<N: Idx, S: Idx + Ord> Sccs<N, S> {
     }
 }
 
-impl<N: Idx, S: Idx + Ord> DirectedGraph for Sccs<N, S> {
+impl<N: Idx, S: Idx + Ord, A: Annotation> DirectedGraph for Sccs<N, S, A> {
     type Node = S;
 
     fn num_nodes(&self) -> usize {
@@ -98,43 +165,33 @@ impl<N: Idx, S: Idx + Ord> DirectedGraph for Sccs<N, S> {
     }
 }
 
-impl<N: Idx, S: Idx + Ord> NumEdges for Sccs<N, S> {
+impl<N: Idx, S: Idx + Ord, A: Annotation> NumEdges for Sccs<N, S, A> {
     fn num_edges(&self) -> usize {
         self.scc_data.all_successors.len()
     }
 }
 
-impl<N: Idx, S: Idx + Ord> Successors for Sccs<N, S> {
+impl<N: Idx, S: Idx + Ord, A: Annotation> Successors for Sccs<N, S, A> {
     fn successors(&self, node: S) -> impl Iterator<Item = Self::Node> {
         self.successors(node).iter().cloned()
     }
 }
 
-impl<S: Idx> SccData<S> {
+impl<S: Idx, A: Annotation> SccData<S, A> {
     /// Number of SCCs,
     fn len(&self) -> usize {
-        self.ranges.len()
-    }
-
-    pub fn ranges(&self) -> &IndexSlice<S, Range<usize>> {
-        &self.ranges
-    }
-
-    pub fn all_successors(&self) -> &Vec<S> {
-        &self.all_successors
+        self.scc_details.len()
     }
 
     /// Returns the successors of the given SCC.
     fn successors(&self, scc: S) -> &[S] {
-        // Annoyingly, `range` does not implement `Copy`, so we have
-        // to do `range.start..range.end`:
-        let range = &self.ranges[scc];
-        &self.all_successors[range.start..range.end]
+        &self.all_successors[self.scc_details[scc].range.clone()]
     }
 
     /// Creates a new SCC with `successors` as its successors and
+    /// the maximum weight of its internal nodes `scc_max_weight` and
     /// returns the resulting index.
-    fn create_scc(&mut self, successors: impl IntoIterator<Item = S>) -> S {
+    fn create_scc(&mut self, successors: impl IntoIterator<Item = S>, annotation: A) -> S {
         // Store the successors on `scc_successors_vec`, remembering
         // the range of indices.
         let all_successors_start = self.all_successors.len();
@@ -142,22 +199,35 @@ impl<S: Idx> SccData<S> {
         let all_successors_end = self.all_successors.len();
 
         debug!(
-            "create_scc({:?}) successors={:?}",
-            self.ranges.len(),
+            "create_scc({:?}) successors={:?}, annotation={:?}",
+            self.len(),
             &self.all_successors[all_successors_start..all_successors_end],
+            annotation
         );
 
-        self.ranges.push(all_successors_start..all_successors_end)
+        let range = all_successors_start..all_successors_end;
+        let metadata = SccDetails { range, annotation };
+        self.scc_details.push(metadata)
+    }
+
+    fn annotation(&self, scc: S) -> A {
+        self.scc_details[scc].annotation
     }
 }
 
-struct SccsConstruction<'c, G: DirectedGraph + Successors, S: Idx> {
+struct SccsConstruction<'c, G, S, A, F>
+where
+    G: DirectedGraph + Successors,
+    S: Idx,
+    A: Annotation,
+    F: Fn(G::Node) -> A,
+{
     graph: &'c G,
 
     /// The state of each node; used during walk to record the stack
     /// and after walk to record what cycle each node ended up being
     /// in.
-    node_states: IndexVec<G::Node, NodeState<G::Node, S>>,
+    node_states: IndexVec<G::Node, NodeState<G::Node, S, A>>,
 
     /// The stack of nodes that we are visiting as part of the DFS.
     node_stack: Vec<G::Node>,
@@ -174,26 +244,34 @@ struct SccsConstruction<'c, G: DirectedGraph + Successors, S: Idx> {
     /// around between successors to amortize memory allocation costs.
     duplicate_set: FxHashSet<S>,
 
-    scc_data: SccData<S>,
+    scc_data: SccData<S, A>,
+
+    /// A function that constructs an initial SCC annotation
+    /// out of a single node.
+    to_annotation: F,
 }
 
 #[derive(Copy, Clone, Debug)]
-enum NodeState<N, S> {
+enum NodeState<N, S, A> {
     /// This node has not yet been visited as part of the DFS.
     ///
     /// After SCC construction is complete, this state ought to be
     /// impossible.
     NotVisited,
 
-    /// This node is currently being walk as part of our DFS. It is on
-    /// the stack at the depth `depth`.
+    /// This node is currently being walked as part of our DFS. It is on
+    /// the stack at the depth `depth` and its current annotation is
+    /// `annotation`.
     ///
     /// After SCC construction is complete, this state ought to be
     /// impossible.
-    BeingVisited { depth: usize },
+    BeingVisited { depth: usize, annotation: A },
 
-    /// Indicates that this node is a member of the given cycle.
-    InCycle { scc_index: S },
+    /// Indicates that this node is a member of the given cycle where
+    /// the merged annotation is `annotation`.
+    /// Note that an SCC can have several cycles, so its final annotation
+    /// is the merged value of all its member annotations.
+    InCycle { scc_index: S, annotation: A },
 
     /// Indicates that this node is a member of whatever cycle
     /// `parent` is a member of. This state is transient: whenever we
@@ -203,16 +281,27 @@ enum NodeState<N, S> {
     InCycleWith { parent: N },
 }
 
+/// The state of walking a given node.
 #[derive(Copy, Clone, Debug)]
-enum WalkReturn<S> {
-    Cycle { min_depth: usize },
-    Complete { scc_index: S },
+enum WalkReturn<S, A> {
+    /// The walk found a cycle, but the entire component is not known to have
+    /// been fully walked yet. We only know the minimum depth of  this
+    /// component in a minimum spanning tree of the graph. This component
+    /// is tentatively represented by the state of the first node of this
+    /// cycle we met, which is at `min_depth`.
+    Cycle { min_depth: usize, annotation: A },
+    /// The SCC and everything reachable from it have been fully walked.
+    /// At this point we know what is inside the SCC as we have visited every
+    /// node reachable from it. The SCC can now be fully represented by its ID.
+    Complete { scc_index: S, annotation: A },
 }
 
-impl<'c, G, S> SccsConstruction<'c, G, S>
+impl<'c, G, S, A, F> SccsConstruction<'c, G, S, A, F>
 where
     G: DirectedGraph + Successors,
     S: Idx,
+    F: Fn(G::Node) -> A,
+    A: Annotation,
 {
     /// Identifies SCCs in the graph `G` and computes the resulting
     /// DAG. This uses a variant of [Tarjan's
@@ -225,8 +314,10 @@ where
     /// D' (i.e., D' < D), we know that N, N', and all nodes in
     /// between them on the stack are part of an SCC.
     ///
+    /// Additionally, we keep track of a current annotation of the SCC.
+    ///
     /// [wikipedia]: https://bit.ly/2EZIx84
-    fn construct(graph: &'c G) -> Sccs<G::Node, S> {
+    fn construct(graph: &'c G, to_annotation: F) -> Sccs<G::Node, S, A> {
         let num_nodes = graph.num_nodes();
 
         let mut this = Self {
@@ -234,15 +325,16 @@ where
             node_states: IndexVec::from_elem_n(NodeState::NotVisited, num_nodes),
             node_stack: Vec::with_capacity(num_nodes),
             successors_stack: Vec::new(),
-            scc_data: SccData { ranges: IndexVec::new(), all_successors: Vec::new() },
+            scc_data: SccData { scc_details: IndexVec::new(), all_successors: Vec::new() },
             duplicate_set: FxHashSet::default(),
+            to_annotation,
         };
 
         let scc_indices = (0..num_nodes)
             .map(G::Node::new)
             .map(|node| match this.start_walk_from(node) {
-                WalkReturn::Complete { scc_index } => scc_index,
-                WalkReturn::Cycle { min_depth } => {
+                WalkReturn::Complete { scc_index, .. } => scc_index,
+                WalkReturn::Cycle { min_depth, .. } => {
                     panic!("`start_walk_node({node:?})` returned cycle with depth {min_depth:?}")
                 }
             })
@@ -251,12 +343,8 @@ where
         Sccs { scc_indices, scc_data: this.scc_data }
     }
 
-    fn start_walk_from(&mut self, node: G::Node) -> WalkReturn<S> {
-        if let Some(result) = self.inspect_node(node) {
-            result
-        } else {
-            self.walk_unvisited_node(node)
-        }
+    fn start_walk_from(&mut self, node: G::Node) -> WalkReturn<S, A> {
+        self.inspect_node(node).unwrap_or_else(|| self.walk_unvisited_node(node))
     }
 
     /// Inspect a node during the DFS. We first examine its current
@@ -271,11 +359,15 @@ where
     /// Otherwise, we are looking at a node that has already been
     /// completely visited. We therefore return `WalkReturn::Complete`
     /// with its associated SCC index.
-    fn inspect_node(&mut self, node: G::Node) -> Option<WalkReturn<S>> {
+    fn inspect_node(&mut self, node: G::Node) -> Option<WalkReturn<S, A>> {
         Some(match self.find_state(node) {
-            NodeState::InCycle { scc_index } => WalkReturn::Complete { scc_index },
+            NodeState::InCycle { scc_index, annotation } => {
+                WalkReturn::Complete { scc_index, annotation }
+            }
 
-            NodeState::BeingVisited { depth: min_depth } => WalkReturn::Cycle { min_depth },
+            NodeState::BeingVisited { depth: min_depth, annotation } => {
+                WalkReturn::Cycle { min_depth, annotation }
+            }
 
             NodeState::NotVisited => return None,
 
@@ -290,7 +382,7 @@ where
     /// of `r2` (and updates `r` to reflect current result). This is
     /// basically the "find" part of a standard union-find algorithm
     /// (with path compression).
-    fn find_state(&mut self, mut node: G::Node) -> NodeState<G::Node, S> {
+    fn find_state(&mut self, mut node: G::Node) -> NodeState<G::Node, S, A> {
         // To avoid recursion we temporarily reuse the `parent` of each
         // InCycleWith link to encode a downwards link while compressing
         // the path. After we have found the root or deepest node being
@@ -306,24 +398,40 @@ where
         // found the initial self-loop.
         let mut previous_node = node;
 
-        // Ultimately assigned by the parent when following
+        // Ultimately propagated to all the transitive parents when following
         // `InCycleWith` upwards.
-        let node_state = loop {
-            debug!("find_state(r = {:?} in state {:?})", node, self.node_states[node]);
-            match self.node_states[node] {
-                NodeState::InCycle { scc_index } => break NodeState::InCycle { scc_index },
-                NodeState::BeingVisited { depth } => break NodeState::BeingVisited { depth },
-                NodeState::NotVisited => break NodeState::NotVisited,
-                NodeState::InCycleWith { parent } => {
-                    // We test this, to be extremely sure that we never
-                    // ever break our termination condition for the
-                    // reverse iteration loop.
-                    assert!(node != parent, "Node can not be in cycle with itself");
-                    // Store the previous node as an inverted list link
-                    self.node_states[node] = NodeState::InCycleWith { parent: previous_node };
-                    // Update to parent node.
-                    previous_node = node;
-                    node = parent;
+        // This loop performs the downward link encoding mentioned above. Details below!
+        // Note that there are two different states being assigned: the root state, and
+        // a potentially derived version of the root state for non-root nodes in the chain.
+        let (root_state, assigned_state) = {
+            loop {
+                debug!("find_state(r = {node:?} in state {:?})", self.node_states[node]);
+                match self.node_states[node] {
+                    // This must have been the first and only state since it is unexplored*;
+                    // no update needed! * Unless there is a bug :')
+                    s @ NodeState::NotVisited => return s,
+                    // We are in a completely discovered SCC; every node on our path is in that SCC:
+                    s @ NodeState::InCycle { .. } => break (s, s),
+                    // The Interesting Third Base Case: we are a path back to a root node
+                    // still being explored. Now we need that node to keep its state and
+                    // every other node to be recorded as being in whatever component that
+                    // ends up in.
+                    s @ NodeState::BeingVisited { depth, .. } => {
+                        break (s, NodeState::InCycleWith { parent: self.node_stack[depth] });
+                    }
+                    // We are not at the head of a path; keep compressing it!
+                    NodeState::InCycleWith { parent } => {
+                        // We test this, to be extremely sure that we never
+                        // ever break our termination condition for the
+                        // reverse iteration loop.
+                        assert!(node != parent, "Node can not be in cycle with itself");
+
+                        // Store the previous node as an inverted list link
+                        self.node_states[node] = NodeState::InCycleWith { parent: previous_node };
+                        // Update to parent node.
+                        previous_node = node;
+                        node = parent;
+                    }
                 }
             }
         };
@@ -365,10 +473,14 @@ where
         // Move backwards until we found the node where we started. We
         // will know when we hit the state where previous_node == node.
         loop {
-            // Back at the beginning, we can return.
+            // Back at the beginning, we can return. Note that we return the root state.
+            // This is becuse for components being explored, we would otherwise get a
+            // `node_state[n] = InCycleWith{ parent: n }` and that's wrong.
             if previous_node == node {
-                return node_state;
+                return root_state;
             }
+            debug!("Compressing {node:?} down to {previous_node:?} with state {assigned_state:?}");
+
             // Update to previous node in the link.
             match self.node_states[previous_node] {
                 NodeState::InCycleWith { parent: previous } => {
@@ -376,34 +488,14 @@ where
                     previous_node = previous;
                 }
                 // Only InCycleWith nodes were added to the reverse linked list.
-                other => panic!("Invalid previous link while compressing cycle: {other:?}"),
+                other => unreachable!("Invalid previous link while compressing cycle: {other:?}"),
             }
 
-            debug!("find_state: parent_state = {:?}", node_state);
-
-            // Update the node state from the parent state. The assigned
-            // state is actually a loop invariant but it will only be
-            // evaluated if there is at least one backlink to follow.
-            // Fully trusting llvm here to find this loop optimization.
-            match node_state {
-                // Path compression, make current node point to the same root.
-                NodeState::InCycle { .. } => {
-                    self.node_states[node] = node_state;
-                }
-                // Still visiting nodes, compress to cycle to the node
-                // at that depth.
-                NodeState::BeingVisited { depth } => {
-                    self.node_states[node] =
-                        NodeState::InCycleWith { parent: self.node_stack[depth] };
-                }
-                // These are never allowed as parent nodes. InCycleWith
-                // should have been followed to a real parent and
-                // NotVisited can not be part of a cycle since it should
-                // have instead gotten explored.
-                NodeState::NotVisited | NodeState::InCycleWith { .. } => {
-                    panic!("invalid parent state: {node_state:?}")
-                }
-            }
+            // Update the node state to the (potentially derived) state.
+            // If the root is still being explored, this is
+            // `InCycleWith{ parent: <root node>}`, otherwise
+            // `assigned_state == root_state`.
+            self.node_states[node] = assigned_state;
         }
     }
 
@@ -413,30 +505,36 @@ where
     /// caller decide avoids mutual recursion between the two methods and allows
     /// us to maintain an allocated stack for nodes on the path between calls.
     #[instrument(skip(self, initial), level = "debug")]
-    fn walk_unvisited_node(&mut self, initial: G::Node) -> WalkReturn<S> {
-        struct VisitingNodeFrame<G: DirectedGraph, Successors> {
+    fn walk_unvisited_node(&mut self, initial: G::Node) -> WalkReturn<S, A> {
+        debug!("Walk unvisited node: {initial:?}");
+        struct VisitingNodeFrame<G: DirectedGraph, Successors, A> {
             node: G::Node,
-            iter: Option<Successors>,
+            successors: Option<Successors>,
             depth: usize,
             min_depth: usize,
             successors_len: usize,
             min_cycle_root: G::Node,
             successor_node: G::Node,
+            /// The annotation for the SCC starting in `node`. It may or may
+            /// not contain other nodes.
+            current_component_annotation: A,
         }
 
         // Move the stack to a local variable. We want to utilize the existing allocation and
         // mutably borrow it without borrowing self at the same time.
         let mut successors_stack = core::mem::take(&mut self.successors_stack);
+
         debug_assert_eq!(successors_stack.len(), 0);
 
-        let mut stack: Vec<VisitingNodeFrame<G, _>> = vec![VisitingNodeFrame {
+        let mut stack: Vec<VisitingNodeFrame<G, _, _>> = vec![VisitingNodeFrame {
             node: initial,
             depth: 0,
             min_depth: 0,
-            iter: None,
+            successors: None,
             successors_len: 0,
             min_cycle_root: initial,
             successor_node: initial,
+            current_component_annotation: (self.to_annotation)(initial),
         }];
 
         let mut return_value = None;
@@ -445,18 +543,26 @@ where
             let VisitingNodeFrame {
                 node,
                 depth,
-                iter,
+                successors,
                 successors_len,
                 min_depth,
                 min_cycle_root,
                 successor_node,
+                current_component_annotation,
             } = frame;
-
             let node = *node;
             let depth = *depth;
 
-            let successors = match iter {
-                Some(iter) => iter,
+            // node is definitely in the current component, add it to the annotation.
+            if node != initial {
+                current_component_annotation.update_scc((self.to_annotation)(node));
+            }
+            debug!(
+                "Visiting {node:?} at depth {depth:?}, annotation: {current_component_annotation:?}"
+            );
+
+            let successors = match successors {
+                Some(successors) => successors,
                 None => {
                     // This None marks that we still have the initialize this node's frame.
                     debug!(?depth, ?node);
@@ -464,7 +570,10 @@ where
                     debug_assert!(matches!(self.node_states[node], NodeState::NotVisited));
 
                     // Push `node` onto the stack.
-                    self.node_states[node] = NodeState::BeingVisited { depth };
+                    self.node_states[node] = NodeState::BeingVisited {
+                        depth,
+                        annotation: *current_component_annotation,
+                    };
                     self.node_stack.push(node);
 
                     // Walk each successor of the node, looking to see if any of
@@ -472,11 +581,11 @@ where
                     // so, that means they can also reach us.
                     *successors_len = successors_stack.len();
                     // Set and return a reference, this is currently empty.
-                    iter.get_or_insert(self.graph.successors(node))
+                    successors.get_or_insert(self.graph.successors(node))
                 }
             };
 
-            // Now that iter is initialized, this is a constant for this frame.
+            // Now that the successors iterator is initialized, this is a constant for this frame.
             let successors_len = *successors_len;
 
             // Construct iterators for the nodes and walk results. There are two cases:
@@ -489,10 +598,17 @@ where
                 debug!(?node, ?successor_node);
                 (successor_node, self.inspect_node(successor_node))
             });
-
             for (successor_node, walk) in returned_walk.chain(successor_walk) {
                 match walk {
-                    Some(WalkReturn::Cycle { min_depth: successor_min_depth }) => {
+                    // The starting node `node` leads to a cycle whose earliest node,
+                    // `successor_node`, is at `min_depth`. There may be more cycles.
+                    Some(WalkReturn::Cycle {
+                        min_depth: successor_min_depth,
+                        annotation: successor_annotation,
+                    }) => {
+                        debug!(
+                            "Cycle found from {node:?}, minimum depth: {successor_min_depth:?}, annotation: {successor_annotation:?}"
+                        );
                         // Track the minimum depth we can reach.
                         assert!(successor_min_depth <= depth);
                         if successor_min_depth < *min_depth {
@@ -500,41 +616,56 @@ where
                             *min_depth = successor_min_depth;
                             *min_cycle_root = successor_node;
                         }
+                        current_component_annotation.update_scc(successor_annotation);
                     }
-
-                    Some(WalkReturn::Complete { scc_index: successor_scc_index }) => {
+                    // The starting node `node` is succeeded by a fully identified SCC
+                    // which is now added to the set under `scc_index`.
+                    Some(WalkReturn::Complete {
+                        scc_index: successor_scc_index,
+                        annotation: successor_annotation,
+                    }) => {
+                        debug!(
+                            "Complete; {node:?} is root of complete-visited SCC idx {successor_scc_index:?} with annotation {successor_annotation:?}"
+                        );
                         // Push the completed SCC indices onto
                         // the `successors_stack` for later.
                         debug!(?node, ?successor_scc_index);
                         successors_stack.push(successor_scc_index);
+                        current_component_annotation.update_reachable(successor_annotation);
                     }
-
+                    // `node` has no more (direct) successors; search recursively.
                     None => {
                         let depth = depth + 1;
+                        debug!("Recursing down into {successor_node:?} at depth {depth:?}");
                         debug!(?depth, ?successor_node);
                         // Remember which node the return value will come from.
                         frame.successor_node = successor_node;
-                        // Start a new stack frame the step into it.
+                        // Start a new stack frame, then step into it.
                         stack.push(VisitingNodeFrame {
                             node: successor_node,
                             depth,
-                            iter: None,
+                            successors: None,
                             successors_len: 0,
                             min_depth: depth,
                             min_cycle_root: successor_node,
                             successor_node,
+                            current_component_annotation: (self.to_annotation)(successor_node),
                         });
                         continue 'recurse;
                     }
                 }
             }
 
+            debug!("Finished walk from {node:?} with annotation: {current_component_annotation:?}");
+
             // Completed walk, remove `node` from the stack.
             let r = self.node_stack.pop();
             debug_assert_eq!(r, Some(node));
 
             // Remove the frame, it's done.
             let frame = stack.pop().unwrap();
+            let current_component_annotation = frame.current_component_annotation;
+            debug_assert_eq!(frame.node, node);
 
             // If `min_depth == depth`, then we are the root of the
             // cycle: we can't reach anyone further down the stack.
@@ -543,6 +674,8 @@ where
             // We return one frame at a time so there can't be another return value.
             debug_assert!(return_value.is_none());
             return_value = Some(if frame.min_depth == depth {
+                // We are at the head of the component.
+
                 // Note that successor stack may have duplicates, so we
                 // want to remove those:
                 let deduplicated_successors = {
@@ -552,15 +685,25 @@ where
                         .drain(successors_len..)
                         .filter(move |&i| duplicate_set.insert(i))
                 };
-                let scc_index = self.scc_data.create_scc(deduplicated_successors);
-                self.node_states[node] = NodeState::InCycle { scc_index };
-                WalkReturn::Complete { scc_index }
+
+                debug!("Creating SCC rooted in {node:?} with successor {:?}", frame.successor_node);
+
+                let scc_index =
+                    self.scc_data.create_scc(deduplicated_successors, current_component_annotation);
+
+                self.node_states[node] =
+                    NodeState::InCycle { scc_index, annotation: current_component_annotation };
+
+                WalkReturn::Complete { scc_index, annotation: current_component_annotation }
             } else {
                 // We are not the head of the cycle. Return back to our
                 // caller. They will take ownership of the
                 // `self.successors` data that we pushed.
                 self.node_states[node] = NodeState::InCycleWith { parent: frame.min_cycle_root };
-                WalkReturn::Cycle { min_depth: frame.min_depth }
+                WalkReturn::Cycle {
+                    min_depth: frame.min_depth,
+                    annotation: current_component_annotation,
+                }
             });
         }
 
diff --git a/compiler/rustc_data_structures/src/graph/scc/tests.rs b/compiler/rustc_data_structures/src/graph/scc/tests.rs
index 513df666d0d..373f87bfdbc 100644
--- a/compiler/rustc_data_structures/src/graph/scc/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/scc/tests.rs
@@ -3,10 +3,53 @@ extern crate test;
 use super::*;
 use crate::graph::tests::TestGraph;
 
+#[derive(Copy, Clone, Debug)]
+struct MaxReached(usize);
+type UsizeSccs = Sccs<usize, usize, ()>;
+type MaxReachedSccs = Sccs<usize, usize, MaxReached>;
+
+impl Annotation for MaxReached {
+    fn merge_scc(self, other: Self) -> Self {
+        Self(std::cmp::max(other.0, self.0))
+    }
+
+    fn merge_reached(self, other: Self) -> Self {
+        self.merge_scc(other)
+    }
+}
+
+impl PartialEq<usize> for MaxReached {
+    fn eq(&self, other: &usize) -> bool {
+        &self.0 == other
+    }
+}
+
+impl MaxReached {
+    fn from_usize(nr: usize) -> Self {
+        Self(nr)
+    }
+}
+
+#[derive(Copy, Clone, Debug)]
+struct MinMaxIn {
+    min: usize,
+    max: usize,
+}
+
+impl Annotation for MinMaxIn {
+    fn merge_scc(self, other: Self) -> Self {
+        Self { min: std::cmp::min(self.min, other.min), max: std::cmp::max(self.max, other.max) }
+    }
+
+    fn merge_reached(self, _other: Self) -> Self {
+        self
+    }
+}
+
 #[test]
 fn diamond() {
     let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]);
-    let sccs: Sccs<_, usize> = Sccs::new(&graph);
+    let sccs: UsizeSccs = Sccs::new(&graph);
     assert_eq!(sccs.num_sccs(), 4);
     assert_eq!(sccs.num_sccs(), 4);
 }
@@ -34,7 +77,7 @@ fn test_big_scc() {
     +-- 2 <--+
          */
     let graph = TestGraph::new(0, &[(0, 1), (1, 2), (1, 3), (2, 0), (3, 2)]);
-    let sccs: Sccs<_, usize> = Sccs::new(&graph);
+    let sccs: UsizeSccs = Sccs::new(&graph);
     assert_eq!(sccs.num_sccs(), 1);
 }
 
@@ -50,7 +93,7 @@ fn test_three_sccs() {
     +-- 2 <--+
          */
     let graph = TestGraph::new(0, &[(0, 1), (1, 2), (2, 1), (3, 2)]);
-    let sccs: Sccs<_, usize> = Sccs::new(&graph);
+    let sccs: UsizeSccs = Sccs::new(&graph);
     assert_eq!(sccs.num_sccs(), 3);
     assert_eq!(sccs.scc(0), 1);
     assert_eq!(sccs.scc(1), 0);
@@ -106,7 +149,7 @@ fn test_find_state_2() {
     // 2 InCycleWith { 1 }
     // 3 InCycleWith { 0 }
 
-    let sccs: Sccs<_, usize> = Sccs::new(&graph);
+    let sccs: UsizeSccs = Sccs::new(&graph);
     assert_eq!(sccs.num_sccs(), 1);
     assert_eq!(sccs.scc(0), 0);
     assert_eq!(sccs.scc(1), 0);
@@ -130,7 +173,7 @@ fn test_find_state_3() {
          */
     let graph =
         TestGraph::new(0, &[(0, 1), (0, 4), (1, 2), (1, 3), (2, 1), (3, 0), (4, 2), (5, 2)]);
-    let sccs: Sccs<_, usize> = Sccs::new(&graph);
+    let sccs: UsizeSccs = Sccs::new(&graph);
     assert_eq!(sccs.num_sccs(), 2);
     assert_eq!(sccs.scc(0), 0);
     assert_eq!(sccs.scc(1), 0);
@@ -165,7 +208,7 @@ fn test_deep_linear() {
         nodes.push((i - 1, i));
     }
     let graph = TestGraph::new(0, nodes.as_slice());
-    let sccs: Sccs<_, usize> = Sccs::new(&graph);
+    let sccs: UsizeSccs = Sccs::new(&graph);
     assert_eq!(sccs.num_sccs(), NR_NODES);
     assert_eq!(sccs.scc(0), NR_NODES - 1);
     assert_eq!(sccs.scc(NR_NODES - 1), 0);
@@ -210,7 +253,164 @@ fn bench_sccc(b: &mut test::Bencher) {
     graph[21] = (7, 4);
     let graph = TestGraph::new(0, &graph[..]);
     b.iter(|| {
-        let sccs: Sccs<_, usize> = Sccs::new(&graph);
+        let sccs: UsizeSccs = Sccs::new(&graph);
         assert_eq!(sccs.num_sccs(), 3);
     });
 }
+
+#[test]
+fn test_max_self_loop() {
+    let graph = TestGraph::new(0, &[(0, 0)]);
+    let sccs: MaxReachedSccs =
+        Sccs::new_with_annotation(&graph, |n| if n == 0 { MaxReached(17) } else { MaxReached(0) });
+    assert_eq!(sccs.annotation(0), 17);
+}
+
+#[test]
+fn test_max_branch() {
+    let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 4)]);
+    let sccs: MaxReachedSccs = Sccs::new_with_annotation(&graph, MaxReached::from_usize);
+    assert_eq!(sccs.annotation(sccs.scc(0)), 4);
+    assert_eq!(sccs.annotation(sccs.scc(1)), 3);
+    assert_eq!(sccs.annotation(sccs.scc(2)), 4);
+}
+#[test]
+fn test_single_cycle_max() {
+    let graph = TestGraph::new(0, &[(0, 2), (2, 3), (2, 4), (4, 1), (1, 2)]);
+    let sccs: MaxReachedSccs = Sccs::new_with_annotation(&graph, MaxReached::from_usize);
+    assert_eq!(sccs.annotation(sccs.scc(2)), 4);
+    assert_eq!(sccs.annotation(sccs.scc(0)), 4);
+}
+
+#[test]
+fn test_simple_cycle_max() {
+    let graph = TestGraph::new(0, &[(0, 1), (1, 2), (2, 0)]);
+    let sccs: MaxReachedSccs = Sccs::new_with_annotation(&graph, MaxReached::from_usize);
+    assert_eq!(sccs.num_sccs(), 1);
+}
+
+#[test]
+fn test_double_cycle_max() {
+    let graph =
+        TestGraph::new(0, &[(0, 1), (1, 2), (1, 4), (2, 3), (2, 4), (3, 5), (4, 1), (5, 4)]);
+    let sccs: MaxReachedSccs =
+        Sccs::new_with_annotation(&graph, |n| if n == 5 { MaxReached(2) } else { MaxReached(1) });
+
+    assert_eq!(sccs.annotation(sccs.scc(0)).0, 2);
+}
+
+#[test]
+fn test_bug_minimised() {
+    let graph = TestGraph::new(0, &[(0, 3), (0, 1), (3, 2), (2, 3), (1, 4), (4, 5), (5, 4)]);
+    let sccs: MaxReachedSccs = Sccs::new_with_annotation(&graph, |n| match n {
+        3 => MaxReached(1),
+        _ => MaxReached(0),
+    });
+    assert_eq!(sccs.annotation(sccs.scc(2)), 1);
+    assert_eq!(sccs.annotation(sccs.scc(1)), 0);
+    assert_eq!(sccs.annotation(sccs.scc(4)), 0);
+}
+
+#[test]
+fn test_bug_max_leak_minimised() {
+    let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (3, 0), (3, 4), (4, 3)]);
+    let sccs: MaxReachedSccs = Sccs::new_with_annotation(&graph, |w| match w {
+        4 => MaxReached(1),
+        _ => MaxReached(0),
+    });
+
+    assert_eq!(sccs.annotation(sccs.scc(2)), 0);
+    assert_eq!(sccs.annotation(sccs.scc(3)), 1);
+    assert_eq!(sccs.annotation(sccs.scc(0)), 1);
+}
+
+#[test]
+fn test_bug_max_leak() {
+    let graph = TestGraph::new(
+        8,
+        &[
+            (0, 0),
+            (0, 18),
+            (0, 19),
+            (0, 1),
+            (0, 2),
+            (0, 7),
+            (0, 8),
+            (0, 23),
+            (18, 0),
+            (18, 12),
+            (19, 0),
+            (19, 25),
+            (12, 18),
+            (12, 3),
+            (12, 5),
+            (3, 12),
+            (3, 21),
+            (3, 22),
+            (5, 13),
+            (21, 3),
+            (22, 3),
+            (13, 5),
+            (13, 4),
+            (4, 13),
+            (4, 0),
+            (2, 11),
+            (7, 6),
+            (6, 20),
+            (20, 6),
+            (8, 17),
+            (17, 9),
+            (9, 16),
+            (16, 26),
+            (26, 15),
+            (15, 10),
+            (10, 14),
+            (14, 27),
+            (23, 24),
+        ],
+    );
+    let sccs: MaxReachedSccs = Sccs::new_with_annotation(&graph, |w| match w {
+        22 => MaxReached(1),
+        24 => MaxReached(2),
+        27 => MaxReached(2),
+        _ => MaxReached(0),
+    });
+
+    assert_eq!(sccs.annotation(sccs.scc(2)), 0);
+    assert_eq!(sccs.annotation(sccs.scc(7)), 0);
+    assert_eq!(sccs.annotation(sccs.scc(8)), 2);
+    assert_eq!(sccs.annotation(sccs.scc(23)), 2);
+    assert_eq!(sccs.annotation(sccs.scc(3)), 2);
+    assert_eq!(sccs.annotation(sccs.scc(0)), 2);
+}
+
+#[test]
+fn test_bug_max_zero_stick_shape() {
+    let graph = TestGraph::new(0, &[(0, 1), (1, 2), (2, 3), (3, 2), (3, 4)]);
+
+    let sccs: MaxReachedSccs = Sccs::new_with_annotation(&graph, |w| match w {
+        4 => MaxReached(1),
+        _ => MaxReached(0),
+    });
+
+    assert_eq!(sccs.annotation(sccs.scc(0)), 1);
+    assert_eq!(sccs.annotation(sccs.scc(1)), 1);
+    assert_eq!(sccs.annotation(sccs.scc(2)), 1);
+    assert_eq!(sccs.annotation(sccs.scc(3)), 1);
+    assert_eq!(sccs.annotation(sccs.scc(4)), 1);
+}
+
+#[test]
+fn test_min_max_in() {
+    let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (3, 0), (3, 4), (4, 3), (3, 5)]);
+    let sccs: Sccs<usize, usize, MinMaxIn> =
+        Sccs::new_with_annotation(&graph, |w| MinMaxIn { min: w, max: w });
+
+    assert_eq!(sccs.annotation(sccs.scc(2)).min, 2);
+    assert_eq!(sccs.annotation(sccs.scc(2)).max, 2);
+    assert_eq!(sccs.annotation(sccs.scc(0)).min, 0);
+    assert_eq!(sccs.annotation(sccs.scc(0)).max, 4);
+    assert_eq!(sccs.annotation(sccs.scc(3)).min, 0);
+    assert_eq!(sccs.annotation(sccs.scc(3)).max, 4);
+    assert_eq!(sccs.annotation(sccs.scc(5)).min, 5);
+}
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index 128e9f48ff5..3295a91029e 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -8,9 +8,14 @@ use rustc_session::parse::ParseSess;
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
+pub(crate) const RAW_IDENT_ERR: &str = "`${concat(..)}` currently does not support raw identifiers";
+
 /// A meta-variable expression, for expansions based on properties of meta-variables.
-#[derive(Debug, Clone, PartialEq, Encodable, Decodable)]
+#[derive(Debug, PartialEq, Encodable, Decodable)]
 pub(crate) enum MetaVarExpr {
+    /// Unification of two or more identifiers.
+    Concat(Box<[MetaVarExprConcatElem]>),
+
     /// The number of repetitions of an identifier.
     Count(Ident, usize),
 
@@ -42,6 +47,31 @@ impl MetaVarExpr {
         check_trailing_token(&mut tts, psess)?;
         let mut iter = args.trees();
         let rslt = match ident.as_str() {
+            "concat" => {
+                let mut result = Vec::new();
+                loop {
+                    let is_var = try_eat_dollar(&mut iter);
+                    let element_ident = parse_ident(&mut iter, psess, outer_span)?;
+                    let element = if is_var {
+                        MetaVarExprConcatElem::Var(element_ident)
+                    } else {
+                        MetaVarExprConcatElem::Ident(element_ident)
+                    };
+                    result.push(element);
+                    if iter.look_ahead(0).is_none() {
+                        break;
+                    }
+                    if !try_eat_comma(&mut iter) {
+                        return Err(psess.dcx.struct_span_err(outer_span, "expected comma"));
+                    }
+                }
+                if result.len() < 2 {
+                    return Err(psess
+                        .dcx
+                        .struct_span_err(ident.span, "`concat` must have at least two elements"));
+                }
+                MetaVarExpr::Concat(result.into())
+            }
             "count" => parse_count(&mut iter, psess, ident.span)?,
             "ignore" => {
                 eat_dollar(&mut iter, psess, ident.span)?;
@@ -68,11 +98,21 @@ impl MetaVarExpr {
     pub(crate) fn ident(&self) -> Option<Ident> {
         match *self {
             MetaVarExpr::Count(ident, _) | MetaVarExpr::Ignore(ident) => Some(ident),
-            MetaVarExpr::Index(..) | MetaVarExpr::Len(..) => None,
+            MetaVarExpr::Concat { .. } | MetaVarExpr::Index(..) | MetaVarExpr::Len(..) => None,
         }
     }
 }
 
+#[derive(Debug, Decodable, Encodable, PartialEq)]
+pub(crate) enum MetaVarExprConcatElem {
+    /// There is NO preceding dollar sign, which means that this identifier should be interpreted
+    /// as a literal.
+    Ident(Ident),
+    /// There is a preceding dollar sign, which means that this identifier should be expanded
+    /// and interpreted as a variable.
+    Var(Ident),
+}
+
 // Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
 fn check_trailing_token<'psess>(
     iter: &mut RefTokenTreeCursor<'_>,
@@ -138,26 +178,30 @@ fn parse_depth<'psess>(
 fn parse_ident<'psess>(
     iter: &mut RefTokenTreeCursor<'_>,
     psess: &'psess ParseSess,
-    span: Span,
+    fallback_span: Span,
 ) -> PResult<'psess, Ident> {
-    if let Some(tt) = iter.next()
-        && let TokenTree::Token(token, _) = tt
-    {
-        if let Some((elem, IdentIsRaw::No)) = token.ident() {
-            return Ok(elem);
+    let Some(tt) = iter.next() else {
+        return Err(psess.dcx.struct_span_err(fallback_span, "expected identifier"));
+    };
+    let TokenTree::Token(token, _) = tt else {
+        return Err(psess.dcx.struct_span_err(tt.span(), "expected identifier"));
+    };
+    if let Some((elem, is_raw)) = token.ident() {
+        if let IdentIsRaw::Yes = is_raw {
+            return Err(psess.dcx.struct_span_err(elem.span, RAW_IDENT_ERR));
         }
-        let token_str = pprust::token_to_string(token);
-        let mut err =
-            psess.dcx.struct_span_err(span, format!("expected identifier, found `{}`", &token_str));
-        err.span_suggestion(
-            token.span,
-            format!("try removing `{}`", &token_str),
-            "",
-            Applicability::MaybeIncorrect,
-        );
-        return Err(err);
+        return Ok(elem);
     }
-    Err(psess.dcx.struct_span_err(span, "expected identifier"))
+    let token_str = pprust::token_to_string(token);
+    let mut err =
+        psess.dcx.struct_span_err(token.span, format!("expected identifier, found `{token_str}`"));
+    err.span_suggestion(
+        token.span,
+        format!("try removing `{token_str}`"),
+        "",
+        Applicability::MaybeIncorrect,
+    );
+    Err(err)
 }
 
 /// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
@@ -170,6 +214,17 @@ fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool {
     false
 }
 
+/// Tries to move the iterator forward returning `true` if there is a dollar sign. If not, then the
+/// iterator is not modified and the result is `false`.
+fn try_eat_dollar(iter: &mut RefTokenTreeCursor<'_>) -> bool {
+    if let Some(TokenTree::Token(token::Token { kind: token::Dollar, .. }, _)) = iter.look_ahead(0)
+    {
+        let _ = iter.next();
+        return true;
+    }
+    false
+}
+
 /// Expects that the next item is a dollar sign.
 fn eat_dollar<'psess>(
     iter: &mut RefTokenTreeCursor<'_>,
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index 8ad7cb15c92..74f78c0ef78 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -155,6 +155,13 @@ fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &Session, sp
     }
 }
 
+fn maybe_emit_macro_metavar_expr_concat_feature(features: &Features, sess: &Session, span: Span) {
+    if !features.macro_metavar_expr_concat {
+        let msg = "the `concat` meta-variable expression is unstable";
+        feature_err(sess, sym::macro_metavar_expr_concat, span, msg).emit();
+    }
+}
+
 /// Takes a `tokenstream::TokenTree` and returns a `self::TokenTree`. Specifically, this takes a
 /// generic `TokenTree`, such as is used in the rest of the compiler, and returns a `TokenTree`
 /// for use in parsing a macro.
@@ -217,11 +224,19 @@ fn parse_tree<'a>(
                                         return TokenTree::token(token::Dollar, dollar_span);
                                     }
                                     Ok(elem) => {
-                                        maybe_emit_macro_metavar_expr_feature(
-                                            features,
-                                            sess,
-                                            delim_span.entire(),
-                                        );
+                                        if let MetaVarExpr::Concat(_) = elem {
+                                            maybe_emit_macro_metavar_expr_concat_feature(
+                                                features,
+                                                sess,
+                                                delim_span.entire(),
+                                            );
+                                        } else {
+                                            maybe_emit_macro_metavar_expr_feature(
+                                                features,
+                                                sess,
+                                                delim_span.entire(),
+                                            );
+                                        }
                                         return TokenTree::MetaVarExpr(delim_span, elem);
                                     }
                                 }
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 25e961d6009..914bd03675a 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -3,18 +3,19 @@ use crate::errors::{
     NoSyntaxVarsExprRepeat, VarStillRepeating,
 };
 use crate::mbe::macro_parser::{NamedMatch, NamedMatch::*};
+use crate::mbe::metavar_expr::{MetaVarExprConcatElem, RAW_IDENT_ERR};
 use crate::mbe::{self, KleeneOp, MetaVarExpr};
 use rustc_ast::mut_visit::{self, MutVisitor};
+use rustc_ast::token::IdentIsRaw;
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, Diag, DiagCtxt, PResult};
 use rustc_parse::parser::ParseNtResult;
+use rustc_session::parse::ParseSess;
 use rustc_span::hygiene::{LocalExpnId, Transparency};
 use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
-use rustc_span::{with_metavar_spans, Span, SyntaxContext};
-
-use rustc_session::parse::ParseSess;
+use rustc_span::{with_metavar_spans, Span, Symbol, SyntaxContext};
 use smallvec::{smallvec, SmallVec};
 use std::mem;
 
@@ -30,7 +31,7 @@ impl MutVisitor for Marker {
         // it's some advanced case with macro-generated macros. So if we cache the marked version
         // of that context once, we'll typically have a 100% cache hit rate after that.
         let Marker(expn_id, transparency, ref mut cache) = *self;
-        span.update_ctxt(|ctxt| {
+        *span = span.map_ctxt(|ctxt| {
             *cache
                 .entry(ctxt)
                 .or_insert_with(|| ctxt.apply_mark(expn_id.to_expn_id(), transparency))
@@ -675,6 +676,23 @@ fn transcribe_metavar_expr<'a>(
         span
     };
     match *expr {
+        MetaVarExpr::Concat(ref elements) => {
+            let mut concatenated = String::new();
+            for element in elements.into_iter() {
+                let string = match element {
+                    MetaVarExprConcatElem::Ident(ident) => ident.to_string(),
+                    MetaVarExprConcatElem::Var(ident) => extract_ident(dcx, *ident, interp)?,
+                };
+                concatenated.push_str(&string);
+            }
+            // The current implementation marks the span as coming from the macro regardless of
+            // contexts of the concatenated identifiers but this behavior may change in the
+            // future.
+            result.push(TokenTree::Token(
+                Token::from_ast_ident(Ident::new(Symbol::intern(&concatenated), visited_span())),
+                Spacing::Alone,
+            ));
+        }
         MetaVarExpr::Count(original_ident, depth) => {
             let matched = matched_from_ident(dcx, original_ident, interp)?;
             let count = count_repetitions(dcx, depth, matched, repeats, sp)?;
@@ -709,3 +727,33 @@ fn transcribe_metavar_expr<'a>(
     }
     Ok(())
 }
+
+/// Extracts an identifier that can be originated from a `$var:ident` variable or from a token tree.
+fn extract_ident<'a>(
+    dcx: &'a DiagCtxt,
+    ident: Ident,
+    interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
+) -> PResult<'a, String> {
+    if let NamedMatch::MatchedSingle(pnr) = matched_from_ident(dcx, ident, interp)? {
+        if let ParseNtResult::Ident(nt_ident, is_raw) = pnr {
+            if let IdentIsRaw::Yes = is_raw {
+                return Err(dcx.struct_span_err(ident.span, RAW_IDENT_ERR));
+            }
+            return Ok(nt_ident.to_string());
+        }
+        if let ParseNtResult::Tt(TokenTree::Token(
+            Token { kind: TokenKind::Ident(token_ident, is_raw), .. },
+            _,
+        )) = pnr
+        {
+            if let IdentIsRaw::Yes = is_raw {
+                return Err(dcx.struct_span_err(ident.span, RAW_IDENT_ERR));
+            }
+            return Ok(token_ident.to_string());
+        }
+    }
+    Err(dcx.struct_span_err(
+        ident.span,
+        "`${concat(..)}` currently only accepts identifiers or meta-variables as parameters",
+    ))
+}
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 7c76392858c..ef141c7c25e 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -139,7 +139,7 @@ declare_features! (
     /// Allows `crate` in paths.
     (accepted, crate_in_paths, "1.30.0", Some(45477)),
     /// Allows users to provide classes for fenced code block using `class:classname`.
-    (accepted, custom_code_classes_in_docs, "CURRENT_RUSTC_VERSION", Some(79483)),
+    (accepted, custom_code_classes_in_docs, "1.80.0", Some(79483)),
     /// Allows using `#[debugger_visualizer]` attribute.
     (accepted, debugger_visualizer, "1.71.0", Some(95939)),
     /// Allows rustc to inject a default alloc_error_handler
@@ -165,7 +165,7 @@ declare_features! (
     /// Allows using `dyn Trait` as a syntax for trait objects.
     (accepted, dyn_trait, "1.27.0", Some(44662)),
     /// Allows `X..Y` patterns.
-    (accepted, exclusive_range_pattern, "CURRENT_RUSTC_VERSION", Some(37854)),
+    (accepted, exclusive_range_pattern, "1.80.0", Some(37854)),
     /// Allows integer match exhaustiveness checking (RFC 2591).
     (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907)),
     /// Allows explicit generic arguments specification with `impl Trait` present.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 2410019868a..58832cb1087 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -457,7 +457,7 @@ declare_features! (
     /// Allows explicit tail calls via `become` expression.
     (incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
     /// Uses 2024 rules for matching `expr` fragments in macros. Also enables `expr_2021` fragment.
-    (incomplete, expr_fragment_specifier_2024, "CURRENT_RUSTC_VERSION", Some(123742)),
+    (incomplete, expr_fragment_specifier_2024, "1.80.0", Some(123742)),
     /// Allows using `efiapi`, `sysv64` and `win64` as calling convention
     /// for functions with varargs.
     (unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
@@ -488,7 +488,7 @@ declare_features! (
     /// Allows generic parameters and where-clauses on free & associated const items.
     (incomplete, generic_const_items, "1.73.0", Some(113521)),
     /// Allows registering static items globally, possibly across crates, to iterate over at runtime.
-    (unstable, global_registration, "CURRENT_RUSTC_VERSION", Some(125119)),
+    (unstable, global_registration, "1.80.0", Some(125119)),
     /// Allows using `..=X` as a patterns in slices.
     (unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)),
     /// Allows `if let` guard in match arms.
@@ -516,6 +516,8 @@ declare_features! (
     (unstable, lint_reasons, "1.31.0", Some(54503)),
     /// Give access to additional metadata about declarative macro meta-variables.
     (unstable, macro_metavar_expr, "1.61.0", Some(83527)),
+    /// Provides a way to concatenate identifiers using metavariable expressions.
+    (unstable, macro_metavar_expr_concat, "CURRENT_RUSTC_VERSION", Some(124225)),
     /// Allows `#[marker]` on certain traits allowing overlapping implementations.
     (unstable, marker_trait_attr, "1.30.0", Some(29864)),
     /// Allows exhaustive pattern matching on types that contain uninhabited types in cases that are
@@ -581,7 +583,7 @@ declare_features! (
     (unstable, repr_simd, "1.4.0", Some(27731)),
     /// Allows enums like Result<T, E> to be used across FFI, if T's niche value can
     /// be used to describe E or vise-versa.
-    (unstable, result_ffi_guarantees, "CURRENT_RUSTC_VERSION", Some(110503)),
+    (unstable, result_ffi_guarantees, "1.80.0", Some(110503)),
     /// Allows bounding the return type of AFIT/RPITIT.
     (incomplete, return_type_notation, "1.70.0", Some(109417)),
     /// Allows `extern "rust-cold"`.
@@ -623,9 +625,9 @@ declare_features! (
     /// Allows unnamed fields of struct and union type
     (incomplete, unnamed_fields, "1.74.0", Some(49804)),
     /// Allows unsafe attributes.
-    (unstable, unsafe_attributes, "CURRENT_RUSTC_VERSION", Some(123757)),
+    (unstable, unsafe_attributes, "1.80.0", Some(123757)),
     /// Allows unsafe on extern declarations and safety qualifiers over internal items.
-    (unstable, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)),
+    (unstable, unsafe_extern_blocks, "1.80.0", Some(123743)),
     /// Allows unsized fn parameters.
     (unstable, unsized_fn_params, "1.49.0", Some(48055)),
     /// Allows unsized rvalues at arguments and parameters.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 042894beec2..d4a22c4c31f 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1633,6 +1633,13 @@ pub struct ConstBlock {
 }
 
 /// An expression.
+///
+/// For more details, see the [rust lang reference].
+/// Note that the reference does not document nightly-only features.
+/// There may be also slight differences in the names and representation of AST nodes between
+/// the compiler and the reference.
+///
+/// [rust lang reference]: https://doc.rust-lang.org/reference/expressions.html
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct Expr<'hir> {
     pub hir_id: HirId,
@@ -2464,6 +2471,15 @@ pub enum AssocItemConstraintKind<'hir> {
     Bound { bounds: &'hir [GenericBound<'hir>] },
 }
 
+impl<'hir> AssocItemConstraintKind<'hir> {
+    pub fn descr(&self) -> &'static str {
+        match self {
+            AssocItemConstraintKind::Equality { .. } => "binding",
+            AssocItemConstraintKind::Bound { .. } => "constraint",
+        }
+    }
+}
+
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct Ty<'hir> {
     pub hir_id: HirId,
@@ -3147,6 +3163,13 @@ impl ItemId {
 /// An item
 ///
 /// The name might be a dummy name in case of anonymous items
+///
+/// For more details, see the [rust lang reference].
+/// Note that the reference does not document nightly-only features.
+/// There may be also slight differences in the names and representation of AST nodes between
+/// the compiler and the reference.
+///
+/// [rust lang reference]: https://doc.rust-lang.org/reference/items.html
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct Item<'hir> {
     pub ident: Ident,
@@ -3749,6 +3772,21 @@ impl<'hir> Node<'hir> {
         }
     }
 
+    /// Get a `hir::Impl` if the node is an impl block for the given `trait_def_id`.
+    pub fn impl_block_of_trait(self, trait_def_id: DefId) -> Option<&'hir Impl<'hir>> {
+        match self {
+            Node::Item(Item { kind: ItemKind::Impl(impl_block), .. })
+                if impl_block
+                    .of_trait
+                    .and_then(|trait_ref| trait_ref.trait_def_id())
+                    .is_some_and(|trait_id| trait_id == trait_def_id) =>
+            {
+                Some(impl_block)
+            }
+            _ => None,
+        }
+    }
+
     pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> {
         match self {
             Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index c3ccba487ed..69461957f80 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -244,7 +244,9 @@ language_item_table! {
     AsyncIterator,           sym::async_iterator,      async_iterator_trait,       Target::Trait,          GenericRequirement::Exact(0);
 
     CoroutineState,          sym::coroutine_state,     coroutine_state,            Target::Enum,           GenericRequirement::None;
-    Coroutine,               sym::coroutine,           coroutine_trait,            Target::Trait,          GenericRequirement::Minimum(1);
+    Coroutine,               sym::coroutine,           coroutine_trait,            Target::Trait,          GenericRequirement::Exact(1);
+    CoroutineReturn,         sym::coroutine_return,    coroutine_return,           Target::AssocTy,        GenericRequirement::Exact(1);
+    CoroutineYield,          sym::coroutine_yield,     coroutine_yield,            Target::AssocTy,        GenericRequirement::Exact(1);
     CoroutineResume,         sym::coroutine_resume,    coroutine_resume,           Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
 
     Unpin,                   sym::unpin,               unpin_trait,                Target::Trait,          GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index 38ecd7dd082..7f0d72b3a8d 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -53,7 +53,7 @@ impl<'tcx> Bounds<'tcx> {
             span,
         );
         // FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands.
-        if tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
+        if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) {
             self.clauses.insert(0, clause);
         } else {
             self.clauses.push(clause);
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 2672614a895..2e965c59ebb 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -1,6 +1,6 @@
 use rustc_ast::InlineAsmTemplatePiece;
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_hir as hir;
+use rustc_hir::{self as hir, LangItem};
 use rustc_middle::bug;
 use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
 use rustc_session::lint;
@@ -62,8 +62,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
             ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Some(InlineAsmType::I64),
             ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Some(InlineAsmType::I128),
             ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(asm_ty_isize),
+            ty::Float(FloatTy::F16) => Some(InlineAsmType::F16),
             ty::Float(FloatTy::F32) => Some(InlineAsmType::F32),
             ty::Float(FloatTy::F64) => Some(InlineAsmType::F64),
+            ty::Float(FloatTy::F128) => Some(InlineAsmType::F128),
             ty::FnPtr(_) => Some(asm_ty_isize),
             ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Some(asm_ty_isize),
             ty::Adt(adt, args) if adt.repr().simd() => {
@@ -105,8 +107,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                             width => bug!("unsupported pointer width: {width}"),
                         })
                     }
+                    ty::Float(FloatTy::F16) => Some(InlineAsmType::VecF16(size)),
                     ty::Float(FloatTy::F32) => Some(InlineAsmType::VecF32(size)),
                     ty::Float(FloatTy::F64) => Some(InlineAsmType::VecF64(size)),
+                    ty::Float(FloatTy::F128) => Some(InlineAsmType::VecF128(size)),
                     _ => None,
                 }
             }
@@ -134,7 +138,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
             // `!` is allowed for input but not for output (issue #87802)
             ty::Never if is_input => return None,
             _ if ty.references_error() => return None,
-            ty::Adt(adt, args) if Some(adt.did()) == self.tcx.lang_items().maybe_uninit() => {
+            ty::Adt(adt, args) if self.tcx.is_lang_item(adt.did(), LangItem::MaybeUninit) => {
                 let fields = &adt.non_enum_variant().fields;
                 let ty = fields[FieldIdx::from_u32(1)].ty(self.tcx, args);
                 // FIXME: Are we just trying to map to the `T` in `MaybeUninit<T>`?
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index eae41d28e89..e9961d3ad08 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -8,6 +8,7 @@
 use crate::errors;
 use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::LangItem;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_session::parse::feature_err;
@@ -49,7 +50,7 @@ fn enforce_trait_manually_implementable(
 ) -> Result<(), ErrorGuaranteed> {
     let impl_header_span = tcx.def_span(impl_def_id);
 
-    if tcx.lang_items().freeze_trait() == Some(trait_def_id) {
+    if tcx.is_lang_item(trait_def_id, LangItem::Freeze) {
         if !tcx.features().freeze_impls {
             feature_err(
                 &tcx.sess,
@@ -75,7 +76,7 @@ fn enforce_trait_manually_implementable(
 
         // Maintain explicit error code for `Unsize`, since it has a useful
         // explanation about using `CoerceUnsized` instead.
-        if Some(trait_def_id) == tcx.lang_items().unsize_trait() {
+        if tcx.is_lang_item(trait_def_id, LangItem::Unsize) {
             err.code(E0328);
         }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 40204961e9c..3421c8da4e9 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -169,12 +169,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
         predicates.insert((trait_ref.upcast(tcx), tcx.def_span(def_id)));
     }
 
-    // Collect the predicates that were written inline by the user on each
-    // type parameter (e.g., `<T: Foo>`). Also add `ConstArgHasType` predicates
-    // for each const parameter.
+    // Add implicit predicates that should be treated as if the user has written them,
+    // including the implicit `T: Sized` for all generic parameters, and `ConstArgHasType`
+    // for const params.
     for param in hir_generics.params {
         match param.kind {
-            // We already dealt with early bound lifetimes above.
             GenericParamKind::Lifetime { .. } => (),
             GenericParamKind::Type { .. } => {
                 let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
@@ -204,7 +203,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     }
 
     trace!(?predicates);
-    // Add in the bounds that appear in the where-clause.
+    // Add inline `<T: Foo>` bounds and bounds in the where clause.
     for predicate in hir_generics.predicates {
         match predicate {
             hir::WherePredicate::BoundPredicate(bound_pred) => {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 3a9ef244fd3..2d240699105 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -1217,7 +1217,6 @@ pub fn prohibit_assoc_item_constraint(
     // otherwise suggest the removal of the binding.
     if let Some((def_id, segment, _)) = segment
         && segment.args().parenthesized == hir::GenericArgsParentheses::No
-        && let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
     {
         // Suggests removal of the offending binding
         let suggest_removal = |e: &mut Diag<'_>| {
@@ -1263,7 +1262,7 @@ pub fn prohibit_assoc_item_constraint(
             if let Ok(suggestion) = tcx.sess.source_map().span_to_snippet(removal_span) {
                 e.span_suggestion_verbose(
                     removal_span,
-                    "consider removing this associated item binding",
+                    format!("consider removing this associated item {}", constraint.kind.descr()),
                     suggestion,
                     Applicability::MaybeIncorrect,
                 );
@@ -1286,19 +1285,73 @@ pub fn prohibit_assoc_item_constraint(
         // Check if the type has a generic param with the same name
         // as the assoc type name in the associated item binding.
         let generics = tcx.generics_of(def_id);
-        let matching_param =
-            generics.own_params.iter().find(|p| p.name.as_str() == constraint.ident.as_str());
+        let matching_param = generics.own_params.iter().find(|p| p.name == constraint.ident.name);
 
         // Now emit the appropriate suggestion
         if let Some(matching_param) = matching_param {
-            match (&matching_param.kind, term) {
-                (GenericParamDefKind::Type { .. }, hir::Term::Ty(ty)) => {
-                    suggest_direct_use(&mut err, ty.span);
-                }
-                (GenericParamDefKind::Const { .. }, hir::Term::Const(c)) => {
+            match (constraint.kind, &matching_param.kind) {
+                (
+                    hir::AssocItemConstraintKind::Equality { term: hir::Term::Ty(ty) },
+                    GenericParamDefKind::Type { .. },
+                ) => suggest_direct_use(&mut err, ty.span),
+                (
+                    hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) },
+                    GenericParamDefKind::Const { .. },
+                ) => {
                     let span = tcx.hir().span(c.hir_id);
                     suggest_direct_use(&mut err, span);
                 }
+                (hir::AssocItemConstraintKind::Bound { bounds }, _) => {
+                    // Suggest `impl<T: Bound> Trait<T> for Foo` when finding
+                    // `impl Trait<T: Bound> for Foo`
+
+                    // Get the parent impl block based on the binding we have
+                    // and the trait DefId
+                    let impl_block = tcx
+                        .hir()
+                        .parent_iter(constraint.hir_id)
+                        .find_map(|(_, node)| node.impl_block_of_trait(def_id));
+
+                    let type_with_constraints =
+                        tcx.sess.source_map().span_to_snippet(constraint.span);
+
+                    if let Some(impl_block) = impl_block
+                        && let Ok(type_with_constraints) = type_with_constraints
+                    {
+                        // Filter out the lifetime parameters because
+                        // they should be declared before the type parameter
+                        let lifetimes: String = bounds
+                            .iter()
+                            .filter_map(|bound| {
+                                if let hir::GenericBound::Outlives(lifetime) = bound {
+                                    Some(format!("{lifetime}, "))
+                                } else {
+                                    None
+                                }
+                            })
+                            .collect();
+                        // Figure out a span and suggestion string based on
+                        // whether there are any existing parameters
+                        let param_decl = if let Some(param_span) =
+                            impl_block.generics.span_for_param_suggestion()
+                        {
+                            (param_span, format!(", {lifetimes}{type_with_constraints}"))
+                        } else {
+                            (
+                                impl_block.generics.span.shrink_to_lo(),
+                                format!("<{lifetimes}{type_with_constraints}>"),
+                            )
+                        };
+                        let suggestions =
+                            vec![param_decl, (constraint.span, format!("{}", matching_param.name))];
+
+                        err.multipart_suggestion_verbose(
+                            format!("declare the type parameter right after the `impl` keyword"),
+                            suggestions,
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                }
                 _ => suggest_removal(&mut err),
             }
         } else {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index 26cabb69d25..3f888c4e272 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -531,6 +531,7 @@ pub(crate) fn check_generic_arg_count(
 
         let num_default_params = expected_max - expected_min;
 
+        let mut all_params_are_binded = false;
         let gen_args_info = if provided > expected_max {
             invalid_args.extend((expected_max..provided).map(|i| i + args_offset));
             let num_redundant_args = provided - expected_max;
@@ -547,6 +548,20 @@ pub(crate) fn check_generic_arg_count(
         } else {
             let num_missing_args = expected_max - provided;
 
+            let constraint_names: Vec<_> =
+                gen_args.constraints.iter().map(|b| b.ident.name).collect();
+            let param_names: Vec<_> = gen_params
+                .own_params
+                .iter()
+                .filter(|param| !has_self || param.index != 0) // Assumes `Self` will always be the first parameter
+                .map(|param| param.name)
+                .collect();
+            if constraint_names == param_names {
+                // We set this to true and delay emitting `WrongNumberOfGenericArgs`
+                // to provide a succinct error for cases like issue #113073
+                all_params_are_binded = true;
+            };
+
             GenericArgsInfo::MissingTypesOrConsts {
                 num_missing_args,
                 num_default_params,
@@ -567,7 +582,7 @@ pub(crate) fn check_generic_arg_count(
                 def_id,
             )
             .diagnostic()
-            .emit()
+            .emit_unless(all_params_are_binded)
         });
 
         Err(reported)
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 6f499947d5c..d6f3f4d640b 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -44,6 +44,10 @@ hir_typeck_convert_using_method = try using `{$sugg}` to convert `{$found}` to `
 
 hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private
 
+hir_typeck_dependency_on_unit_never_type_fallback = this function depends on never type fallback being `()`
+    .note = in edition 2024, the requirement `{$obligation}` will fail
+    .help = specify the types explicitly
+
 hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty`
 
 hir_typeck_expected_default_return_type = expected `()` because of default return type
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index a599e8d05fd..281af80bff5 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -234,7 +234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let ret_ty = ret_coercion.borrow().expected_ty();
                 let ret_ty = self.infcx.shallow_resolve(ret_ty);
                 self.can_coerce(arm_ty, ret_ty)
-                    && prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty))
+                    && prior_arm.is_none_or(|(_, ty, _)| self.can_coerce(ty, ret_ty))
                     // The match arms need to unify for the case of `impl Trait`.
                     && !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..))
             }
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 9736c8b8920..46c85515575 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -5,9 +5,9 @@ use super::{Expectation, FnCtxt, TupleArgumentsFlag};
 use crate::errors;
 use rustc_ast::util::parser::PREC_POSTFIX;
 use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
-use rustc_hir as hir;
 use rustc_hir::def::{self, CtorKind, Namespace, Res};
 use rustc_hir::def_id::DefId;
+use rustc_hir::{self as hir, LangItem};
 use rustc_hir_analysis::autoderef::Autoderef;
 use rustc_infer::traits::ObligationCauseCode;
 use rustc_infer::{
@@ -41,7 +41,7 @@ pub fn check_legal_trait_for_method_call(
     trait_id: DefId,
     body_id: DefId,
 ) -> Result<(), ErrorGuaranteed> {
-    if tcx.lang_items().drop_trait() == Some(trait_id)
+    if tcx.is_lang_item(trait_id, LangItem::Drop)
         && tcx.lang_items().fallback_surface_drop_fn() != Some(body_id)
     {
         let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
@@ -628,7 +628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return;
             };
 
-            let pick = self.confirm_method(
+            let pick = self.confirm_method_for_diagnostic(
                 call_expr.span,
                 callee_expr,
                 call_expr,
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index e54a07786cd..fcd22b74676 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -913,7 +913,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 if self
                     .tcx
                     .upvars_mentioned(closure_def_id_a.expect_local())
-                    .map_or(true, |u| u.is_empty()) =>
+                    .is_none_or(|u| u.is_empty()) =>
             {
                 // We coerce the closure, which has fn type
                 //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index d2a5924c8bb..f9720c9c307 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -4,7 +4,7 @@ use rustc_errors::{Applicability, Diag};
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::intravisit::Visitor;
-use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
+use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_middle::bug;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
@@ -166,7 +166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Requires that the two types unify, and prints an error message if
     /// they don't.
     pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
-        if let Some(e) = self.demand_suptype_diag(sp, expected, actual) {
+        if let Err(e) = self.demand_suptype_diag(sp, expected, actual) {
             e.emit();
         }
     }
@@ -176,7 +176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         sp: Span,
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
-    ) -> Option<Diag<'tcx>> {
+    ) -> Result<(), Diag<'tcx>> {
         self.demand_suptype_with_origin(&self.misc(sp), expected, actual)
     }
 
@@ -186,18 +186,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         cause: &ObligationCause<'tcx>,
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
-    ) -> Option<Diag<'tcx>> {
-        match self.at(cause, self.param_env).sup(DefineOpaqueTypes::Yes, expected, actual) {
-            Ok(InferOk { obligations, value: () }) => {
-                self.register_predicates(obligations);
-                None
-            }
-            Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)),
-        }
+    ) -> Result<(), Diag<'tcx>> {
+        self.at(cause, self.param_env)
+            .sup(DefineOpaqueTypes::Yes, expected, actual)
+            .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
+            .map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e))
     }
 
     pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
-        if let Some(err) = self.demand_eqtype_diag(sp, expected, actual) {
+        if let Err(err) = self.demand_eqtype_diag(sp, expected, actual) {
             err.emit();
         }
     }
@@ -207,7 +204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         sp: Span,
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
-    ) -> Option<Diag<'tcx>> {
+    ) -> Result<(), Diag<'tcx>> {
         self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
     }
 
@@ -216,14 +213,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         cause: &ObligationCause<'tcx>,
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
-    ) -> Option<Diag<'tcx>> {
-        match self.at(cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, actual) {
-            Ok(InferOk { obligations, value: () }) => {
-                self.register_predicates(obligations);
-                None
-            }
-            Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)),
-        }
+    ) -> Result<(), Diag<'tcx>> {
+        self.at(cause, self.param_env)
+            .eq(DefineOpaqueTypes::Yes, expected, actual)
+            .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
+            .map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e))
     }
 
     pub fn demand_coerce(
@@ -234,12 +228,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
         allow_two_phase: AllowTwoPhase,
     ) -> Ty<'tcx> {
-        let (ty, err) =
-            self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase);
-        if let Some(err) = err {
-            err.emit();
+        match self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase)
+        {
+            Ok(ty) => ty,
+            Err(err) => {
+                err.emit();
+                // Return the original type instead of an error type here, otherwise the type of `x` in
+                // `let x: u32 = ();` will be a type error, causing all subsequent usages of `x` to not
+                // report errors, even though `x` is definitely `u32`.
+                expected
+            }
         }
-        ty
     }
 
     /// Checks that the type of `expr` can be coerced to `expected`.
@@ -254,11 +253,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
         allow_two_phase: AllowTwoPhase,
-    ) -> (Ty<'tcx>, Option<Diag<'tcx>>) {
+    ) -> Result<Ty<'tcx>, Diag<'tcx>> {
         let expected = self.resolve_vars_with_obligations(expected);
 
         let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
-            Ok(ty) => return (ty, None),
+            Ok(ty) => return Ok(ty),
             Err(e) => e,
         };
 
@@ -275,7 +274,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
 
-        (expected, Some(err))
+        Err(err)
     }
 
     /// Notes the point at which a variable is constrained to some type incompatible
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 3f12f252654..24f039b8e90 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -7,7 +7,7 @@ use rustc_errors::{
     SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
-use rustc_middle::ty::Ty;
+use rustc_middle::ty::{self, Ty};
 use rustc_span::{
     edition::{Edition, LATEST_STABLE_EDITION},
     symbol::Ident,
@@ -183,6 +183,15 @@ pub enum NeverTypeFallbackFlowingIntoUnsafe {
     Deref,
 }
 
+#[derive(LintDiagnostic)]
+#[help]
+#[diag(hir_typeck_dependency_on_unit_never_type_fallback)]
+pub struct DependencyOnUnitNeverTypeFallback<'tcx> {
+    #[note]
+    pub obligation_span: Span,
+    pub obligation: ty::Predicate<'tcx>,
+}
+
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(
     hir_typeck_add_missing_parentheses_in_range,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 5b27ebe3416..fe497498c4b 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -87,7 +87,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty = adj_ty;
         }
 
-        if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
+        if let Err(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
             let _ = self.emit_type_mismatch_suggestions(
                 &mut err,
                 expr.peel_drop_temps(),
@@ -1132,7 +1132,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
             // The likely cause of this is `if foo = bar { .. }`.
             let actual_ty = self.tcx.types.unit;
-            let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap();
+            let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap_err();
             let lhs_ty = self.check_expr(lhs);
             let rhs_ty = self.check_expr(rhs);
             let refs_can_coerce = |lhs: Ty<'tcx>, rhs: Ty<'tcx>| {
@@ -1236,7 +1236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // This is (basically) inlined `check_expr_coercible_to_type`, but we want
         // to suggest an additional fixup here in `suggest_deref_binop`.
         let rhs_ty = self.check_expr_with_hint(rhs, lhs_ty);
-        if let (_, Some(mut diag)) =
+        if let Err(mut diag) =
             self.demand_coerce_diag(rhs, rhs_ty, lhs_ty, Some(lhs), AllowTwoPhase::No)
         {
             suggest_deref_binop(&mut diag, rhs_ty);
@@ -1342,14 +1342,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Ok(method)
             }
             Err(error) => {
-                if segment.ident.name != kw::Empty {
-                    if let Some(err) =
-                        self.report_method_error(expr.hir_id, rcvr_t, error, expected, false)
-                    {
-                        err.emit();
-                    }
+                if segment.ident.name == kw::Empty {
+                    span_bug!(rcvr.span, "empty method name")
+                } else {
+                    Err(self.report_method_error(expr.hir_id, rcvr_t, error, expected, false))
                 }
-                Err(())
             }
         };
 
@@ -1560,7 +1557,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
         // don't copy that one element, we move it. Only check for Copy if the length is larger.
-        if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
+        if count.try_eval_target_usize(tcx, self.param_env).is_none_or(|len| len > 1) {
             let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
             let code = traits::ObligationCauseCode::RepeatElementCopy {
                 is_constable,
@@ -1741,10 +1738,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Make sure to give a type to the field even if there's
             // an error, so we can continue type-checking.
             let ty = self.check_expr_with_hint(field.expr, field_type);
-            let (_, diag) =
-                self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);
+            let diag = self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);
 
-            if let Some(diag) = diag {
+            if let Err(diag) = diag {
                 if idx == hir_fields.len() - 1 {
                     if remaining_fields.is_empty() {
                         self.suggest_fru_from_range_and_emit(field, variant, args, diag);
@@ -3154,7 +3150,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 error.obligation.predicate.kind().skip_binder(),
             ) {
                 (ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)), _)
-                    if self.tcx.lang_items().index_trait() == Some(predicate.trait_ref.def_id) =>
+                    if self.tcx.is_lang_item(predicate.trait_ref.def_id, LangItem::Index) =>
                 {
                     seen_preds.insert(error.obligation.predicate.kind().skip_binder());
                 }
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index 5ba67c52ef2..3cecbfd4275 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -14,6 +14,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
 use rustc_session::lint;
 use rustc_span::DUMMY_SP;
 use rustc_span::{def_id::LocalDefId, Span};
+use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
 
 #[derive(Copy, Clone)]
 pub enum DivergingFallbackBehavior {
@@ -344,6 +345,9 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         // `!`.
         let mut diverging_fallback = UnordMap::with_capacity(diverging_vids.len());
         let unsafe_infer_vars = OnceCell::new();
+
+        self.lint_obligations_broken_by_never_type_fallback_change(behavior, &diverging_vids);
+
         for &diverging_vid in &diverging_vids {
             let diverging_ty = Ty::new_var(self.tcx, diverging_vid);
             let root_vid = self.root_var(diverging_vid);
@@ -468,6 +472,56 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         }
     }
 
+    fn lint_obligations_broken_by_never_type_fallback_change(
+        &self,
+        behavior: DivergingFallbackBehavior,
+        diverging_vids: &[ty::TyVid],
+    ) {
+        let DivergingFallbackBehavior::ToUnit = behavior else { return };
+
+        // Fallback happens if and only if there are diverging variables
+        if diverging_vids.is_empty() {
+            return;
+        }
+
+        // Returns errors which happen if fallback is set to `fallback`
+        let remaining_errors_if_fallback_to = |fallback| {
+            self.probe(|_| {
+                let obligations = self.fulfillment_cx.borrow().pending_obligations();
+                let ocx = ObligationCtxt::new_with_diagnostics(&self.infcx);
+                ocx.register_obligations(obligations.iter().cloned());
+
+                for &diverging_vid in diverging_vids {
+                    let diverging_ty = Ty::new_var(self.tcx, diverging_vid);
+
+                    ocx.eq(&ObligationCause::dummy(), self.param_env, diverging_ty, fallback)
+                        .expect("expected diverging var to be unconstrained");
+                }
+
+                ocx.select_where_possible()
+            })
+        };
+
+        // If we have no errors with `fallback = ()`, but *do* have errors with `fallback = !`,
+        // then this code will be broken by the never type fallback change.qba
+        let unit_errors = remaining_errors_if_fallback_to(self.tcx.types.unit);
+        if unit_errors.is_empty()
+            && let mut never_errors = remaining_errors_if_fallback_to(self.tcx.types.never)
+            && let [ref mut never_error, ..] = never_errors.as_mut_slice()
+        {
+            self.adjust_fulfillment_error_for_expr_obligation(never_error);
+            self.tcx.emit_node_span_lint(
+                lint::builtin::DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK,
+                self.tcx.local_def_id_to_hir_id(self.body_id),
+                self.tcx.def_span(self.body_id),
+                errors::DependencyOnUnitNeverTypeFallback {
+                    obligation_span: never_error.obligation.cause.span,
+                    obligation: never_error.obligation.predicate,
+                },
+            )
+        }
+    }
+
     /// Returns a graph whose nodes are (unresolved) inference variables and where
     /// an edge `?A -> ?B` indicates that the variable `?A` is coerced to `?B`.
     fn create_coercion_graph(&self) -> VecGraph<ty::TyVid, true> {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index e354e1ec59c..9531c002829 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -660,8 +660,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         })
     }
 
-    pub(crate) fn err_args(&self, len: usize) -> Vec<Ty<'tcx>> {
-        let ty_error = Ty::new_misc_error(self.tcx);
+    pub(crate) fn err_args(&self, len: usize, guar: ErrorGuaranteed) -> Vec<Ty<'tcx>> {
+        let ty_error = Ty::new_error(self.tcx, guar);
         vec![ty_error; len]
     }
 
@@ -846,15 +846,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
 
                 if item_name.name != kw::Empty {
-                    if let Some(e) = self.report_method_error(
+                    self.report_method_error(
                         hir_id,
                         ty.normalized,
                         error,
                         Expectation::NoExpectation,
                         trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021
-                    ) {
-                        e.emit();
-                    }
+                    );
                 }
 
                 result
@@ -1420,7 +1418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args));
             let self_ty = self.normalize(span, self_ty);
             match self.at(&self.misc(span), self.param_env).eq(
-                DefineOpaqueTypes::No,
+                DefineOpaqueTypes::Yes,
                 impl_ty,
                 self_ty,
             ) {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index b8333d47493..10d9e07db6f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -113,17 +113,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         sp: Span,
         expr: &'tcx hir::Expr<'tcx>,
-        method: Result<MethodCallee<'tcx>, ()>,
+        method: Result<MethodCallee<'tcx>, ErrorGuaranteed>,
         args_no_rcvr: &'tcx [hir::Expr<'tcx>],
         tuple_arguments: TupleArgumentsFlag,
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
         let has_error = match method {
-            Ok(method) => method.args.references_error() || method.sig.references_error(),
-            Err(_) => true,
+            Ok(method) => method.args.error_reported().and(method.sig.error_reported()),
+            Err(guar) => Err(guar),
         };
-        if has_error {
-            let err_inputs = self.err_args(args_no_rcvr.len());
+        if let Err(guar) = has_error {
+            let err_inputs = self.err_args(args_no_rcvr.len(), guar);
 
             let err_inputs = match tuple_arguments {
                 DontTupleArguments => err_inputs,
@@ -140,7 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 tuple_arguments,
                 method.ok().map(|method| method.def_id),
             );
-            return Ty::new_misc_error(self.tcx);
+            return Ty::new_error(self.tcx, guar);
         }
 
         let method = method.unwrap();
@@ -237,7 +237,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 _ => {
                     // Otherwise, there's a mismatch, so clear out what we're expecting, and set
                     // our input types to err_args so we don't blow up the error messages
-                    struct_span_code_err!(
+                    let guar = struct_span_code_err!(
                         tcx.dcx(),
                         call_span,
                         E0059,
@@ -245,7 +245,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                          for the function trait is neither a tuple nor unit"
                     )
                     .emit();
-                    (self.err_args(provided_args.len()), None)
+                    (self.err_args(provided_args.len(), guar), None)
                 }
             }
         } else {
@@ -1578,7 +1578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // type of the place it is referencing, and not some
             // supertype thereof.
             let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
-            if let Some(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
+            if let Err(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
                 self.emit_type_mismatch_suggestions(
                     &mut diag,
                     init.peel_drop_temps(),
@@ -1624,7 +1624,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let previous_diverges = self.diverges.get();
             let else_ty = self.check_block_with_expected(blk, NoExpectation);
             let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
-            if let Some(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
+            if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
             {
                 err.emit();
             }
@@ -2240,7 +2240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             for (idx, (generic_param, param)) in
                 params_with_generics.iter().enumerate().filter(|(idx, _)| {
                     check_for_matched_generics
-                        || expected_idx.map_or(true, |expected_idx| expected_idx == *idx)
+                        || expected_idx.is_none_or(|expected_idx| expected_idx == *idx)
                 })
             {
                 let Some(generic_param) = generic_param else {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 9ab89f3444c..9743dc7c69f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -440,7 +440,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             };
             // Given `Result<_, E>`, check our expected ty is `Result<_, &E>` for
             // `as_ref` and `as_deref` compatibility.
-            let error_tys_equate_as_ref = error_tys.map_or(true, |(found, expected)| {
+            let error_tys_equate_as_ref = error_tys.is_none_or(|(found, expected)| {
                 self.can_eq(
                     self.param_env,
                     Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, found),
@@ -489,10 +489,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
                 return true;
             } else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind()
-                && Some(adt.did()) == self.tcx.lang_items().string()
+                && self.tcx.is_lang_item(adt.did(), LangItem::String)
                 && peeled.is_str()
                 // `Result::map`, conversely, does not take ref of the error type.
-                && error_tys.map_or(true, |(found, expected)| {
+                && error_tys.is_none_or(|(found, expected)| {
                     self.can_eq(self.param_env, found, expected)
                 })
             {
@@ -3147,7 +3147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return;
         }
         if let ty::Adt(adt, _) = expected_ty.kind()
-            && self.tcx.lang_items().range_struct() == Some(adt.did())
+            && self.tcx.is_lang_item(adt.did(), LangItem::Range)
         {
             return;
         }
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index b0fd6de3496..a87ee7b4554 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -4,6 +4,7 @@
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(if_let_guard)]
+#![feature(is_none_or)]
 #![feature(let_chains)]
 #![feature(never_type)]
 #![feature(try_blocks)]
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 3c9a49e91a3..120e3239d1f 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -497,7 +497,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                 args,
             })),
         );
-        match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::No, method_self_ty, self_ty) {
+        match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::Yes, method_self_ty, self_ty) {
             Ok(InferOk { obligations, value: () }) => {
                 self.register_predicates(obligations);
             }
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index e842bba34bf..3986374a343 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -634,8 +634,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) {
-        debug!("assemble_probe: self_ty={:?}", self_ty);
         let raw_self_ty = self_ty.value.value;
         match *raw_self_ty.kind() {
             ty::Dynamic(data, ..) if let Some(p) = data.principal() => {
@@ -713,13 +713,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
         if !self.impl_dups.insert(impl_def_id) {
             return; // already visited
         }
 
-        debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
-
         for item in self.impl_or_trait_item(impl_def_id) {
             if !self.has_applicable_self(&item) {
                 // No receiver declared. Not a candidate.
@@ -737,9 +736,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) {
-        debug!("assemble_inherent_candidates_from_object(self_ty={:?})", self_ty);
-
         let principal = match self_ty.kind() {
             ty::Dynamic(ref data, ..) => Some(data),
             _ => None,
@@ -768,9 +766,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         });
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
         // FIXME: do we want to commit to this behavior for param bounds?
-        debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty);
 
         let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
             let bound_predicate = predicate.kind();
@@ -826,6 +824,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_extension_candidates_for_traits_in_scope(&mut self) {
         let mut duplicates = FxHashSet::default();
         let opt_applicable_traits = self.tcx.in_scope_traits(self.scope_expr_id);
@@ -842,6 +841,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_extension_candidates_for_all_traits(&mut self) {
         let mut duplicates = FxHashSet::default();
         for trait_info in suggest::all_traits(self.tcx) {
@@ -863,12 +863,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn assemble_extension_candidates_for_trait(
         &mut self,
         import_ids: &SmallVec<[LocalDefId; 1]>,
         trait_def_id: DefId,
     ) {
-        debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
         let trait_args = self.fresh_args_for_item(self.span, trait_def_id);
         let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_args);
 
@@ -958,6 +958,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     ///////////////////////////////////////////////////////////////////////////
     // THE ACTUAL SEARCH
 
+    #[instrument(level = "debug", skip(self))]
     fn pick(mut self) -> PickResult<'tcx> {
         assert!(self.method_name.is_some());
 
@@ -1386,6 +1387,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "trace", skip(self, possibly_unsatisfied_predicates), ret)]
     fn consider_probe(
         &self,
         self_ty: Ty<'tcx>,
@@ -1415,15 +1417,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     (xform_self_ty, xform_ret_ty) =
                         self.xform_self_ty(probe.item, impl_ty, impl_args);
                     xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
-                    // FIXME: Make this `ocx.sup` once we define opaques more eagerly.
-                    match self.at(cause, self.param_env).sup(
-                        DefineOpaqueTypes::No,
-                        xform_self_ty,
-                        self_ty,
-                    ) {
-                        Ok(infer_ok) => {
-                            ocx.register_infer_ok_obligations(infer_ok);
-                        }
+                    match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
+                        Ok(()) => {}
                         Err(err) => {
                             debug!("--> cannot relate self-types {:?}", err);
                             return ProbeResult::NoMatch;
@@ -1484,19 +1479,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     (xform_self_ty, xform_ret_ty) =
                         self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
                     xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
-                    // FIXME: Make this `ocx.sup` once we define opaques more eagerly.
-                    match self.at(cause, self.param_env).sup(
-                        DefineOpaqueTypes::No,
-                        xform_self_ty,
-                        self_ty,
-                    ) {
-                        Ok(infer_ok) => {
-                            ocx.register_infer_ok_obligations(infer_ok);
-                        }
-                        Err(err) => {
-                            debug!("--> cannot relate self-types {:?}", err);
+                    match self_ty.kind() {
+                        // HACK: opaque types will match anything for which their bounds hold.
+                        // Thus we need to prevent them from trying to match the `&_` autoref
+                        // candidates that get created for `&self` trait methods.
+                        ty::Alias(ty::Opaque, alias_ty)
+                            if self.infcx.can_define_opaque_ty(alias_ty.def_id)
+                                && !xform_self_ty.is_ty_var() =>
+                        {
                             return ProbeResult::NoMatch;
                         }
+                        _ => match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
+                            Ok(()) => {}
+                            Err(err) => {
+                                debug!("--> cannot relate self-types {:?}", err);
+                                return ProbeResult::NoMatch;
+                            }
+                        },
                     }
                     let obligation = traits::Obligation::new(
                         self.tcx,
@@ -1536,15 +1535,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     (xform_self_ty, xform_ret_ty) =
                         self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
                     xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
-                    // FIXME: Make this `ocx.sup` once we define opaques more eagerly.
-                    match self.at(cause, self.param_env).sup(
-                        DefineOpaqueTypes::No,
-                        xform_self_ty,
-                        self_ty,
-                    ) {
-                        Ok(infer_ok) => {
-                            ocx.register_infer_ok_obligations(infer_ok);
-                        }
+                    match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
+                        Ok(()) => {}
                         Err(err) => {
                             debug!("--> cannot relate self-types {:?}", err);
                             return ProbeResult::NoMatch;
@@ -1665,6 +1657,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     /// Similarly to `probe_for_return_type`, this method attempts to find the best matching
     /// candidate method where the method name may have been misspelled. Similarly to other
     /// edit distance based suggestions, we provide at most one such suggestion.
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn probe_for_similar_candidate(
         &mut self,
     ) -> Result<Option<ty::AssocItem>, MethodError<'tcx>> {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 803d1554324..abbfe452f5f 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -33,7 +33,7 @@ use rustc_middle::ty::IsSuggestable;
 use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::def_id::DefIdSet;
 use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::{edit_distance, ExpnKind, FileName, MacroKind, Span};
+use rustc_span::{edit_distance, ErrorGuaranteed, ExpnKind, FileName, MacroKind, Span};
 use rustc_span::{Symbol, DUMMY_SP};
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
@@ -192,7 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         error: MethodError<'tcx>,
         expected: Expectation<'tcx>,
         trait_missing_method: bool,
-    ) -> Option<Diag<'_>> {
+    ) -> ErrorGuaranteed {
         let (span, sugg_span, source, item_name, args) = match self.tcx.hir_node(call_id) {
             hir::Node::Expr(&hir::Expr {
                 kind: hir::ExprKind::MethodCall(segment, rcvr, args, _),
@@ -226,8 +226,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // Avoid suggestions when we don't know what's going on.
-        if rcvr_ty.references_error() {
-            return None;
+        if let Err(guar) = rcvr_ty.error_reported() {
+            return guar;
         }
 
         match error {
@@ -265,7 +265,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     &mut sources,
                     Some(sugg_span),
                 );
-                err.emit();
+                return err.emit();
             }
 
             MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
@@ -286,7 +286,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .unwrap_or_else(|| self.tcx.def_span(def_id));
                 err.span_label(sp, format!("private {kind} defined here"));
                 self.suggest_valid_traits(&mut err, item_name, out_of_scope_traits, true);
-                err.emit();
+                return err.emit();
             }
 
             MethodError::IllegalSizedBound { candidates, needs_mut, bound_span, self_expr } => {
@@ -343,12 +343,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                 }
-                err.emit();
+                return err.emit();
             }
 
             MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
         }
-        None
     }
 
     fn suggest_missing_writer(&self, rcvr_ty: Ty<'tcx>, rcvr_expr: &hir::Expr<'tcx>) -> Diag<'_> {
@@ -564,7 +563,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    pub fn report_no_match_method_error(
+    fn report_no_match_method_error(
         &self,
         mut span: Span,
         rcvr_ty: Ty<'tcx>,
@@ -576,7 +575,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         no_match_data: &mut NoMatchData<'tcx>,
         expected: Expectation<'tcx>,
         trait_missing_method: bool,
-    ) -> Option<Diag<'_>> {
+    ) -> ErrorGuaranteed {
         let mode = no_match_data.mode;
         let tcx = self.tcx;
         let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
@@ -608,14 +607,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // We could pass the file for long types into these two, but it isn't strictly necessary
         // given how targeted they are.
-        if self.suggest_wrapping_range_with_parens(
+        if let Err(guar) = self.report_failed_method_call_on_range_end(
             tcx,
             rcvr_ty,
             source,
             span,
             item_name,
             &short_ty_str,
-        ) || self.suggest_constraining_numerical_ty(
+        ) {
+            return guar;
+        }
+        if let Err(guar) = self.report_failed_method_call_on_numerical_infer_var(
             tcx,
             rcvr_ty,
             source,
@@ -624,7 +626,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             item_name,
             &short_ty_str,
         ) {
-            return None;
+            return guar;
         }
         span = item_name.span;
 
@@ -881,7 +883,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 vec![(span.shrink_to_lo(), format!("into_iter()."))],
                 Applicability::MaybeIncorrect,
             );
-            return Some(err);
+            return err.emit();
         } else if !unsatisfied_predicates.is_empty() && matches!(rcvr_ty.kind(), ty::Param(_)) {
             // We special case the situation where we are looking for `_` in
             // `<TypeParam as _>::method` because otherwise the machinery will look for blanket
@@ -1100,7 +1102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             unsatisfied_predicates.iter().any(|(pred, _, _)| {
                                 match pred.kind().skip_binder() {
                                     ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
-                                        Some(pred.def_id()) == self.tcx.lang_items().sized_trait()
+                                        self.tcx.is_lang_item(pred.def_id(), LangItem::Sized)
                                             && pred.polarity == ty::PredicatePolarity::Positive
                                     }
                                     _ => false,
@@ -1373,10 +1375,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ty.is_str()
                             || matches!(
                                 ty.kind(),
-                                ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string()
+                                ty::Adt(adt, _) if self.tcx.is_lang_item(adt.did(), LangItem::String)
                             )
                     }
-                    ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(),
+                    ty::Adt(adt, _) => self.tcx.is_lang_item(adt.did(), LangItem::String),
                     _ => false,
                 };
                 if is_string_or_ref_str && item_name.name == sym::iter {
@@ -1606,7 +1608,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
-        Some(err)
+        err.emit()
     }
 
     /// If an appropriate error source is not found, check method chain for possible candidates
@@ -2251,7 +2253,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// Suggest possible range with adding parentheses, for example:
     /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
-    fn suggest_wrapping_range_with_parens(
+    fn report_failed_method_call_on_range_end(
         &self,
         tcx: TyCtxt<'tcx>,
         actual: Ty<'tcx>,
@@ -2259,7 +2261,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         item_name: Ident,
         ty_str: &str,
-    ) -> bool {
+    ) -> Result<(), ErrorGuaranteed> {
         if let SelfSource::MethodCall(expr) = source {
             for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
                 if let Node::Expr(parent_expr) = parent {
@@ -2316,7 +2318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     );
                     if pick.is_ok() {
                         let range_span = parent_expr.span.with_hi(expr.span.hi());
-                        tcx.dcx().emit_err(errors::MissingParenthesesInRange {
+                        return Err(tcx.dcx().emit_err(errors::MissingParenthesesInRange {
                             span,
                             ty_str: ty_str.to_string(),
                             method_name: item_name.as_str().to_string(),
@@ -2325,16 +2327,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 left: range_span.shrink_to_lo(),
                                 right: range_span.shrink_to_hi(),
                             }),
-                        });
-                        return true;
+                        }));
                     }
                 }
             }
         }
-        false
+        Ok(())
     }
 
-    fn suggest_constraining_numerical_ty(
+    fn report_failed_method_call_on_numerical_infer_var(
         &self,
         tcx: TyCtxt<'tcx>,
         actual: Ty<'tcx>,
@@ -2343,7 +2344,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         item_kind: &str,
         item_name: Ident,
         ty_str: &str,
-    ) -> bool {
+    ) -> Result<(), ErrorGuaranteed> {
         let found_candidate = all_traits(self.tcx)
             .into_iter()
             .any(|info| self.associated_value(info.def_id, item_name).is_some());
@@ -2447,10 +2448,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
                 _ => {}
             }
-            err.emit();
-            return true;
+            return Err(err.emit());
         }
-        false
+        Ok(())
     }
 
     /// For code `rect::area(...)`,
@@ -2723,7 +2723,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
                     err.help("use `with` or `try_with` to access thread local storage");
-                } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
+                } else if tcx.is_lang_item(kind.did(), LangItem::MaybeUninit) {
                     err.help(format!(
                         "if this `{name}` has been initialized, \
                         use one of the `assume_init` methods to access the inner value"
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 9476dc70483..aaf3d3ec34d 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -7,7 +7,7 @@ use rustc_errors::{
 };
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
-use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, Pat, PatKind};
+use rustc_hir::{self as hir, BindingMode, ByRef, HirId, LangItem, Mutability, Pat, PatKind};
 use rustc_infer::infer;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
@@ -105,15 +105,16 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
         ti: &TopInfo<'tcx>,
-    ) -> Option<Diag<'tcx>> {
-        let mut diag =
-            self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)?;
-        if let Some(expr) = ti.origin_expr {
-            self.suggest_fn_call(&mut diag, expr, expected, |output| {
-                self.can_eq(self.param_env, output, actual)
-            });
-        }
-        Some(diag)
+    ) -> Result<(), Diag<'tcx>> {
+        self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)
+            .map_err(|mut diag| {
+                if let Some(expr) = ti.origin_expr {
+                    self.suggest_fn_call(&mut diag, expr, expected, |output| {
+                        self.can_eq(self.param_env, output, actual)
+                    });
+                }
+                diag
+            })
     }
 
     fn demand_eqtype_pat(
@@ -122,10 +123,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
         ti: &TopInfo<'tcx>,
-    ) {
-        if let Some(err) = self.demand_eqtype_pat_diag(cause_span, expected, actual, ti) {
-            err.emit();
-        }
+    ) -> Result<(), ErrorGuaranteed> {
+        self.demand_eqtype_pat_diag(cause_span, expected, actual, ti).map_err(|err| err.emit())
     }
 }
 
@@ -492,7 +491,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let tcx = self.tcx;
             let expected = self.resolve_vars_if_possible(expected);
             pat_ty = match expected.kind() {
-                ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().string() => expected,
+                ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => expected,
                 ty::Str => Ty::new_static_str(tcx),
                 _ => pat_ty,
             };
@@ -509,7 +508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         //
         // then that's equivalent to there existing a LUB.
         let cause = self.pattern_cause(ti, span);
-        if let Some(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
+        if let Err(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
             err.emit_unless(
                 ti.span
                     .filter(|&s| {
@@ -562,7 +561,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Subtyping doesn't matter here, as the value is some kind of scalar.
         let demand_eqtype = |x: &mut _, y| {
             if let Some((ref mut fail, x_ty, x_span)) = *x
-                && let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
+                && let Err(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
             {
                 if let Some((_, y_ty, y_span)) = y {
                     self.endpoint_has_type(&mut err, y_span, y_ty);
@@ -736,7 +735,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Otherwise, the type of x is the expected type `T`.
             ByRef::No => expected, // As above, `T <: typeof(x)` is required, but we use equality, see (note_1).
         };
-        self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
+
+        // We have a concrete type for the local, so we do not need to taint it and hide follow up errors *using* the local.
+        let _ = self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
 
         // If there are multiple arms, make sure they all agree on
         // what the type of the binding `x` ought to be.
@@ -763,7 +764,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ti: &TopInfo<'tcx>,
     ) {
         let var_ty = self.local_ty(span, var_id);
-        if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
+        if let Err(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
             let hir = self.tcx.hir();
             let var_ty = self.resolve_vars_if_possible(var_ty);
             let msg = format!("first introduced with type `{var_ty}` here");
@@ -986,13 +987,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // Type-check the path.
-        self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info);
+        let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info);
 
         // Type-check subpatterns.
-        if self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
-            pat_ty
-        } else {
-            Ty::new_misc_error(self.tcx)
+        match self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
+            Ok(()) => pat_ty,
+            Err(guar) => Ty::new_error(self.tcx, guar),
         }
     }
 
@@ -1050,7 +1050,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Type-check the path.
         let (pat_ty, pat_res) =
             self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id);
-        if let Some(err) =
+        if let Err(err) =
             self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty)
         {
             self.emit_bad_pat_path(err, pat, res, pat_res, pat_ty, segments);
@@ -1223,12 +1223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Type-check the tuple struct pattern against the expected type.
         let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, pat_info.top_info);
-        let had_err = if let Some(err) = diag {
-            err.emit();
-            true
-        } else {
-            false
-        };
+        let had_err = diag.map_err(|diag| diag.emit());
 
         // Type-check subpatterns.
         if subpats.len() == variant.fields.len()
@@ -1249,6 +1244,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     None,
                 );
             }
+            if let Err(e) = had_err {
+                on_error(e);
+                return Ty::new_error(tcx, e);
+            }
         } else {
             let e = self.emit_err_pat_wrong_number_of_fields(
                 pat.span,
@@ -1273,7 +1272,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         subpats: &'tcx [Pat<'tcx>],
         fields: &'tcx [ty::FieldDef],
         expected: Ty<'tcx>,
-        had_err: bool,
+        had_err: Result<(), ErrorGuaranteed>,
     ) -> ErrorGuaranteed {
         let subpats_ending = pluralize!(subpats.len());
         let fields_ending = pluralize!(fields.len());
@@ -1330,7 +1329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // #67037: only do this if we could successfully type-check the expected type against
             // the tuple struct pattern. Otherwise the args could get out of range on e.g.,
             // `let P() = U;` where `P != U` with `struct P<T>(T);`.
-            (ty::Adt(_, args), [field], false) => {
+            (ty::Adt(_, args), [field], Ok(())) => {
                 let field_ty = self.field_ty(pat_span, field, args);
                 match field_ty.kind() {
                     ty::Tuple(fields) => fields.len() == subpats.len(),
@@ -1445,8 +1444,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(span));
         let element_tys = tcx.mk_type_list_from_iter(element_tys_iter);
         let pat_ty = Ty::new_tup(tcx, element_tys);
-        if let Some(err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, pat_info.top_info) {
-            let reported = err.emit();
+        if let Err(reported) = self.demand_eqtype_pat(span, expected, pat_ty, pat_info.top_info) {
             // Walk subpatterns with an expected type of `err` in this case to silence
             // further errors being emitted when using the bindings. #50333
             let element_tys_iter = (0..max_len).map(|_| Ty::new_error(tcx, reported));
@@ -1470,7 +1468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         fields: &'tcx [hir::PatField<'tcx>],
         has_rest_pat: bool,
         pat_info: PatInfo<'tcx, '_>,
-    ) -> bool {
+    ) -> Result<(), ErrorGuaranteed> {
         let tcx = self.tcx;
 
         let ty::Adt(adt, args) = adt_ty.kind() else {
@@ -1486,7 +1484,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Keep track of which fields have already appeared in the pattern.
         let mut used_fields = FxHashMap::default();
-        let mut no_field_errors = true;
+        let mut result = Ok(());
 
         let mut inexistent_fields = vec![];
         // Typecheck each field.
@@ -1495,8 +1493,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let ident = tcx.adjust_ident(field.ident, variant.def_id);
             let field_ty = match used_fields.entry(ident) {
                 Occupied(occupied) => {
-                    no_field_errors = false;
                     let guar = self.error_field_already_bound(span, field.ident, *occupied.get());
+                    result = Err(guar);
                     Ty::new_error(tcx, guar)
                 }
                 Vacant(vacant) => {
@@ -1511,7 +1509,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         })
                         .unwrap_or_else(|| {
                             inexistent_fields.push(field);
-                            no_field_errors = false;
                             Ty::new_misc_error(tcx)
                         })
                 }
@@ -1585,37 +1582,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         match (inexistent_fields_err, unmentioned_err) {
             (Some(i), Some(u)) => {
-                if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
+                if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
                     // We don't want to show the nonexistent fields error when this was
                     // `Foo { a, b }` when it should have been `Foo(a, b)`.
                     i.delay_as_bug();
                     u.delay_as_bug();
-                    e.emit();
+                    Err(e)
                 } else {
                     i.emit();
-                    u.emit();
+                    Err(u.emit())
                 }
             }
             (None, Some(u)) => {
-                if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
+                if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
                     u.delay_as_bug();
-                    e.emit();
+                    Err(e)
                 } else {
-                    u.emit();
+                    Err(u.emit())
                 }
             }
-            (Some(err), None) => {
-                err.emit();
-            }
-            (None, None)
-                if let Some(err) =
-                    self.error_tuple_variant_index_shorthand(variant, pat, fields) =>
-            {
-                err.emit();
+            (Some(err), None) => Err(err.emit()),
+            (None, None) => {
+                self.error_tuple_variant_index_shorthand(variant, pat, fields)?;
+                result
             }
-            (None, None) => {}
         }
-        no_field_errors
     }
 
     fn error_tuple_variant_index_shorthand(
@@ -1623,7 +1614,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         variant: &VariantDef,
         pat: &'_ Pat<'_>,
         fields: &[hir::PatField<'_>],
-    ) -> Option<Diag<'_>> {
+    ) -> Result<(), ErrorGuaranteed> {
         // if this is a tuple struct, then all field names will be numbers
         // so if any fields in a struct pattern use shorthand syntax, they will
         // be invalid identifiers (for example, Foo { 0, 1 }).
@@ -1645,10 +1636,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     format!("({})", self.get_suggested_tuple_struct_pattern(fields, variant)),
                     Applicability::MaybeIncorrect,
                 );
-                return Some(err);
+                return Err(err.emit());
             }
         }
-        None
+        Ok(())
     }
 
     fn error_foreign_non_exhaustive_spat(&self, pat: &Pat<'_>, descr: &str, no_fields: bool) {
@@ -1804,14 +1795,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat: &Pat<'_>,
         fields: &'tcx [hir::PatField<'tcx>],
         variant: &ty::VariantDef,
-    ) -> Option<Diag<'tcx>> {
+    ) -> Result<(), ErrorGuaranteed> {
         if let (Some(CtorKind::Fn), PatKind::Struct(qpath, pattern_fields, ..)) =
             (variant.ctor_kind(), &pat.kind)
         {
             let is_tuple_struct_match = !pattern_fields.is_empty()
                 && pattern_fields.iter().map(|field| field.ident.name.as_str()).all(is_number);
             if is_tuple_struct_match {
-                return None;
+                return Ok(());
             }
 
             let path = rustc_hir_pretty::qpath_to_string(&self.tcx, qpath);
@@ -1839,9 +1830,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 format!("({sugg})"),
                 appl,
             );
-            return Some(err);
+            return Err(err.emit());
         }
-        None
+        Ok(())
     }
 
     fn get_suggested_tuple_struct_pattern(
@@ -2065,20 +2056,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
-        let (box_ty, inner_ty) = match self.check_dereferenceable(span, expected, inner) {
-            Ok(()) => {
+        let (box_ty, inner_ty) = self
+            .check_dereferenceable(span, expected, inner)
+            .and_then(|()| {
                 // Here, `demand::subtype` is good enough, but I don't
                 // think any errors can be introduced by using `demand::eqtype`.
                 let inner_ty = self.next_ty_var(inner.span);
                 let box_ty = Ty::new_box(tcx, inner_ty);
-                self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info);
-                (box_ty, inner_ty)
-            }
-            Err(guar) => {
+                self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info)?;
+                Ok((box_ty, inner_ty))
+            })
+            .unwrap_or_else(|guar| {
                 let err = Ty::new_error(tcx, guar);
                 (err, err)
-            }
-        };
+            });
         self.check_pat(inner, inner_ty, pat_info);
         box_ty
     }
@@ -2222,7 +2213,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                         // Look for a case like `fn foo(&foo: u32)` and suggest
                         // `fn foo(foo: &u32)`
-                        if let Some(mut err) = err {
+                        if let Err(mut err) = err {
                             self.borrow_pat_suggestion(&mut err, pat);
                             err.emit();
                         }
@@ -2327,7 +2318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.try_resolve_slice_ty_to_array_ty(before, slice, span)
             {
                 debug!(?resolved_arr_ty);
-                self.demand_eqtype(span, expected, resolved_arr_ty);
+                let _ = self.demand_eqtype(span, expected, resolved_arr_ty);
             }
         }
 
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index 5136ab79a0f..c1565a7d40f 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -18,7 +18,6 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
-rustc_type_ir = { path = "../rustc_type_ir" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 tracing = "0.1"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 01bd732a4cd..fc7a22833ff 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -212,19 +212,63 @@ impl<'a, 'tcx> At<'a, 'tcx> {
         T: ToTrace<'tcx>,
     {
         match variance {
-            ty::Variance::Covariant => self.sub(define_opaque_types, expected, actual),
-            ty::Variance::Invariant => self.eq(define_opaque_types, expected, actual),
-            ty::Variance::Contravariant => self.sup(define_opaque_types, expected, actual),
+            ty::Covariant => self.sub(define_opaque_types, expected, actual),
+            ty::Invariant => self.eq(define_opaque_types, expected, actual),
+            ty::Contravariant => self.sup(define_opaque_types, expected, actual),
 
             // We could make this make sense but it's not readily
             // exposed and I don't feel like dealing with it. Note
             // that bivariance in general does a bit more than just
             // *nothing*, it checks that the types are the same
             // "modulo variance" basically.
-            ty::Variance::Bivariant => panic!("Bivariant given to `relate()`"),
+            ty::Bivariant => panic!("Bivariant given to `relate()`"),
         }
     }
 
+    /// Used in the new solver since we don't care about tracking an `ObligationCause`.
+    pub fn relate_no_trace<T>(
+        self,
+        expected: T,
+        variance: ty::Variance,
+        actual: T,
+    ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>
+    where
+        T: Relate<TyCtxt<'tcx>>,
+    {
+        let mut fields = CombineFields::new(
+            self.infcx,
+            TypeTrace::dummy(self.cause),
+            self.param_env,
+            DefineOpaqueTypes::Yes,
+        );
+        fields.sub().relate_with_variance(
+            variance,
+            ty::VarianceDiagInfo::default(),
+            expected,
+            actual,
+        )?;
+        Ok(fields.goals)
+    }
+
+    /// Used in the new solver since we don't care about tracking an `ObligationCause`.
+    pub fn eq_structurally_relating_aliases_no_trace<T>(
+        self,
+        expected: T,
+        actual: T,
+    ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>
+    where
+        T: Relate<TyCtxt<'tcx>>,
+    {
+        let mut fields = CombineFields::new(
+            self.infcx,
+            TypeTrace::dummy(self.cause),
+            self.param_env,
+            DefineOpaqueTypes::Yes,
+        );
+        fields.equate(StructurallyRelateAliases::Yes).relate(expected, actual)?;
+        Ok(fields.goals)
+    }
+
     /// Computes the least-upper-bound, or mutual supertype, of two
     /// values. The order of the arguments doesn't matter, but since
     /// this can result in an error (e.g., if asked to compute LUB of
@@ -303,7 +347,7 @@ impl<'tcx> ToTrace<'tcx> for Ty<'tcx> {
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+            values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
         }
     }
 }
@@ -315,7 +359,10 @@ impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
         a: Self,
         b: Self,
     ) -> TypeTrace<'tcx> {
-        TypeTrace { cause: cause.clone(), values: Regions(ExpectedFound::new(a_is_expected, a, b)) }
+        TypeTrace {
+            cause: cause.clone(),
+            values: ValuePairs::Regions(ExpectedFound::new(a_is_expected, a, b)),
+        }
     }
 }
 
@@ -328,7 +375,7 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> {
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+            values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
         }
     }
 }
@@ -344,13 +391,13 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
             cause: cause.clone(),
             values: match (a.unpack(), b.unpack()) {
                 (GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => {
-                    Regions(ExpectedFound::new(a_is_expected, a, b))
+                    ValuePairs::Regions(ExpectedFound::new(a_is_expected, a, b))
                 }
                 (GenericArgKind::Type(a), GenericArgKind::Type(b)) => {
-                    Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
+                    ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
                 }
                 (GenericArgKind::Const(a), GenericArgKind::Const(b)) => {
-                    Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
+                    ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
                 }
 
                 (
@@ -379,7 +426,10 @@ impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
         a: Self,
         b: Self,
     ) -> TypeTrace<'tcx> {
-        TypeTrace { cause: cause.clone(), values: Terms(ExpectedFound::new(a_is_expected, a, b)) }
+        TypeTrace {
+            cause: cause.clone(),
+            values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a, b)),
+        }
     }
 }
 
@@ -392,7 +442,7 @@ impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
+            values: ValuePairs::TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
         }
     }
 }
@@ -406,7 +456,7 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: Aliases(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+            values: ValuePairs::Aliases(ExpectedFound::new(a_is_expected, a.into(), b.into())),
         }
     }
 }
@@ -418,7 +468,10 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTerm<'tcx> {
         a: Self,
         b: Self,
     ) -> TypeTrace<'tcx> {
-        TypeTrace { cause: cause.clone(), values: Aliases(ExpectedFound::new(a_is_expected, a, b)) }
+        TypeTrace {
+            cause: cause.clone(),
+            values: ValuePairs::Aliases(ExpectedFound::new(a_is_expected, a, b)),
+        }
     }
 }
 
@@ -431,7 +484,7 @@ impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: PolySigs(ExpectedFound::new(
+            values: ValuePairs::PolySigs(ExpectedFound::new(
                 a_is_expected,
                 ty::Binder::dummy(a),
                 ty::Binder::dummy(b),
@@ -449,7 +502,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyFnSig<'tcx> {
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: PolySigs(ExpectedFound::new(a_is_expected, a, b)),
+            values: ValuePairs::PolySigs(ExpectedFound::new(a_is_expected, a, b)),
         }
     }
 }
@@ -463,7 +516,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> {
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: ExistentialTraitRef(ExpectedFound::new(a_is_expected, a, b)),
+            values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(a_is_expected, a, b)),
         }
     }
 }
@@ -477,7 +530,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: ExistentialProjection(ExpectedFound::new(a_is_expected, a, b)),
+            values: ValuePairs::ExistentialProjection(ExpectedFound::new(a_is_expected, a, b)),
         }
     }
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index ed483c6cbeb..e15866f3f0f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -64,11 +64,11 @@ use rustc_errors::{
     codes::*, pluralize, struct_span_code_err, Applicability, Diag, DiagCtxt, DiagStyledString,
     ErrorGuaranteed, IntoDiagArg, StringPart,
 };
-use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
+use rustc_hir::{self as hir, ParamName};
 use rustc_macros::extension;
 use rustc_middle::bug;
 use rustc_middle::dep_graph::DepContext;
@@ -1707,6 +1707,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     ValuePairs::ExistentialProjection(_) => {
                         (false, Mismatch::Fixed("existential projection"))
                     }
+                    ValuePairs::Dummy => {
+                        bug!("do not expect to report a type error from a ValuePairs::Dummy")
+                    }
                 };
                 let Some(vals) = self.values_str(values) else {
                     // Derived error. Cancel the emitter.
@@ -2250,12 +2253,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         values: ValuePairs<'tcx>,
     ) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
         match values {
-            infer::Regions(exp_found) => self.expected_found_str(exp_found),
-            infer::Terms(exp_found) => self.expected_found_str_term(exp_found),
-            infer::Aliases(exp_found) => self.expected_found_str(exp_found),
-            infer::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
-            infer::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
-            infer::TraitRefs(exp_found) => {
+            ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found),
+            ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found),
+            ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found),
+            ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
+            ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
+            ValuePairs::TraitRefs(exp_found) => {
                 let pretty_exp_found = ty::error::ExpectedFound {
                     expected: exp_found.expected.print_trait_sugared(),
                     found: exp_found.found.print_trait_sugared(),
@@ -2267,7 +2270,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     ret => ret,
                 }
             }
-            infer::PolySigs(exp_found) => {
+            ValuePairs::PolySigs(exp_found) => {
                 let exp_found = self.resolve_vars_if_possible(exp_found);
                 if exp_found.references_error() {
                     return None;
@@ -2275,6 +2278,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found);
                 Some((exp, fnd, None))
             }
+            ValuePairs::Dummy => {
+                bug!("do not expect to report a type error from a ValuePairs::Dummy")
+            }
         }
     }
 
@@ -2423,7 +2429,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             let (type_scope, type_param_sugg_span) = match bound_kind {
                 GenericKind::Param(param) => {
                     let generics = self.tcx.generics_of(generic_param_scope);
-                    let def_id = generics.type_param(param, self.tcx).def_id.expect_local();
+                    let type_param = generics.type_param(param, self.tcx);
+                    let def_id = type_param.def_id.expect_local();
                     let scope = self.tcx.local_def_id_to_hir_id(def_id).owner.def_id;
                     // Get the `hir::Param` to verify whether it already has any bounds.
                     // We do this to avoid suggesting code that ends up as `T: 'a'b`,
@@ -2433,7 +2440,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         Some((span, open_paren_sp)) => Some((span, true, open_paren_sp)),
                         // If `param` corresponds to `Self`, no usable suggestion span.
                         None if generics.has_self && param.index == 0 => None,
-                        None => Some((self.tcx.def_span(def_id).shrink_to_hi(), false, None)),
+                        None => {
+                            let span = if let Some(param) =
+                                hir_generics.params.iter().find(|param| param.def_id == def_id)
+                                && let ParamName::Plain(ident) = param.name
+                            {
+                                ident.span.shrink_to_hi()
+                            } else {
+                                let span = self.tcx.def_span(def_id);
+                                span.shrink_to_hi()
+                            };
+                            Some((span, false, None))
+                        }
                     };
                     (scope, sugg_span)
                 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index effb4090692..bc59b5e033b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -546,7 +546,7 @@ impl<T> Trait<T> for X {
         for pred in hir_generics.bounds_for_param(def_id) {
             if self.constrain_generic_bound_associated_type_structured_suggestion(
                 diag,
-                &trait_ref,
+                trait_ref,
                 pred.bounds,
                 assoc,
                 assoc_args,
@@ -715,7 +715,7 @@ fn foo(&self) -> Self::T { String::new() }
 
             self.constrain_generic_bound_associated_type_structured_suggestion(
                 diag,
-                &trait_ref,
+                trait_ref,
                 opaque_hir_ty.bounds,
                 assoc,
                 assoc_args,
@@ -869,7 +869,7 @@ fn foo(&self) -> Self::T { String::new() }
     fn constrain_generic_bound_associated_type_structured_suggestion(
         &self,
         diag: &mut Diag<'_>,
-        trait_ref: &ty::TraitRef<'tcx>,
+        trait_ref: ty::TraitRef<'tcx>,
         bounds: hir::GenericBounds<'_>,
         assoc: ty::AssocItem,
         assoc_args: &[ty::GenericArg<'tcx>],
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 32b50053b50..9447ea06fdd 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -9,9 +9,8 @@ pub use rustc_middle::ty::IntVarValue;
 pub use BoundRegionConversionTime::*;
 pub use RegionVariableOrigin::*;
 pub use SubregionOrigin::*;
-pub use ValuePairs::*;
 
-use crate::infer::relate::RelateResult;
+use crate::infer::relate::{Relate, RelateResult};
 use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine};
 use error_reporting::TypeErrCtxt;
 use free_regions::RegionRelations;
@@ -35,6 +34,7 @@ use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
 use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::traits::select;
+use rustc_middle::traits::solve::{Goal, NoSolution};
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BoundVarReplacerDelegate;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
@@ -44,7 +44,7 @@ use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid};
 use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Symbol;
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use snapshot::undo_log::InferCtxtUndoLogs;
 use std::cell::{Cell, RefCell};
 use std::fmt;
@@ -352,27 +352,27 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
         }
     }
 
-    fn universe_of_ct(&self, ct: ConstVid) -> Option<ty::UniverseIndex> {
-        // Same issue as with `universe_of_ty`
-        match self.probe_const_var(ct) {
+    fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
+        match self.inner.borrow_mut().unwrap_region_constraints().probe_value(lt) {
             Err(universe) => Some(universe),
             Ok(_) => None,
         }
     }
 
-    fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
-        match self.inner.borrow_mut().unwrap_region_constraints().probe_value(lt) {
+    fn universe_of_ct(&self, ct: ConstVid) -> Option<ty::UniverseIndex> {
+        // Same issue as with `universe_of_ty`
+        match self.probe_const_var(ct) {
             Err(universe) => Some(universe),
             Ok(_) => None,
         }
     }
 
-    fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
-        self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
+    fn root_ty_var(&self, var: TyVid) -> TyVid {
+        self.root_var(var)
     }
 
-    fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
-        self.defining_opaque_types
+    fn root_const_var(&self, var: ConstVid) -> ConstVid {
+        self.root_const_var(var)
     }
 
     fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> Ty<'tcx> {
@@ -405,6 +405,76 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
             }
         }
     }
+
+    fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
+        self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
+    }
+
+    fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
+        self.defining_opaque_types
+    }
+
+    fn next_ty_infer(&self) -> Ty<'tcx> {
+        self.next_ty_var(DUMMY_SP)
+    }
+
+    fn next_const_infer(&self) -> ty::Const<'tcx> {
+        self.next_const_var(DUMMY_SP)
+    }
+
+    fn fresh_args_for_item(&self, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
+        self.fresh_args_for_item(DUMMY_SP, def_id)
+    }
+
+    fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
+        &self,
+        value: ty::Binder<'tcx, T>,
+    ) -> T {
+        self.instantiate_binder_with_fresh_vars(
+            DUMMY_SP,
+            BoundRegionConversionTime::HigherRankedType,
+            value,
+        )
+    }
+
+    fn enter_forall<T: TypeFoldable<TyCtxt<'tcx>> + Copy, U>(
+        &self,
+        value: ty::Binder<'tcx, T>,
+        f: impl FnOnce(T) -> U,
+    ) -> U {
+        self.enter_forall(value, f)
+    }
+
+    fn relate<T: Relate<TyCtxt<'tcx>>>(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        lhs: T,
+        variance: ty::Variance,
+        rhs: T,
+    ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
+        self.at(&ObligationCause::dummy(), param_env).relate_no_trace(lhs, variance, rhs)
+    }
+
+    fn eq_structurally_relating_aliases<T: Relate<TyCtxt<'tcx>>>(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        lhs: T,
+        rhs: T,
+    ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
+        self.at(&ObligationCause::dummy(), param_env)
+            .eq_structurally_relating_aliases_no_trace(lhs, rhs)
+    }
+
+    fn resolve_vars_if_possible<T>(&self, value: T) -> T
+    where
+        T: TypeFoldable<TyCtxt<'tcx>>,
+    {
+        self.resolve_vars_if_possible(value)
+    }
+
+    fn probe<T>(&self, probe: impl FnOnce() -> T) -> T {
+        self.probe(|_| probe())
+    }
 }
 
 /// See the `error_reporting` module for more details.
@@ -417,6 +487,7 @@ pub enum ValuePairs<'tcx> {
     PolySigs(ExpectedFound<ty::PolyFnSig<'tcx>>),
     ExistentialTraitRef(ExpectedFound<ty::PolyExistentialTraitRef<'tcx>>),
     ExistentialProjection(ExpectedFound<ty::PolyExistentialProjection<'tcx>>),
+    Dummy,
 }
 
 impl<'tcx> ValuePairs<'tcx> {
@@ -1812,7 +1883,7 @@ impl<'tcx> TypeTrace<'tcx> {
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+            values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
         }
     }
 
@@ -1824,7 +1895,7 @@ impl<'tcx> TypeTrace<'tcx> {
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
+            values: ValuePairs::TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
         }
     }
 
@@ -1836,9 +1907,13 @@ impl<'tcx> TypeTrace<'tcx> {
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+            values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
         }
     }
+
+    fn dummy(cause: &ObligationCause<'tcx>) -> TypeTrace<'tcx> {
+        TypeTrace { cause: cause.clone(), values: ValuePairs::Dummy }
+    }
 }
 
 impl<'tcx> SubregionOrigin<'tcx> {
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index 7114b888718..b8dd501a721 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -345,7 +345,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 .args
                 .iter()
                 .enumerate()
-                .filter(|(i, _)| variances[*i] == ty::Variance::Invariant)
+                .filter(|(i, _)| variances[*i] == ty::Invariant)
                 .filter_map(|(_, arg)| match arg.unpack() {
                     GenericArgKind::Lifetime(r) => Some(r),
                     GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
@@ -441,7 +441,7 @@ where
                 let variances = self.tcx.variances_of(*def_id);
 
                 for (v, s) in std::iter::zip(variances, args.iter()) {
-                    if *v != ty::Variance::Bivariant {
+                    if *v != ty::Bivariant {
                         s.visit_with(self);
                     }
                 }
diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
index 488f435994d..c02ab98b2ba 100644
--- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
+++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
@@ -102,9 +102,7 @@ where
                     };
 
                     for (idx, s) in args.iter().enumerate() {
-                        if variances.map(|variances| variances[idx])
-                            != Some(ty::Variance::Bivariant)
-                        {
+                        if variances.map(|variances| variances[idx]) != Some(ty::Bivariant) {
                             s.visit_with(self);
                         }
                     }
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index 87a2f0b4580..d6e57d85387 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -83,16 +83,16 @@ impl<'tcx> InferCtxt<'tcx> {
             // mention `?0`.
             if self.next_trait_solver() {
                 let (lhs, rhs, direction) = match instantiation_variance {
-                    ty::Variance::Invariant => {
+                    ty::Invariant => {
                         (generalized_ty.into(), source_ty.into(), AliasRelationDirection::Equate)
                     }
-                    ty::Variance::Covariant => {
+                    ty::Covariant => {
                         (generalized_ty.into(), source_ty.into(), AliasRelationDirection::Subtype)
                     }
-                    ty::Variance::Contravariant => {
+                    ty::Contravariant => {
                         (source_ty.into(), generalized_ty.into(), AliasRelationDirection::Subtype)
                     }
-                    ty::Variance::Bivariant => unreachable!("bivariant generalization"),
+                    ty::Bivariant => unreachable!("bivariant generalization"),
                 };
 
                 relation.register_predicates([ty::PredicateKind::AliasRelate(lhs, rhs, direction)]);
@@ -192,7 +192,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 relation.span(),
                 relation.structurally_relate_aliases(),
                 target_vid,
-                ty::Variance::Invariant,
+                ty::Invariant,
                 source_ct,
             )?;
 
@@ -210,14 +210,14 @@ impl<'tcx> InferCtxt<'tcx> {
         // generalized const and the source.
         if target_is_expected {
             relation.relate_with_variance(
-                ty::Variance::Invariant,
+                ty::Invariant,
                 ty::VarianceDiagInfo::default(),
                 generalized_ct,
                 source_ct,
             )?;
         } else {
             relation.relate_with_variance(
-                ty::Variance::Invariant,
+                ty::Invariant,
                 ty::VarianceDiagInfo::default(),
                 source_ct,
                 generalized_ct,
@@ -411,7 +411,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
         a_arg: ty::GenericArgsRef<'tcx>,
         b_arg: ty::GenericArgsRef<'tcx>,
     ) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
-        if self.ambient_variance == ty::Variance::Invariant {
+        if self.ambient_variance == ty::Invariant {
             // Avoid fetching the variance if we are in an invariant
             // context; no need, and it can induce dependency cycles
             // (e.g., #41849).
@@ -667,7 +667,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
             // structural.
             ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
                 let args = self.relate_with_variance(
-                    ty::Variance::Invariant,
+                    ty::Invariant,
                     ty::VarianceDiagInfo::default(),
                     args,
                     args,
diff --git a/compiler/rustc_infer/src/infer/relate/glb.rs b/compiler/rustc_infer/src/infer/relate/glb.rs
index cc17e60a79b..067004ecaeb 100644
--- a/compiler/rustc_infer/src/infer/relate/glb.rs
+++ b/compiler/rustc_infer/src/infer/relate/glb.rs
@@ -94,12 +94,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Glb<'_, '_, 'tcx> {
             // When higher-ranked types are involved, computing the GLB is
             // very challenging, switch to invariance. This is obviously
             // overly conservative but works ok in practice.
-            self.relate_with_variance(
-                ty::Variance::Invariant,
-                ty::VarianceDiagInfo::default(),
-                a,
-                b,
-            )?;
+            self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
             Ok(a)
         } else {
             Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
diff --git a/compiler/rustc_infer/src/infer/relate/lub.rs b/compiler/rustc_infer/src/infer/relate/lub.rs
index e9d300d349c..2184416b4cc 100644
--- a/compiler/rustc_infer/src/infer/relate/lub.rs
+++ b/compiler/rustc_infer/src/infer/relate/lub.rs
@@ -94,12 +94,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Lub<'_, '_, 'tcx> {
             // When higher-ranked types are involved, computing the LUB is
             // very challenging, switch to invariance. This is obviously
             // overly conservative but works ok in practice.
-            self.relate_with_variance(
-                ty::Variance::Invariant,
-                ty::VarianceDiagInfo::default(),
-                a,
-                b,
-            )?;
+            self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
             Ok(a)
         } else {
             Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs
index e7b50479b85..41cc945492d 100644
--- a/compiler/rustc_infer/src/infer/relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/relate/mod.rs
@@ -4,11 +4,9 @@
 
 pub use rustc_middle::ty::relate::*;
 
-pub use self::_match::MatchAgainstFreshVars;
 pub use self::combine::CombineFields;
 pub use self::combine::PredicateEmittingRelation;
 
-pub mod _match;
 pub(super) mod combine;
 mod generalize;
 mod glb;
diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs
index f7b2f11e3d7..f2bec9392d5 100644
--- a/compiler/rustc_infer/src/infer/relate/type_relating.rs
+++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs
@@ -42,7 +42,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
         a_arg: ty::GenericArgsRef<'tcx>,
         b_arg: ty::GenericArgsRef<'tcx>,
     ) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
-        if self.ambient_variance == ty::Variance::Invariant {
+        if self.ambient_variance == ty::Invariant {
             // Avoid fetching the variance if we are in an invariant
             // context; no need, and it can induce dependency cycles
             // (e.g., #41849).
@@ -325,23 +325,23 @@ impl<'tcx> PredicateEmittingRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
 
     fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
         self.register_predicates([ty::Binder::dummy(match self.ambient_variance {
-            ty::Variance::Covariant => ty::PredicateKind::AliasRelate(
+            ty::Covariant => ty::PredicateKind::AliasRelate(
                 a.into(),
                 b.into(),
                 ty::AliasRelationDirection::Subtype,
             ),
             // a :> b is b <: a
-            ty::Variance::Contravariant => ty::PredicateKind::AliasRelate(
+            ty::Contravariant => ty::PredicateKind::AliasRelate(
                 b.into(),
                 a.into(),
                 ty::AliasRelationDirection::Subtype,
             ),
-            ty::Variance::Invariant => ty::PredicateKind::AliasRelate(
+            ty::Invariant => ty::PredicateKind::AliasRelate(
                 a.into(),
                 b.into(),
                 ty::AliasRelationDirection::Equate,
             ),
-            ty::Variance::Bivariant => {
+            ty::Bivariant => {
                 unreachable!("Expected bivariance to be handled in relate_with_variance")
             }
         })]);
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index cc12a4bf091..ab4148faaab 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -285,8 +285,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
                 let obligations =
                     predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| {
                         elaboratable.child_with_derived_cause(
-                            clause
-                                .instantiate_supertrait(tcx, &bound_clause.rebind(data.trait_ref)),
+                            clause.instantiate_supertrait(tcx, bound_clause.rebind(data.trait_ref)),
                             span,
                             bound_clause.rebind(data),
                             index,
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 733c73bc3d0..043042a492b 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -550,6 +550,7 @@ lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks sho
     .bounds = `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type
     .exception = items in an anonymous const item (`const _: () = {"{"} ... {"}"}`) are treated as in the same scope as the anonymous const's declaration
     .const_anon = use a const-anon item to suppress this lint
+    .macro_to_change = the {$macro_kind} `{$macro_to_change}` defines the non-local `impl`, and may need to be changed
 
 lint_non_local_definitions_impl_move_help =
     move the `impl` block outside of this {$body_kind_descr} {$depth ->
diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
index b671dfaa0d1..911975f6179 100644
--- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
+++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
@@ -3,7 +3,7 @@ use crate::{
     LateContext, LateLintPass, LintContext,
 };
 
-use rustc_hir as hir;
+use rustc_hir::{self as hir, LangItem};
 use rustc_middle::ty;
 use rustc_session::lint::FutureIncompatibilityReason;
 use rustc_session::{declare_lint, declare_lint_pass};
@@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
             // the trait is a `Deref` implementation
             && let Some(trait_) = &impl_.of_trait
             && let Some(did) = trait_.trait_def_id()
-            && Some(did) == tcx.lang_items().deref_trait()
+            && tcx.is_lang_item(did, LangItem::Deref)
             // the self type is `dyn t_principal`
             && let self_ty = tcx.type_of(item.owner_id).instantiate_identity()
             && let ty::Dynamic(data, _, ty::Dyn) = self_ty.kind()
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index b377da31a58..8059f5c1a2e 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1362,6 +1362,7 @@ pub enum NonLocalDefinitionsDiag {
         has_trait: bool,
         self_ty_str: String,
         of_trait_str: Option<String>,
+        macro_to_change: Option<(String, &'static str)>,
     },
     MacroRules {
         depth: u32,
@@ -1387,6 +1388,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
                 has_trait,
                 self_ty_str,
                 of_trait_str,
+                macro_to_change,
             } => {
                 diag.primary_message(fluent::lint_non_local_definitions_impl);
                 diag.arg("depth", depth);
@@ -1397,6 +1399,15 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
                     diag.arg("of_trait_str", of_trait_str);
                 }
 
+                if let Some((macro_to_change, macro_kind)) = macro_to_change {
+                    diag.arg("macro_to_change", macro_to_change);
+                    diag.arg("macro_kind", macro_kind);
+                    diag.note(fluent::lint_macro_to_change);
+                }
+                if let Some(cargo_update) = cargo_update {
+                    diag.subdiagnostic(&diag.dcx, cargo_update);
+                }
+
                 if has_trait {
                     diag.note(fluent::lint_bounds);
                     diag.note(fluent::lint_with_trait);
@@ -1422,9 +1433,6 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
                     );
                 }
 
-                if let Some(cargo_update) = cargo_update {
-                    diag.subdiagnostic(&diag.dcx, cargo_update);
-                }
                 if let Some(const_anon) = const_anon {
                     diag.note(fluent::lint_exception);
                     if let Some(const_anon) = const_anon {
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index c9d67854112..2dc2a0efdf0 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -2,7 +2,7 @@ use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused};
 use crate::{fluent_generated as fluent, LateContext, LateLintPass, LintContext};
 use rustc_ast as ast;
 use rustc_errors::Applicability;
-use rustc_hir as hir;
+use rustc_hir::{self as hir, LangItem};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::bug;
 use rustc_middle::lint::in_external_macro;
@@ -53,8 +53,8 @@ impl<'tcx> LateLintPass<'tcx> for NonPanicFmt {
             if let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind() {
                 let f_diagnostic_name = cx.tcx.get_diagnostic_name(def_id);
 
-                if Some(def_id) == cx.tcx.lang_items().begin_panic_fn()
-                    || Some(def_id) == cx.tcx.lang_items().panic_fn()
+                if cx.tcx.is_lang_item(def_id, LangItem::BeginPanic)
+                    || cx.tcx.is_lang_item(def_id, LangItem::Panic)
                     || f_diagnostic_name == Some(sym::panic_str_2015)
                 {
                     if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id {
@@ -153,7 +153,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
                 ty::Ref(_, r, _) if r.is_str(),
             ) || matches!(
                 ty.ty_adt_def(),
-                Some(ty_def) if Some(ty_def.did()) == cx.tcx.lang_items().string(),
+                Some(ty_def) if cx.tcx.is_lang_item(ty_def.did(), LangItem::String),
             );
 
             let infcx = cx.tcx.infer_ctxt().build();
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index d7ffc34d824..b0ec6e06658 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -258,6 +258,13 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
                     Some((cx.tcx.def_span(parent), may_move))
                 };
 
+                let macro_to_change =
+                    if let ExpnKind::Macro(kind, name) = item.span.ctxt().outer_expn_data().kind {
+                        Some((name.to_string(), kind.descr()))
+                    } else {
+                        None
+                    };
+
                 cx.emit_span_lint(
                     NON_LOCAL_DEFINITIONS,
                     ms,
@@ -274,6 +281,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
                         move_to,
                         may_remove,
                         has_trait: impl_.of_trait.is_some(),
+                        macro_to_change,
                     },
                 )
             }
diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs
index 41ec84faa78..85006421fdd 100644
--- a/compiler/rustc_lint/src/shadowed_into_iter.rs
+++ b/compiler/rustc_lint/src/shadowed_into_iter.rs
@@ -49,10 +49,10 @@ declare_lint! {
     ///
     /// ### Explanation
     ///
-    /// Since Rust CURRENT_RUSTC_VERSION, boxed slices implement `IntoIterator`. However, to avoid
+    /// Since Rust 1.80.0, boxed slices implement `IntoIterator`. However, to avoid
     /// breakage, `boxed_slice.into_iter()` in Rust 2015, 2018, and 2021 code will still
     /// behave as `(&boxed_slice).into_iter()`, returning an iterator over
-    /// references, just like in Rust CURRENT_RUSTC_VERSION and earlier.
+    /// references, just like in Rust 1.80.0 and earlier.
     /// This only applies to the method call syntax `boxed_slice.into_iter()`, not to
     /// any other syntax such as `for _ in boxed_slice` or `IntoIterator::into_iter(boxed_slice)`.
     pub BOXED_SLICE_INTO_ITER,
diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs
index 4d1b1dc4fb7..6983e7abbd6 100644
--- a/compiler/rustc_lint/src/traits.rs
+++ b/compiler/rustc_lint/src/traits.rs
@@ -2,7 +2,7 @@ use crate::lints::{DropGlue, DropTraitConstraintsDiag};
 use crate::LateContext;
 use crate::LateLintPass;
 use crate::LintContext;
-use rustc_hir as hir;
+use rustc_hir::{self as hir, LangItem};
 use rustc_session::{declare_lint, declare_lint_pass};
 use rustc_span::symbol::sym;
 
@@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
                 continue;
             };
             let def_id = trait_predicate.trait_ref.def_id;
-            if cx.tcx.lang_items().drop_trait() == Some(def_id) {
+            if cx.tcx.is_lang_item(def_id, LangItem::Drop) {
                 // Explicitly allow `impl Drop`, a drop-guards-as-unnameable-type pattern.
                 if trait_predicate.trait_ref.self_ty().is_impl_trait() {
                     continue;
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index c8da9f179e7..7a1aa4043be 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -10,9 +10,9 @@ use rustc_ast as ast;
 use rustc_ast::util::{classify, parser};
 use rustc_ast::{ExprKind, StmtKind};
 use rustc_errors::{pluralize, MultiSpan};
-use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
+use rustc_hir::{self as hir, LangItem};
 use rustc_infer::traits::util::elaborate;
 use rustc_middle::ty::adjustment;
 use rustc_middle::ty::{self, Ty};
@@ -289,7 +289,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                     is_ty_must_use(cx, boxed_ty, expr, span)
                         .map(|inner| MustUsePath::Boxed(Box::new(inner)))
                 }
-                ty::Adt(def, args) if cx.tcx.lang_items().pin_type() == Some(def.did()) => {
+                ty::Adt(def, args) if cx.tcx.is_lang_item(def.did(), LangItem::Pin) => {
                     let pinned_ty = args.type_at(0);
                     is_ty_must_use(cx, pinned_ty, expr, span)
                         .map(|inner| MustUsePath::Pinned(Box::new(inner)))
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 726bd0de129..a12c76037e7 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -34,6 +34,7 @@ declare_lint_pass! {
         CONST_EVALUATABLE_UNCHECKED,
         CONST_ITEM_MUTATION,
         DEAD_CODE,
+        DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK,
         DEPRECATED,
         DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
         DEPRECATED_IN_FUTURE,
@@ -3257,7 +3258,11 @@ declare_lint! {
     /// See the [Checking Conditional Configurations][check-cfg] section for more
     /// details.
     ///
+    /// See the [Cargo Specifics][unexpected_cfgs_lint_config] section for configuring this lint in
+    /// `Cargo.toml`.
+    ///
     /// [check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html
+    /// [unexpected_cfgs_lint_config]: https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html#check-cfg-in-lintsrust-table
     pub UNEXPECTED_CFGS,
     Warn,
     "detects unexpected names and values in `#[cfg]` conditions",
@@ -4196,6 +4201,59 @@ declare_lint! {
 }
 
 declare_lint! {
+    /// The `dependency_on_unit_never_type_fallback` lint detects cases where code compiles with
+    /// [never type fallback] being [`()`], but will stop compiling with fallback being [`!`].
+    ///
+    /// [never type fallback]: https://doc.rust-lang.org/nightly/core/primitive.never.html#never-type-fallback
+    /// [`!`]: https://doc.rust-lang.org/core/primitive.never.html
+    /// [`()`]: https://doc.rust-lang.org/core/primitive.unit.html
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![deny(dependency_on_unit_never_type_fallback)]
+    /// fn main() {
+    ///     if true {
+    ///         // return has type `!` which, is some cases, causes never type fallback
+    ///         return
+    ///     } else {
+    ///         // the type produced by this call is not specified explicitly,
+    ///         // so it will be inferred from the previous branch
+    ///         Default::default()
+    ///     };
+    ///     // depending on the fallback, this may compile (because `()` implements `Default`),
+    ///     // or it may not (because `!` does not implement `Default`)
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Due to historic reasons never type fallback was `()`, meaning that `!` got spontaneously
+    /// coerced to `()`. There are plans to change that, but they may make the code such as above
+    /// not compile. Instead of depending on the fallback, you should specify the type explicitly:
+    /// ```
+    /// if true {
+    ///     return
+    /// } else {
+    ///     // type is explicitly specified, fallback can't hurt us no more
+    ///     <() as Default>::default()
+    /// };
+    /// ```
+    ///
+    /// See [Tracking Issue for making `!` fall back to `!`](https://github.com/rust-lang/rust/issues/123748).
+    pub DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK,
+    Warn,
+    "never type fallback affecting unsafe function calls",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reference: "issue #123748 <https://github.com/rust-lang/rust/issues/123748>",
+    };
+    report_in_external_macro
+}
+
+declare_lint! {
     /// The `byte_slice_in_packed_struct_with_derive` lint detects cases where a byte slice field
     /// (`[u8]`) or string slice field (`str`) is used in a `packed` struct that derives one or
     /// more built-in traits.
diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml
index 3ff86f700a5..fe399bc77e3 100644
--- a/compiler/rustc_log/Cargo.toml
+++ b/compiler/rustc_log/Cargo.toml
@@ -8,7 +8,7 @@ edition = "2021"
 tracing = "0.1.28"
 tracing-core = "=0.1.30" # FIXME(Nilstrieb) tracing has a deadlock: https://github.com/tokio-rs/tracing/issues/2635
 tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
-tracing-tree = "0.3.0"
+tracing-tree = "0.3.1"
 # tidy-alphabetical-end
 
 [dev-dependencies]
diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs
index 41b26ecce3c..01b6e342df0 100644
--- a/compiler/rustc_log/src/lib.rs
+++ b/compiler/rustc_log/src/lib.rs
@@ -58,6 +58,7 @@ pub struct LoggerConfig {
     pub verbose_thread_ids: Result<String, VarError>,
     pub backtrace: Result<String, VarError>,
     pub wraptree: Result<String, VarError>,
+    pub lines: Result<String, VarError>,
 }
 
 impl LoggerConfig {
@@ -69,6 +70,7 @@ impl LoggerConfig {
             verbose_thread_ids: env::var(format!("{env}_THREAD_IDS")),
             backtrace: env::var(format!("{env}_BACKTRACE")),
             wraptree: env::var(format!("{env}_WRAPTREE")),
+            lines: env::var(format!("{env}_LINES")),
         }
     }
 }
@@ -101,6 +103,11 @@ pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> {
         Err(_) => false,
     };
 
+    let lines = match cfg.lines {
+        Ok(v) => &v == "1",
+        Err(_) => false,
+    };
+
     let mut layer = tracing_tree::HierarchicalLayer::default()
         .with_writer(io::stderr)
         .with_ansi(color_logs)
@@ -108,6 +115,7 @@ pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> {
         .with_verbose_exit(verbose_entry_exit)
         .with_verbose_entry(verbose_entry_exit)
         .with_indent_amount(2)
+        .with_indent_lines(lines)
         .with_thread_ids(verbose_thread_ids)
         .with_thread_names(verbose_thread_ids);
 
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 89da0df8575..d7840a2d516 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -2020,7 +2020,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
                 // if this is an impl of `CoerceUnsized`, create its
                 // "unsized info", else just store None
-                if Some(trait_ref.def_id) == tcx.lang_items().coerce_unsized_trait() {
+                if tcx.is_lang_item(trait_ref.def_id, LangItem::CoerceUnsized) {
                     let coerce_unsized_info = tcx.coerce_unsized_info(def_id).unwrap();
                     record!(self.tables.coerce_unsized_info[def_id] <- coerce_unsized_info);
                 }
diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs
index 4fd1c1f4a1b..e76d7af6e4a 100644
--- a/compiler/rustc_middle/src/middle/lang_items.rs
+++ b/compiler/rustc_middle/src/middle/lang_items.rs
@@ -23,6 +23,10 @@ impl<'tcx> TyCtxt<'tcx> {
         })
     }
 
+    pub fn is_lang_item(self, def_id: DefId, lang_item: LangItem) -> bool {
+        self.lang_items().get(lang_item) == Some(def_id)
+    }
+
     /// Given a [`DefId`] of one of the [`Fn`], [`FnMut`] or [`FnOnce`] traits,
     /// returns a corresponding [`ty::ClosureKind`].
     /// For any other [`DefId`] return `None`.
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 70e5ad0635b..a84a4c583ed 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -69,6 +69,13 @@ impl<Prov: Provenance> fmt::LowerHex for Scalar<Prov> {
     }
 }
 
+impl<Prov> From<Half> for Scalar<Prov> {
+    #[inline(always)]
+    fn from(f: Half) -> Self {
+        Scalar::from_f16(f)
+    }
+}
+
 impl<Prov> From<Single> for Scalar<Prov> {
     #[inline(always)]
     fn from(f: Single) -> Self {
@@ -83,6 +90,13 @@ impl<Prov> From<Double> for Scalar<Prov> {
     }
 }
 
+impl<Prov> From<Quad> for Scalar<Prov> {
+    #[inline(always)]
+    fn from(f: Quad) -> Self {
+        Scalar::from_f128(f)
+    }
+}
+
 impl<Prov> From<ScalarInt> for Scalar<Prov> {
     #[inline(always)]
     fn from(ptr: ScalarInt) -> Self {
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index b64b7e2b1dc..f1c3cb69896 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -1287,7 +1287,7 @@ fn use_verbose(ty: Ty<'_>, fn_def: bool) -> bool {
 }
 
 impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
-    fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _location: Location) {
+    fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, _location: Location) {
         let ConstOperand { span, user_ty, const_ } = constant;
         if use_verbose(const_.ty(), true) {
             self.push("mir::ConstOperand");
@@ -1415,7 +1415,7 @@ pub fn write_allocations<'tcx>(
     struct CollectAllocIds(BTreeSet<AllocId>);
 
     impl<'tcx> Visitor<'tcx> for CollectAllocIds {
-        fn visit_constant(&mut self, c: &ConstOperand<'tcx>, _: Location) {
+        fn visit_const_operand(&mut self, c: &ConstOperand<'tcx>, _: Location) {
             match c.const_ {
                 Const::Ty(_, _) | Const::Unevaluated(..) => {}
                 Const::Val(val, _) => {
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index ebe77a1abfd..3edc5fe36cd 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1490,7 +1490,8 @@ pub enum BinOp {
     BitOr,
     /// The `<<` operator (shift left)
     ///
-    /// The offset is (uniquely) determined as follows:
+    /// The offset is given by `RHS.rem_euclid(LHS::BITS)`.
+    /// In other words, it is (uniquely) determined as follows:
     /// - it is "equal modulo LHS::BITS" to the RHS
     /// - it is in the range `0..LHS::BITS`
     Shl,
@@ -1498,7 +1499,8 @@ pub enum BinOp {
     ShlUnchecked,
     /// The `>>` operator (shift right)
     ///
-    /// The offset is (uniquely) determined as follows:
+    /// The offset is given by `RHS.rem_euclid(LHS::BITS)`.
+    /// In other words, it is (uniquely) determined as follows:
     /// - it is "equal modulo LHS::BITS" to the RHS
     /// - it is in the range `0..LHS::BITS`
     ///
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index f553b417294..10609e56f2c 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -184,12 +184,12 @@ macro_rules! make_mir_visitor {
 
             /// This is called for every constant in the MIR body and every `required_consts`
             /// (i.e., including consts that have been dead-code-eliminated).
-            fn visit_constant(
+            fn visit_const_operand(
                 &mut self,
                 constant: & $($mutability)? ConstOperand<'tcx>,
                 location: Location,
             ) {
-                self.super_constant(constant, location);
+                self.super_const_operand(constant, location);
             }
 
             fn visit_ty_const(
@@ -597,7 +597,7 @@ macro_rules! make_mir_visitor {
                                 }
                                 InlineAsmOperand::Const { value }
                                 | InlineAsmOperand::SymFn { value } => {
-                                    self.visit_constant(value, location);
+                                    self.visit_const_operand(value, location);
                                 }
                                 InlineAsmOperand::Out { place: None, .. }
                                 | InlineAsmOperand::SymStatic { def_id: _ }
@@ -788,7 +788,7 @@ macro_rules! make_mir_visitor {
                         );
                     }
                     Operand::Constant(constant) => {
-                        self.visit_constant(constant, location);
+                        self.visit_const_operand(constant, location);
                     }
                 }
             }
@@ -867,7 +867,7 @@ macro_rules! make_mir_visitor {
                     }
                 }
                 match value {
-                    VarDebugInfoContents::Const(c) => self.visit_constant(c, location),
+                    VarDebugInfoContents::Const(c) => self.visit_const_operand(c, location),
                     VarDebugInfoContents::Place(place) =>
                         self.visit_place(
                             place,
@@ -882,7 +882,7 @@ macro_rules! make_mir_visitor {
                 _scope: $(& $mutability)? SourceScope
             ) {}
 
-            fn super_constant(
+            fn super_const_operand(
                 &mut self,
                 constant: & $($mutability)? ConstOperand<'tcx>,
                 location: Location
@@ -1057,7 +1057,7 @@ macro_rules! super_body {
 
         for const_ in &$($mutability)? $body.required_consts {
             let location = Location::START;
-            $self.visit_constant(const_, location);
+            $self.visit_const_operand(const_, location);
         }
     }
 }
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 50b6c77e1b2..4fad721ce98 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -156,7 +156,7 @@ pub struct CandidateStep<'tcx> {
 
 #[derive(Copy, Clone, Debug, HashStable)]
 pub struct MethodAutoderefStepsResult<'tcx> {
-    /// The valid autoderef steps that could be find.
+    /// The valid autoderef steps that could be found.
     pub steps: &'tcx [CandidateStep<'tcx>],
     /// If Some(T), a type autoderef reported an error on.
     pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>,
diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs
index 707e076921b..adbb6cf2ddc 100644
--- a/compiler/rustc_middle/src/traits/util.rs
+++ b/compiler/rustc_middle/src/traits/util.rs
@@ -37,7 +37,7 @@ impl<'tcx> Elaborator<'tcx> {
         let super_predicates =
             self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map(
                 |&(pred, _)| {
-                    let clause = pred.instantiate_supertrait(self.tcx, &trait_ref);
+                    let clause = pred.instantiate_supertrait(self.tcx, trait_ref);
                     self.visited.insert(clause).then_some(clause)
                 },
             );
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 886dbd317af..684b3233cfd 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -8,9 +8,9 @@ use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::HashingControls;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::ErrorGuaranteed;
-use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
+use rustc_hir::{self as hir, LangItem};
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_query_system::ich::StableHashingContext;
@@ -204,6 +204,23 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
     fn def_id(self) -> DefId {
         self.did()
     }
+
+    fn is_phantom_data(self) -> bool {
+        self.is_phantom_data()
+    }
+
+    fn all_field_tys(
+        self,
+        tcx: TyCtxt<'tcx>,
+    ) -> ty::EarlyBinder<'tcx, impl Iterator<Item = Ty<'tcx>>> {
+        ty::EarlyBinder::bind(
+            self.all_fields().map(move |field| tcx.type_of(field.did).skip_binder()),
+        )
+    }
+
+    fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
+        self.sized_constraint(tcx)
+    }
 }
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)]
@@ -257,16 +274,16 @@ impl AdtDefData {
         if tcx.has_attr(did, sym::fundamental) {
             flags |= AdtFlags::IS_FUNDAMENTAL;
         }
-        if Some(did) == tcx.lang_items().phantom_data() {
+        if tcx.is_lang_item(did, LangItem::PhantomData) {
             flags |= AdtFlags::IS_PHANTOM_DATA;
         }
-        if Some(did) == tcx.lang_items().owned_box() {
+        if tcx.is_lang_item(did, LangItem::OwnedBox) {
             flags |= AdtFlags::IS_BOX;
         }
-        if Some(did) == tcx.lang_items().manually_drop() {
+        if tcx.is_lang_item(did, LangItem::ManuallyDrop) {
             flags |= AdtFlags::IS_MANUALLY_DROP;
         }
-        if Some(did) == tcx.lang_items().unsafe_cell_type() {
+        if tcx.is_lang_item(did, LangItem::UnsafeCell) {
             flags |= AdtFlags::IS_UNSAFE_CELL;
         }
         if is_anonymous {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 65d744239a6..3651c990c97 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -70,9 +70,9 @@ use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
 use rustc_target::spec::abi;
 use rustc_type_ir::fold::TypeFoldable;
+use rustc_type_ir::lang_items::TraitSolverLangItem;
 use rustc_type_ir::TyKind::*;
-use rustc_type_ir::WithCachedTypeInfo;
-use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
+use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo};
 use tracing::{debug, instrument};
 
 use std::assert_matches::assert_matches;
@@ -154,7 +154,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
 
     type VariancesOf = &'tcx [ty::Variance];
 
-    fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf {
+    fn variances_of(self, def_id: DefId) -> Self::VariancesOf {
         self.variances_of(def_id)
     }
 
@@ -198,7 +198,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
 
     fn trait_ref_and_own_args_for_alias(
         self,
-        def_id: Self::DefId,
+        def_id: DefId,
         args: Self::GenericArgs,
     ) -> (rustc_type_ir::TraitRef<Self>, Self::GenericArgsSlice) {
         assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst);
@@ -246,7 +246,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.mk_type_list_from_iter(args)
     }
 
-    fn parent(self, def_id: Self::DefId) -> Self::DefId {
+    fn parent(self, def_id: DefId) -> DefId {
         self.parent(def_id)
     }
 
@@ -259,15 +259,85 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     fn features(self) -> Self::Features {
         self.features()
     }
+
+    fn bound_coroutine_hidden_types(
+        self,
+        def_id: DefId,
+    ) -> impl IntoIterator<Item = ty::EarlyBinder<'tcx, ty::Binder<'tcx, Ty<'tcx>>>> {
+        self.bound_coroutine_hidden_types(def_id)
+    }
+
+    fn fn_sig(self, def_id: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> {
+        self.fn_sig(def_id)
+    }
+
+    fn coroutine_movability(self, def_id: DefId) -> rustc_ast::Movability {
+        self.coroutine_movability(def_id)
+    }
+
+    fn coroutine_for_closure(self, def_id: DefId) -> DefId {
+        self.coroutine_for_closure(def_id)
+    }
+
+    fn generics_require_sized_self(self, def_id: DefId) -> bool {
+        self.generics_require_sized_self(def_id)
+    }
+
+    fn item_bounds(
+        self,
+        def_id: DefId,
+    ) -> ty::EarlyBinder<'tcx, impl IntoIterator<Item = ty::Clause<'tcx>>> {
+        self.item_bounds(def_id).map_bound(IntoIterator::into_iter)
+    }
+
+    fn super_predicates_of(
+        self,
+        def_id: DefId,
+    ) -> ty::EarlyBinder<'tcx, impl IntoIterator<Item = ty::Clause<'tcx>>> {
+        ty::EarlyBinder::bind(
+            self.super_predicates_of(def_id).instantiate_identity(self).predicates.into_iter(),
+        )
+    }
+
+    fn has_target_features(self, def_id: DefId) -> bool {
+        !self.codegen_fn_attrs(def_id).target_features.is_empty()
+    }
+
+    fn require_lang_item(self, lang_item: TraitSolverLangItem) -> DefId {
+        self.require_lang_item(
+            match lang_item {
+                TraitSolverLangItem::Future => hir::LangItem::Future,
+                TraitSolverLangItem::FutureOutput => hir::LangItem::FutureOutput,
+                TraitSolverLangItem::AsyncFnKindHelper => hir::LangItem::AsyncFnKindHelper,
+                TraitSolverLangItem::AsyncFnKindUpvars => hir::LangItem::AsyncFnKindUpvars,
+            },
+            None,
+        )
+    }
+
+    fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator<Item = DefId> {
+        self.associated_items(def_id)
+            .in_definition_order()
+            .filter(|assoc_item| matches!(assoc_item.kind, ty::AssocKind::Type))
+            .map(|assoc_item| assoc_item.def_id)
+    }
 }
 
 impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for abi::Abi {
+    fn rust() -> Self {
+        abi::Abi::Rust
+    }
+
     fn is_rust(self) -> bool {
         matches!(self, abi::Abi::Rust)
     }
 }
 
 impl<'tcx> rustc_type_ir::inherent::Safety<TyCtxt<'tcx>> for hir::Safety {
+    fn safe() -> Self {
+        hir::Safety::Safe
+    }
+
     fn is_safe(self) -> bool {
         matches!(self, hir::Safety::Safe)
     }
@@ -281,6 +351,10 @@ impl<'tcx> rustc_type_ir::inherent::Features<TyCtxt<'tcx>> for &'tcx rustc_featu
     fn generic_const_exprs(self) -> bool {
         self.generic_const_exprs
     }
+
+    fn coroutine_clone(self) -> bool {
+        self.coroutine_clone
+    }
 }
 
 type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 7fff3d01324..54c88e48614 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -41,6 +41,8 @@ pub struct GenericArg<'tcx> {
     marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>,
 }
 
+impl<'tcx> rustc_type_ir::inherent::GenericArg<TyCtxt<'tcx>> for GenericArg<'tcx> {}
+
 impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArgsRef<'tcx> {
     fn type_at(self, i: usize) -> Ty<'tcx> {
         self.type_at(i)
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index a887047f62f..bdf90cbb25b 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -699,26 +699,25 @@ impl<'tcx> Instance<'tcx> {
         };
         let coroutine_kind = tcx.coroutine_kind(coroutine_def_id).unwrap();
 
-        let lang_items = tcx.lang_items();
-        let coroutine_callable_item = if Some(trait_id) == lang_items.future_trait() {
+        let coroutine_callable_item = if tcx.is_lang_item(trait_id, LangItem::Future) {
             assert_matches!(
                 coroutine_kind,
                 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
             );
             hir::LangItem::FuturePoll
-        } else if Some(trait_id) == lang_items.iterator_trait() {
+        } else if tcx.is_lang_item(trait_id, LangItem::Iterator) {
             assert_matches!(
                 coroutine_kind,
                 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
             );
             hir::LangItem::IteratorNext
-        } else if Some(trait_id) == lang_items.async_iterator_trait() {
+        } else if tcx.is_lang_item(trait_id, LangItem::AsyncIterator) {
             assert_matches!(
                 coroutine_kind,
                 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)
             );
             hir::LangItem::AsyncIteratorPollNext
-        } else if Some(trait_id) == lang_items.coroutine_trait() {
+        } else if tcx.is_lang_item(trait_id, LangItem::Coroutine) {
             assert_matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_));
             hir::LangItem::CoroutineResume
         } else {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 56945bf6be4..02c0d41f619 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -9,6 +9,7 @@ use rustc_errors::{
 };
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::LangItem;
 use rustc_index::IndexVec;
 use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable};
 use rustc_session::config::OptLevel;
@@ -850,7 +851,7 @@ where
                         // and we rely on this layout information to trigger a panic in
                         // `std::mem::uninitialized::<&dyn Trait>()`, for example.
                         if let ty::Adt(def, args) = metadata.kind()
-                            && Some(def.did()) == tcx.lang_items().dyn_metadata()
+                            && tcx.is_lang_item(def.did(), LangItem::DynMetadata)
                             && let ty::Dynamic(data, _, ty::Dyn) = args.type_at(0).kind()
                         {
                             mk_dyn_vtable(data.principal())
@@ -1169,7 +1170,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) ->
         // This is not part of `codegen_fn_attrs` as it can differ between crates
         // and therefore cannot be computed in core.
         if tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Abort {
-            if Some(did) == tcx.lang_items().drop_in_place_fn() {
+            if tcx.is_lang_item(did, LangItem::DropInPlace) {
                 return false;
             }
         }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 83f8de6b6f9..5a94a53e175 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -16,7 +16,6 @@ pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeV
 pub use self::AssocItemContainer::*;
 pub use self::BorrowKind::*;
 pub use self::IntVarValue::*;
-pub use self::Variance::*;
 use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
 use crate::metadata::ModChild;
 use crate::middle::privacy::EffectiveVisibilities;
@@ -488,6 +487,8 @@ pub struct Term<'tcx> {
     marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>,
 }
 
+impl<'tcx> rustc_type_ir::inherent::Term<TyCtxt<'tcx>> for Term<'tcx> {}
+
 impl<'tcx> rustc_type_ir::inherent::IntoKind for Term<'tcx> {
     type Kind = TermKind<'tcx>;
 
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index c730f5117c5..ae36f2624ca 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -49,6 +49,18 @@ impl<'tcx> rustc_type_ir::inherent::Predicate<TyCtxt<'tcx>> for Predicate<'tcx>
     fn is_coinductive(self, interner: TyCtxt<'tcx>) -> bool {
         self.is_coinductive(interner)
     }
+
+    fn allow_normalization(self) -> bool {
+        self.allow_normalization()
+    }
+}
+
+impl<'tcx> rustc_type_ir::inherent::IntoKind for Predicate<'tcx> {
+    type Kind = ty::Binder<'tcx, ty::PredicateKind<'tcx>>;
+
+    fn kind(self) -> Self::Kind {
+        self.kind()
+    }
 }
 
 impl<'tcx> rustc_type_ir::visit::Flags for Predicate<'tcx> {
@@ -120,6 +132,7 @@ impl<'tcx> Predicate<'tcx> {
     /// unsoundly accept some programs. See #91068.
     #[inline]
     pub fn allow_normalization(self) -> bool {
+        // Keep this in sync with the one in `rustc_type_ir::inherent`!
         match self.kind().skip_binder() {
             PredicateKind::Clause(ClauseKind::WellFormed(_))
             | PredicateKind::AliasRelate(..)
@@ -313,7 +326,7 @@ impl<'tcx> Clause<'tcx> {
     pub fn instantiate_supertrait(
         self,
         tcx: TyCtxt<'tcx>,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
+        trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Clause<'tcx> {
         // The interaction between HRTB and supertraits is not entirely
         // obvious. Let me walk you (and myself) through an example.
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 662eafd0ccb..de1796d4800 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -999,7 +999,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     let trait_ref = bound_predicate.rebind(pred.trait_ref);
 
                     // Don't print `+ Sized`, but rather `+ ?Sized` if absent.
-                    if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() {
+                    if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) {
                         match pred.polarity {
                             ty::PredicatePolarity::Positive => {
                                 has_sized_bound = true;
@@ -1254,14 +1254,14 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 }
                 entry.has_fn_once = true;
                 return;
-            } else if Some(trait_def_id) == self.tcx().lang_items().fn_mut_trait() {
+            } else if self.tcx().is_lang_item(trait_def_id, LangItem::FnMut) {
                 let super_trait_ref = supertraits_for_pretty_printing(self.tcx(), trait_ref)
                     .find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait)
                     .unwrap();
 
                 fn_traits.entry(super_trait_ref).or_default().fn_mut_trait_ref = Some(trait_ref);
                 return;
-            } else if Some(trait_def_id) == self.tcx().lang_items().fn_trait() {
+            } else if self.tcx().is_lang_item(trait_def_id, LangItem::Fn) {
                 let super_trait_ref = supertraits_for_pretty_printing(self.tcx(), trait_ref)
                     .find(|super_trait_ref| super_trait_ref.def_id() == fn_once_trait)
                     .unwrap();
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index ba9ed0d5b70..8308e537e5e 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -786,6 +786,10 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
         tcx.types.bool
     }
 
+    fn new_u8(tcx: TyCtxt<'tcx>) -> Self {
+        tcx.types.u8
+    }
+
     fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Self {
         Ty::new_infer(tcx, infer)
     }
diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs
index a4cbfe86711..dc1d73684f4 100644
--- a/compiler/rustc_middle/src/util/call_kind.rs
+++ b/compiler/rustc_middle/src/util/call_kind.rs
@@ -117,19 +117,19 @@ pub fn call_kind<'tcx>(
     kind.unwrap_or_else(|| {
         // This isn't a 'special' use of `self`
         debug!(?method_did, ?fn_call_span);
-        let desugaring = if Some(method_did) == tcx.lang_items().into_iter_fn()
+        let desugaring = if tcx.is_lang_item(method_did, LangItem::IntoIterIntoIter)
             && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop)
         {
             Some((CallDesugaringKind::ForLoopIntoIter, method_args.type_at(0)))
         } else if fn_call_span.desugaring_kind() == Some(DesugaringKind::QuestionMark) {
-            if Some(method_did) == tcx.lang_items().branch_fn() {
+            if tcx.is_lang_item(method_did, LangItem::TryTraitBranch) {
                 Some((CallDesugaringKind::QuestionBranch, method_args.type_at(0)))
-            } else if Some(method_did) == tcx.lang_items().from_residual_fn() {
+            } else if tcx.is_lang_item(method_did, LangItem::TryTraitFromResidual) {
                 Some((CallDesugaringKind::QuestionFromResidual, method_args.type_at(0)))
             } else {
                 None
             }
-        } else if Some(method_did) == tcx.lang_items().from_output_fn()
+        } else if tcx.is_lang_item(method_did, LangItem::TryTraitFromOutput)
             && fn_call_span.desugaring_kind() == Some(DesugaringKind::TryBlock)
         {
             Some((CallDesugaringKind::TryBlockFromOutput, method_args.type_at(0)))
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 4ae475d35d1..8c323188826 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -142,7 +142,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for &[ty::Variance] {
             && let Some(def_id) = frame.query.def_id
         {
             let n = tcx.generics_of(def_id).own_params.len();
-            vec![ty::Variance::Bivariant; n].leak()
+            vec![ty::Bivariant; n].leak()
         } else {
             span_bug!(
                 cycle_error.usage.as_ref().unwrap().0,
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index b783eba8c4e..3b69058d3cb 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -2,6 +2,7 @@
 
 use crate::build::{parse_float_into_constval, Builder};
 use rustc_ast as ast;
+use rustc_hir::LangItem;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{Allocation, LitToConstError, LitToConstInput, Scalar};
 use rustc_middle::mir::*;
@@ -142,7 +143,7 @@ fn lit_to_mir_constant<'tcx>(
             let id = tcx.allocate_bytes(data);
             ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
         }
-        (ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().c_str()) =>
+        (ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
         {
             let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
             let allocation = tcx.mk_const_alloc(allocation);
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 54138789369..544f27b84e9 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -699,7 +699,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             // exactly `T` (i.e., with invariance). The variance field, in
                             // contrast, is intended to be used to relate `T` to the type of
                             // `<expr>`.
-                            ty::Variance::Invariant,
+                            ty::Invariant,
                         ),
                     },
                 );
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 2040071e76e..11d3e2a8180 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -141,7 +141,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let success_block = target_block(TestBranch::Success);
                 let fail_block = target_block(TestBranch::Failure);
                 if let ty::Adt(def, _) = ty.kind()
-                    && Some(def.did()) == tcx.lang_items().string()
+                    && tcx.is_lang_item(def.did(), LangItem::String)
                 {
                     if !tcx.features().string_deref_patterns {
                         bug!(
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index d781fb1c297..a65586ccdb7 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -97,6 +97,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
                 if !span.at_least_rust_2024()
                     && self.tcx.has_attr(id, sym::rustc_deprecated_safe_2024) =>
             {
+                let sm = self.tcx.sess.source_map();
                 self.tcx.emit_node_span_lint(
                     DEPRECATED_SAFE,
                     self.hir_context,
@@ -105,6 +106,8 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
                         span,
                         function: with_no_trimmed_paths!(self.tcx.def_path_str(id)),
                         sub: CallToDeprecatedSafeFnRequiresUnsafeSub {
+                            indent: sm.indentation_before(span).unwrap_or_default(),
+                            start_of_line: sm.span_extend_to_line(span).shrink_to_lo(),
                             left: span.shrink_to_lo(),
                             right: span.shrink_to_hi(),
                         },
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index cf324c03dc9..3bd2e47976b 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -33,6 +33,11 @@ pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe {
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(mir_build_suggestion, applicability = "machine-applicable")]
 pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafeSub {
+    pub(crate) indent: String,
+    #[suggestion_part(
+        code = "{indent}// TODO: Audit that the environment access only happens in single-threaded code.\n" // ignore-tidy-todo
+    )]
+    pub(crate) start_of_line: Span,
     #[suggestion_part(code = "unsafe {{ ")]
     pub(crate) left: Span,
     #[suggestion_part(code = " }}")]
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index a98e046d4dc..7b94867114d 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -1,4 +1,5 @@
 use rustc_ast as ast;
+use rustc_hir::LangItem;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
 use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt};
@@ -46,7 +47,7 @@ pub(crate) fn lit_to_const<'tcx>(
         (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
             ty::ValTree::from_scalar_int((*n).into())
         }
-        (ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().c_str()) =>
+        (ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
         {
             let bytes = data as &[u8];
             ty::ValTree::from_raw_bytes(tcx, bytes)
diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs
index 54eafdd828a..95cd703dbb3 100644
--- a/compiler/rustc_mir_build/src/thir/cx/block.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/block.rs
@@ -92,7 +92,7 @@ impl<'tcx> Cx<'tcx> {
                                     kind: PatKind::AscribeUserType {
                                         ascription: Ascription {
                                             annotation,
-                                            variance: ty::Variance::Covariant,
+                                            variance: ty::Covariant,
                                         },
                                         subpattern: pattern,
                                     },
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 158ca91fcf1..93db1f61853 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -525,7 +525,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             };
             kind = PatKind::AscribeUserType {
                 subpattern: Box::new(Pat { span, ty, kind }),
-                ascription: Ascription { annotation, variance: ty::Variance::Covariant },
+                ascription: Ascription { annotation, variance: ty::Covariant },
             };
         }
 
@@ -612,7 +612,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                                 annotation,
                                 // Note that use `Contravariant` here. See the
                                 // `variance` field documentation for details.
-                                variance: ty::Variance::Contravariant,
+                                variance: ty::Contravariant,
                             },
                         },
                         ty: const_.ty(),
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index bdc59e84356..654020164db 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -454,8 +454,7 @@ where
             });
         }
 
-        let skip_contents =
-            adt.is_union() || Some(adt.did()) == self.tcx().lang_items().manually_drop();
+        let skip_contents = adt.is_union() || adt.is_manually_drop();
         let contents_drop = if skip_contents {
             (self.succ, self.unwind)
         } else {
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index f880476cec2..16977a63c59 100644
--- a/compiler/rustc_mir_transform/src/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -4,6 +4,7 @@
 //! of MIR building, and only after this pass we think of the program has having the
 //! normal MIR semantics.
 
+use rustc_hir::LangItem;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
@@ -27,7 +28,7 @@ fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> b
         // References and Boxes (`noalias` sources)
         ty::Ref(..) => true,
         ty::Adt(..) if ty.is_box() => true,
-        ty::Adt(adt, _) if Some(adt.did()) == tcx.lang_items().ptr_unique() => true,
+        ty::Adt(adt, _) if tcx.is_lang_item(adt.did(), LangItem::PtrUnique) => true,
         // Compound types: recurse
         ty::Array(ty, _) | ty::Slice(ty) => {
             // This does not branch so we keep the depth the same.
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 121a3b99a39..0f8f28e3462 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -330,8 +330,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         let is_sized = !self.feature_unsized_locals
             || self.local_decls[local].ty.is_sized(self.tcx, self.param_env);
         if is_sized {
-            self.rev_locals.ensure_contains_elem(value, SmallVec::new);
-            self.rev_locals[value].push(local);
+            self.rev_locals.ensure_contains_elem(value, SmallVec::new).push(local);
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index fe2237dd2e9..2cbe0a01e9e 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -225,13 +225,8 @@ 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::relate_types(
-            self.tcx,
-            self.param_env,
-            ty::Variance::Covariant,
-            output_type,
-            destination_ty,
-        ) {
+        if !util::relate_types(self.tcx, self.param_env, ty::Covariant, output_type, destination_ty)
+        {
             trace!(?output_type, ?destination_ty);
             return Err("failed to normalize return type");
         }
@@ -261,13 +256,8 @@ 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::relate_types(
-                    self.tcx,
-                    self.param_env,
-                    ty::Variance::Covariant,
-                    input_type,
-                    arg_ty,
-                ) {
+                if !util::relate_types(self.tcx, self.param_env, ty::Covariant, input_type, arg_ty)
+                {
                     trace!(?arg_ty, ?input_type);
                     return Err("failed to normalize tuple argument type");
                 }
@@ -276,13 +266,8 @@ 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.node.ty(&caller_body.local_decls, self.tcx);
-                if !util::relate_types(
-                    self.tcx,
-                    self.param_env,
-                    ty::Variance::Covariant,
-                    input_type,
-                    arg_ty,
-                ) {
+                if !util::relate_types(self.tcx, self.param_env, ty::Covariant, input_type, arg_ty)
+                {
                     trace!(?arg_ty, ?input_type);
                     return Err("failed to normalize argument type");
                 }
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 6a20b46e7f9..8d6c00bbedb 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -706,9 +706,9 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
         self.super_operand(operand, location);
     }
 
-    fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
-        trace!("visit_constant: {:?}", constant);
-        self.super_constant(constant, location);
+    fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
+        trace!("visit_const_operand: {:?}", constant);
+        self.super_const_operand(constant, location);
         self.eval_constant(constant);
     }
 
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index ecd1179ca99..ecdca8292b4 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -956,7 +956,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> {
         }
     }
 
-    fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, _location: Location) {
+    fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>, _location: Location) {
         if constant.const_.is_required_const() {
             self.promoted.required_consts.push(*constant);
         }
diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs
index 71ac929d35e..00bfb5e6600 100644
--- a/compiler/rustc_mir_transform/src/required_consts.rs
+++ b/compiler/rustc_mir_transform/src/required_consts.rs
@@ -12,7 +12,7 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
 }
 
 impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
-    fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _: Location) {
+    fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, _: Location) {
         if constant.const_.is_required_const() {
             self.required_consts.push(*constant);
         }
diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs
index 4d2eca57840..5eaa024f846 100644
--- a/compiler/rustc_mir_transform/src/reveal_all.rs
+++ b/compiler/rustc_mir_transform/src/reveal_all.rs
@@ -49,14 +49,14 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
     }
 
     #[inline]
-    fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) {
+    fn visit_const_operand(&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);
+        self.super_const_operand(constant, location);
     }
 
     #[inline]
diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
index aa9c87d8f80..41643f20285 100644
--- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
+++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
@@ -561,7 +561,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
 
             // If projection of Discriminant then compare with `Ty::discriminant_ty`
             if let ty::Alias(ty::Projection, ty::AliasTy { args, def_id, .. }) = expected_ty.kind()
-                && Some(*def_id) == self.tcx.lang_items().discriminant_type()
+                && self.tcx.is_lang_item(*def_id, LangItem::Discriminant)
                 && args.first().unwrap().as_type().unwrap().discriminant_ty(self.tcx) == operand_ty
             {
                 return;
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index f19c34cae7a..c2108795372 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -1,4 +1,5 @@
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
+use rustc_hir::LangItem;
 use rustc_index::bit_set::{BitSet, GrowableBitSet};
 use rustc_index::IndexVec;
 use rustc_middle::bug;
@@ -70,7 +71,7 @@ fn escaping_locals<'tcx>(
                 // Exclude #[repr(simd)] types so that they are not de-optimized into an array
                 return true;
             }
-            if Some(def.did()) == tcx.lang_items().dyn_metadata() {
+            if tcx.is_lang_item(def.did(), LangItem::DynMetadata) {
                 // codegen wants to see the `DynMetadata<T>`,
                 // not the inner reference-to-opaque-type.
                 return true;
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 586c1254995..ea23bbc2a38 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -1,6 +1,7 @@
 //! Validates the MIR to ensure that invariants are upheld.
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir::LangItem;
 use rustc_index::bit_set::BitSet;
 use rustc_index::IndexVec;
 use rustc_infer::traits::Reveal;
@@ -689,7 +690,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     }
                     ty::Adt(adt_def, args) => {
                         // see <https://github.com/rust-lang/rust/blob/7601adcc764d42c9f2984082b49948af652df986/compiler/rustc_middle/src/ty/layout.rs#L861-L864>
-                        if Some(adt_def.did()) == self.tcx.lang_items().dyn_metadata() {
+                        if self.tcx.is_lang_item(adt_def.did(), LangItem::DynMetadata) {
                             self.fail(
                                 location,
                                 format!(
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 61680dbfaf5..04de1654c1a 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -593,7 +593,7 @@ fn check_recursion_limit<'tcx>(
     let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0);
     debug!(" => recursion depth={}", recursion_depth);
 
-    let adjusted_recursion_depth = if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
+    let adjusted_recursion_depth = if tcx.is_lang_item(def_id, LangItem::DropInPlace) {
         // HACK: drop_in_place creates tight monomorphization loops. Give
         // it more margin.
         recursion_depth / 4
@@ -799,7 +799,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
     /// This does not walk the MIR of the constant as that is not needed for codegen, all we need is
     /// to ensure that the constant evaluates successfully and walk the result.
     #[instrument(skip(self), level = "debug")]
-    fn visit_constant(&mut self, constant: &mir::ConstOperand<'tcx>, location: Location) {
+    fn visit_const_operand(&mut self, constant: &mir::ConstOperand<'tcx>, location: Location) {
         // No `super_constant` as we don't care about `visit_ty`/`visit_ty_const`.
         let Some(val) = self.eval_constant(constant) else { return };
         collect_const_value(self.tcx, val, self.used_items);
@@ -945,7 +945,7 @@ fn visit_instance_use<'tcx>(
             // be lowered in codegen to nothing or a call to panic_nounwind. So if we encounter any
             // of those intrinsics, we need to include a mono item for panic_nounwind, else we may try to
             // codegen a call to that function without generating code for the function itself.
-            let def_id = tcx.lang_items().get(LangItem::PanicNounwind).unwrap();
+            let def_id = tcx.require_lang_item(LangItem::PanicNounwind, None);
             let panic_instance = Instance::mono(tcx, def_id);
             if should_codegen_locally(tcx, panic_instance) {
                 output.push(create_fn_mono_item(tcx, panic_instance, source));
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 336341f4e74..14b5b22dc64 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -104,6 +104,7 @@ use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathDataName;
+use rustc_hir::LangItem;
 use rustc_middle::bug;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
@@ -813,7 +814,7 @@ fn mono_item_visibility<'tcx>(
     //        from the `main` symbol we'll generate later.
     //
     //        This may be fixable with a new `InstanceDef` perhaps? Unsure!
-    if tcx.lang_items().start_fn() == Some(def_id) {
+    if tcx.is_lang_item(def_id, LangItem::Start) {
         *can_be_internalized = false;
         return Visibility::Hidden;
     }
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index a3ca9e9f9cf..c187cb63ee1 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -261,7 +261,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
         self.super_local_decl(local, local_decl);
     }
 
-    fn visit_constant(&mut self, ct: &mir::ConstOperand<'tcx>, location: Location) {
+    fn visit_const_operand(&mut self, ct: &mir::ConstOperand<'tcx>, location: Location) {
         match ct.const_ {
             mir::Const::Ty(_, c) => {
                 c.visit_with(self);
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 2cb3c5d8965..6a74ddc5508 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -472,7 +472,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                             && let ItemKind::Impl(impl_ref) =
                                 self.tcx.hir().expect_item(local_impl_id).kind
                         {
-                            if matches!(trait_item.kind, hir::TraitItemKind::Fn(..))
+                            if !matches!(trait_item.kind, hir::TraitItemKind::Type(..))
                                 && !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
                                     .ty_and_all_fields_are_public
                             {
@@ -802,7 +802,7 @@ fn check_item<'tcx>(
             // And we access the Map here to get HirId from LocalDefId
             for local_def_id in local_def_ids {
                 // check the function may construct Self
-                let mut may_construct_self = true;
+                let mut may_construct_self = false;
                 if let Some(fn_sig) =
                     tcx.hir().fn_sig_by_hir_id(tcx.local_def_id_to_hir_id(local_def_id))
                 {
@@ -898,7 +898,7 @@ fn create_and_seed_worklist(
                     match tcx.def_kind(id) {
                         DefKind::Impl { .. } => false,
                         DefKind::AssocConst | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer),
-                        DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()),
+                        DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(),
                         _ => true
                     })
                 .map(|id| (id, ComesFromAllowExpect::No))
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index d1541527cf5..8d470c6c61e 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -2783,33 +2783,65 @@ fn show_candidates(
     // by iterating through a hash map, so make sure they are ordered:
     for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
         path_strings.sort_by(|a, b| a.0.cmp(&b.0));
+        path_strings.dedup_by(|a, b| a.0 == b.0);
         let core_path_strings =
             path_strings.extract_if(|p| p.0.starts_with("core::")).collect::<Vec<_>>();
-        path_strings.extend(core_path_strings);
-        path_strings.dedup_by(|a, b| a.0 == b.0);
+        let std_path_strings =
+            path_strings.extract_if(|p| p.0.starts_with("std::")).collect::<Vec<_>>();
+        let foreign_crate_path_strings =
+            path_strings.extract_if(|p| !p.0.starts_with("crate::")).collect::<Vec<_>>();
+
+        // We list the `crate` local paths first.
+        // Then we list the `std`/`core` paths.
+        if std_path_strings.len() == core_path_strings.len() {
+            // Do not list `core::` paths if we are already listing the `std::` ones.
+            path_strings.extend(std_path_strings);
+        } else {
+            path_strings.extend(std_path_strings);
+            path_strings.extend(core_path_strings);
+        }
+        // List all paths from foreign crates last.
+        path_strings.extend(foreign_crate_path_strings);
     }
-    accessible_path_strings.sort();
 
     if !accessible_path_strings.is_empty() {
-        let (determiner, kind, name, through) =
+        let (determiner, kind, s, name, through) =
             if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
                 (
                     "this",
                     *descr,
+                    "",
                     format!(" `{name}`"),
                     if *via_import { " through its public re-export" } else { "" },
                 )
             } else {
-                ("one of these", "items", String::new(), "")
+                // Get the unique item kinds and if there's only one, we use the right kind name
+                // instead of the more generic "items".
+                let mut kinds = accessible_path_strings
+                    .iter()
+                    .map(|(_, descr, _, _, _)| *descr)
+                    .collect::<FxHashSet<&str>>()
+                    .into_iter();
+                let kind = if let Some(kind) = kinds.next()
+                    && let None = kinds.next()
+                {
+                    kind
+                } else {
+                    "item"
+                };
+                let s = if kind.ends_with('s') { "es" } else { "s" };
+
+                ("one of these", kind, s, String::new(), "")
             };
 
         let instead = if let Instead::Yes = instead { " instead" } else { "" };
         let mut msg = if let DiagMode::Pattern = mode {
             format!(
-                "if you meant to match on {kind}{instead}{name}, use the full path in the pattern",
+                "if you meant to match on {kind}{s}{instead}{name}, use the full path in the \
+                 pattern",
             )
         } else {
-            format!("consider importing {determiner} {kind}{through}{instead}")
+            format!("consider importing {determiner} {kind}{s}{through}{instead}")
         };
 
         for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index b0adc3775f6..fa711d932b6 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -3281,17 +3281,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         }
         self.visit_path(&delegation.path, delegation.id);
         if let Some(body) = &delegation.body {
-            // `PatBoundCtx` is not necessary in this context
-            let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
-
-            let span = delegation.path.segments.last().unwrap().ident.span;
-            self.fresh_binding(
-                Ident::new(kw::SelfLower, span),
-                delegation.id,
-                PatternSource::FnParam,
-                &mut bindings,
-            );
-            self.visit_block(body);
+            self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
+                // `PatBoundCtx` is not necessary in this context
+                let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
+
+                let span = delegation.path.segments.last().unwrap().ident.span;
+                this.fresh_binding(
+                    Ident::new(kw::SelfLower, span),
+                    delegation.id,
+                    PatternSource::FnParam,
+                    &mut bindings,
+                );
+                this.visit_block(body);
+            });
         }
     }
 
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 9eeb0da7ed2..be24755d4c5 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1021,12 +1021,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             },
         );
         let is_assoc_fn = self.self_type_is_available();
+        let self_from_macro = "a `self` parameter, but a macro invocation can only \
+                               access identifiers it receives from parameters";
         if let Some((fn_kind, span)) = &self.diag_metadata.current_function {
             // The current function has a `self` parameter, but we were unable to resolve
             // a reference to `self`. This can only happen if the `self` identifier we
             // are resolving came from a different hygiene context.
             if fn_kind.decl().inputs.get(0).is_some_and(|p| p.is_self()) {
-                err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters");
+                err.span_label(*span, format!("this function has {self_from_macro}"));
             } else {
                 let doesnt = if is_assoc_fn {
                     let (span, sugg) = fn_kind
@@ -1068,14 +1070,18 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 }
             }
         } else if let Some(item_kind) = self.diag_metadata.current_item {
-            err.span_label(
-                item_kind.ident.span,
-                format!(
-                    "`self` not allowed in {} {}",
-                    item_kind.kind.article(),
-                    item_kind.kind.descr()
-                ),
-            );
+            if matches!(item_kind.kind, ItemKind::Delegation(..)) {
+                err.span_label(item_kind.span, format!("delegation supports {self_from_macro}"));
+            } else {
+                err.span_label(
+                    item_kind.ident.span,
+                    format!(
+                        "`self` not allowed in {} {}",
+                        item_kind.kind.article(),
+                        item_kind.kind.descr()
+                    ),
+                );
+            }
         }
         true
     }
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
index 2fbfb93150e..2cb0c06e336 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -289,7 +289,7 @@ pub fn transform_instance<'tcx>(
     options: TransformTyOptions,
 ) -> Instance<'tcx> {
     if (matches!(instance.def, ty::InstanceDef::Virtual(..))
-        && Some(instance.def_id()) == tcx.lang_items().drop_in_place_fn())
+        && tcx.is_lang_item(instance.def_id(), LangItem::DropInPlace))
         || matches!(instance.def, ty::InstanceDef::DropGlue(..))
     {
         // Adjust the type ids of DropGlues
diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/rustc_smir/builder.rs
index 221224eed01..577373cbc95 100644
--- a/compiler/rustc_smir/src/rustc_smir/builder.rs
+++ b/compiler/rustc_smir/src/rustc_smir/builder.rs
@@ -52,7 +52,11 @@ impl<'tcx> BodyBuilder<'tcx> {
 }
 
 impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
-    fn visit_constant(&mut self, constant: &mut mir::ConstOperand<'tcx>, location: mir::Location) {
+    fn visit_const_operand(
+        &mut self,
+        constant: &mut mir::ConstOperand<'tcx>,
+        location: mir::Location,
+    ) {
         let const_ = constant.const_;
         let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), constant.span) {
             Ok(v) => v,
@@ -63,7 +67,7 @@ impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> {
         };
         let ty = constant.ty();
         constant.const_ = mir::Const::Val(val, ty);
-        self.super_constant(constant, location);
+        self.super_const_operand(constant, location);
     }
 
     fn tcx(&self) -> TyCtxt<'tcx> {
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index a8688c88601..4348bc31bf9 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -6,6 +6,7 @@
 #![allow(rustc::usage_of_qualified_ty)]
 
 use rustc_abi::HasDataLayout;
+use rustc_hir::LangItem;
 use rustc_middle::ty::layout::{
     FnAbiOf, FnAbiOfHelpers, HasParamEnv, HasTyCtxt, LayoutOf, LayoutOfHelpers,
 };
@@ -63,9 +64,10 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
     }
 
     fn has_body(&self, def: DefId) -> bool {
-        let tables = self.0.borrow();
-        let def_id = tables[def];
-        tables.tcx.is_mir_available(def_id)
+        let mut tables = self.0.borrow_mut();
+        let tcx = tables.tcx;
+        let def_id = def.internal(&mut *tables, tcx);
+        tables.item_has_body(def_id)
     }
 
     fn foreign_modules(&self, crate_num: CrateNum) -> Vec<stable_mir::ty::ForeignModuleDef> {
@@ -295,7 +297,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         let def_id = def.0.internal(&mut *tables, tcx);
-        tables.tcx.lang_items().c_str() == Some(def_id)
+        tables.tcx.is_lang_item(def_id, LangItem::CStr)
     }
 
     fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
@@ -322,13 +324,6 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         tcx.intrinsic(def_id).unwrap().name.to_string()
     }
 
-    fn intrinsic_must_be_overridden(&self, def: IntrinsicDef) -> bool {
-        let mut tables = self.0.borrow_mut();
-        let tcx = tables.tcx;
-        let def_id = def.0.internal(&mut *tables, tcx);
-        tcx.intrinsic_raw(def_id).unwrap().must_be_overridden
-    }
-
     fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
@@ -515,7 +510,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let mut tables = self.0.borrow_mut();
         let instance = tables.instances[def];
         tables
-            .has_body(instance)
+            .instance_has_body(instance)
             .then(|| BodyBuilder::new(tables.tcx, instance).build(&mut *tables))
     }
 
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index bcacf54baf3..f15b82d0c03 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -328,13 +328,13 @@ impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
 }
 
 impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> {
-    type T = stable_mir::mir::Constant;
+    type T = stable_mir::mir::ConstOperand;
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        stable_mir::mir::Constant {
+        stable_mir::mir::ConstOperand {
             span: self.span.stable(tables),
             user_ty: self.user_ty.map(|u| u.as_usize()).or(None),
-            literal: self.const_.stable(tables),
+            const_: self.const_.stable(tables),
         }
     }
 }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index 73bc87dc9ab..e3cd7187e77 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -866,10 +866,10 @@ impl<'tcx> Stable<'tcx> for ty::Variance {
     type T = stable_mir::mir::Variance;
     fn stable(&self, _: &mut Tables<'_>) -> Self::T {
         match self {
-            ty::Variance::Bivariant => stable_mir::mir::Variance::Bivariant,
-            ty::Variance::Contravariant => stable_mir::mir::Variance::Contravariant,
-            ty::Variance::Covariant => stable_mir::mir::Variance::Covariant,
-            ty::Variance::Invariant => stable_mir::mir::Variance::Invariant,
+            ty::Bivariant => stable_mir::mir::Variance::Bivariant,
+            ty::Contravariant => stable_mir::mir::Variance::Contravariant,
+            ty::Covariant => stable_mir::mir::Variance::Covariant,
+            ty::Invariant => stable_mir::mir::Variance::Invariant,
         }
     }
 }
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index d13e7803326..89f9adfcfd6 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -51,9 +51,13 @@ impl<'tcx> Tables<'tcx> {
         self.mir_consts.create_or_fetch(constant)
     }
 
-    pub(crate) fn has_body(&self, instance: Instance<'tcx>) -> bool {
+    /// Return whether the instance as a body available.
+    ///
+    /// Items and intrinsics may have a body available from its definition.
+    /// Shims body may be generated depending on their type.
+    pub(crate) fn instance_has_body(&self, instance: Instance<'tcx>) -> bool {
         let def_id = instance.def_id();
-        self.tcx.is_mir_available(def_id)
+        self.item_has_body(def_id)
             || !matches!(
                 instance.def,
                 ty::InstanceDef::Virtual(..)
@@ -61,6 +65,19 @@ impl<'tcx> Tables<'tcx> {
                     | ty::InstanceDef::Item(..)
             )
     }
+
+    /// Return whether the item has a body defined by the user.
+    ///
+    /// Note that intrinsics may have a placeholder body that shouldn't be used in practice.
+    /// In StableMIR, we handle this case as if the body is not available.
+    pub(crate) fn item_has_body(&self, def_id: DefId) -> bool {
+        let must_override = if let Some(intrinsic) = self.tcx.intrinsic(def_id) {
+            intrinsic.must_be_overridden
+        } else {
+            false
+        };
+        !must_override && self.tcx.is_mir_available(def_id)
+    }
 }
 
 /// Build a stable mir crate from a given crate number.
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 99fcaf917fe..b7ffe6c618a 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -520,6 +520,7 @@ impl SpanData {
     pub fn with_hi(&self, hi: BytePos) -> Span {
         Span::new(self.lo, hi, self.ctxt, self.parent)
     }
+    /// Avoid if possible, `Span::map_ctxt` should be preferred.
     #[inline]
     fn with_ctxt(&self, ctxt: SyntaxContext) -> Span {
         Span::new(self.lo, self.hi, ctxt, self.parent)
@@ -576,9 +577,8 @@ impl Span {
         self.data().with_hi(hi)
     }
     #[inline]
-    pub fn with_ctxt(mut self, ctxt: SyntaxContext) -> Span {
-        self.update_ctxt(|_| ctxt);
-        self
+    pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
+        self.map_ctxt(|_| ctxt)
     }
     #[inline]
     pub fn parent(self) -> Option<LocalDefId> {
@@ -1059,9 +1059,8 @@ impl Span {
     }
 
     #[inline]
-    pub fn apply_mark(mut self, expn_id: ExpnId, transparency: Transparency) -> Span {
-        self.update_ctxt(|ctxt| ctxt.apply_mark(expn_id, transparency));
-        self
+    pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
+        self.map_ctxt(|ctxt| ctxt.apply_mark(expn_id, transparency))
     }
 
     #[inline]
@@ -1109,15 +1108,13 @@ impl Span {
     }
 
     #[inline]
-    pub fn normalize_to_macros_2_0(mut self) -> Span {
-        self.update_ctxt(|ctxt| ctxt.normalize_to_macros_2_0());
-        self
+    pub fn normalize_to_macros_2_0(self) -> Span {
+        self.map_ctxt(|ctxt| ctxt.normalize_to_macros_2_0())
     }
 
     #[inline]
-    pub fn normalize_to_macro_rules(mut self) -> Span {
-        self.update_ctxt(|ctxt| ctxt.normalize_to_macro_rules());
-        self
+    pub fn normalize_to_macro_rules(self) -> Span {
+        self.map_ctxt(|ctxt| ctxt.normalize_to_macro_rules())
     }
 }
 
diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs
index 52a1267f891..9d5bc5b0512 100644
--- a/compiler/rustc_span/src/span_encoding.rs
+++ b/compiler/rustc_span/src/span_encoding.rs
@@ -87,43 +87,150 @@ pub struct Span {
     ctxt_or_parent_or_marker: u16,
 }
 
-impl Span {
+// Convenience structures for all span formats.
+#[derive(Clone, Copy)]
+struct InlineCtxt {
+    lo: u32,
+    len: u16,
+    ctxt: u16,
+}
+
+#[derive(Clone, Copy)]
+struct InlineParent {
+    lo: u32,
+    len_with_tag: u16,
+    parent: u16,
+}
+
+#[derive(Clone, Copy)]
+struct PartiallyInterned {
+    index: u32,
+    ctxt: u16,
+}
+
+#[derive(Clone, Copy)]
+struct Interned {
+    index: u32,
+}
+
+impl InlineCtxt {
     #[inline]
-    fn data_inline_ctxt(self) -> SpanData {
-        let len = self.len_with_tag_or_marker as u32;
+    fn data(self) -> SpanData {
+        let len = self.len as u32;
         debug_assert!(len <= MAX_LEN);
         SpanData {
-            lo: BytePos(self.lo_or_index),
-            hi: BytePos(self.lo_or_index.debug_strict_add(len)),
-            ctxt: SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32),
+            lo: BytePos(self.lo),
+            hi: BytePos(self.lo.debug_strict_add(len)),
+            ctxt: SyntaxContext::from_u32(self.ctxt as u32),
             parent: None,
         }
     }
     #[inline]
-    fn data_inline_parent(self) -> SpanData {
-        let len = (self.len_with_tag_or_marker & !PARENT_TAG) as u32;
+    fn span(lo: u32, len: u16, ctxt: u16) -> Span {
+        Span { lo_or_index: lo, len_with_tag_or_marker: len, ctxt_or_parent_or_marker: ctxt }
+    }
+    #[inline]
+    fn from_span(span: Span) -> InlineCtxt {
+        let (lo, len, ctxt) =
+            (span.lo_or_index, span.len_with_tag_or_marker, span.ctxt_or_parent_or_marker);
+        InlineCtxt { lo, len, ctxt }
+    }
+}
+
+impl InlineParent {
+    #[inline]
+    fn data(self) -> SpanData {
+        let len = (self.len_with_tag & !PARENT_TAG) as u32;
         debug_assert!(len <= MAX_LEN);
-        let parent = LocalDefId {
-            local_def_index: DefIndex::from_u32(self.ctxt_or_parent_or_marker as u32),
-        };
         SpanData {
-            lo: BytePos(self.lo_or_index),
-            hi: BytePos(self.lo_or_index.debug_strict_add(len)),
+            lo: BytePos(self.lo),
+            hi: BytePos(self.lo.debug_strict_add(len)),
             ctxt: SyntaxContext::root(),
-            parent: Some(parent),
+            parent: Some(LocalDefId { local_def_index: DefIndex::from_u32(self.parent as u32) }),
         }
     }
     #[inline]
-    fn data_partially_interned(self) -> SpanData {
+    fn span(lo: u32, len: u16, parent: u16) -> Span {
+        let (lo_or_index, len_with_tag_or_marker, ctxt_or_parent_or_marker) =
+            (lo, PARENT_TAG | len, parent);
+        Span { lo_or_index, len_with_tag_or_marker, ctxt_or_parent_or_marker }
+    }
+    #[inline]
+    fn from_span(span: Span) -> InlineParent {
+        let (lo, len_with_tag, parent) =
+            (span.lo_or_index, span.len_with_tag_or_marker, span.ctxt_or_parent_or_marker);
+        InlineParent { lo, len_with_tag, parent }
+    }
+}
+
+impl PartiallyInterned {
+    #[inline]
+    fn data(self) -> SpanData {
         SpanData {
-            ctxt: SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32),
-            ..with_span_interner(|interner| interner.spans[self.lo_or_index as usize])
+            ctxt: SyntaxContext::from_u32(self.ctxt as u32),
+            ..with_span_interner(|interner| interner.spans[self.index as usize])
         }
     }
     #[inline]
-    fn data_interned(self) -> SpanData {
-        with_span_interner(|interner| interner.spans[self.lo_or_index as usize])
+    fn span(index: u32, ctxt: u16) -> Span {
+        let (lo_or_index, len_with_tag_or_marker, ctxt_or_parent_or_marker) =
+            (index, BASE_LEN_INTERNED_MARKER, ctxt);
+        Span { lo_or_index, len_with_tag_or_marker, ctxt_or_parent_or_marker }
+    }
+    #[inline]
+    fn from_span(span: Span) -> PartiallyInterned {
+        PartiallyInterned { index: span.lo_or_index, ctxt: span.ctxt_or_parent_or_marker }
+    }
+}
+
+impl Interned {
+    #[inline]
+    fn data(self) -> SpanData {
+        with_span_interner(|interner| interner.spans[self.index as usize])
+    }
+    #[inline]
+    fn span(index: u32) -> Span {
+        let (lo_or_index, len_with_tag_or_marker, ctxt_or_parent_or_marker) =
+            (index, BASE_LEN_INTERNED_MARKER, CTXT_INTERNED_MARKER);
+        Span { lo_or_index, len_with_tag_or_marker, ctxt_or_parent_or_marker }
     }
+    #[inline]
+    fn from_span(span: Span) -> Interned {
+        Interned { index: span.lo_or_index }
+    }
+}
+
+// This code is very hot, and converting span to an enum and matching on it doesn't optimize away
+// properly. So we are using a macro emulating such a match, but expand it directly to an if-else
+// chain.
+macro_rules! match_span_kind {
+    (
+        $span:expr,
+        InlineCtxt($span1:ident) => $arm1:expr,
+        InlineParent($span2:ident) => $arm2:expr,
+        PartiallyInterned($span3:ident) => $arm3:expr,
+        Interned($span4:ident) => $arm4:expr,
+    ) => {
+        if $span.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER {
+            if $span.len_with_tag_or_marker & PARENT_TAG == 0 {
+                // Inline-context format.
+                let $span1 = InlineCtxt::from_span($span);
+                $arm1
+            } else {
+                // Inline-parent format.
+                let $span2 = InlineParent::from_span($span);
+                $arm2
+            }
+        } else if $span.ctxt_or_parent_or_marker != CTXT_INTERNED_MARKER {
+            // Partially-interned format.
+            let $span3 = PartiallyInterned::from_span($span);
+            $arm3
+        } else {
+            // Interned format.
+            let $span4 = Interned::from_span($span);
+            $arm4
+        }
+    };
 }
 
 // `MAX_LEN` is chosen so that `PARENT_TAG | MAX_LEN` is distinct from
@@ -154,23 +261,13 @@ impl Span {
         let (len, ctxt32) = (hi.0 - lo.0, ctxt.as_u32());
         if len <= MAX_LEN {
             if ctxt32 <= MAX_CTXT && parent.is_none() {
-                // Inline-context format.
-                return Span {
-                    lo_or_index: lo.0,
-                    len_with_tag_or_marker: len as u16,
-                    ctxt_or_parent_or_marker: ctxt32 as u16,
-                };
+                return InlineCtxt::span(lo.0, len as u16, ctxt32 as u16);
             } else if ctxt32 == 0
                 && let Some(parent) = parent
                 && let parent32 = parent.local_def_index.as_u32()
                 && parent32 <= MAX_CTXT
             {
-                // Inline-parent format.
-                return Span {
-                    lo_or_index: lo.0,
-                    len_with_tag_or_marker: PARENT_TAG | len as u16,
-                    ctxt_or_parent_or_marker: parent32 as u16,
-                };
+                return InlineParent::span(lo.0, len as u16, parent32 as u16);
             }
         }
 
@@ -179,20 +276,10 @@ impl Span {
             with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt, parent }))
         };
         if ctxt32 <= MAX_CTXT {
-            // Partially-interned format.
-            Span {
-                // Interned ctxt should never be read, so it can use any value.
-                lo_or_index: index(SyntaxContext::from_u32(u32::MAX)),
-                len_with_tag_or_marker: BASE_LEN_INTERNED_MARKER,
-                ctxt_or_parent_or_marker: ctxt32 as u16,
-            }
+            // Interned ctxt should never be read, so it can use any value.
+            PartiallyInterned::span(index(SyntaxContext::from_u32(u32::MAX)), ctxt32 as u16)
         } else {
-            // Interned format.
-            Span {
-                lo_or_index: index(ctxt),
-                len_with_tag_or_marker: BASE_LEN_INTERNED_MARKER,
-                ctxt_or_parent_or_marker: CTXT_INTERNED_MARKER,
-            }
+            Interned::span(index(ctxt))
         }
     }
 
@@ -209,20 +296,12 @@ impl Span {
     /// This function must not be used outside the incremental engine.
     #[inline]
     pub fn data_untracked(self) -> SpanData {
-        if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER {
-            if self.len_with_tag_or_marker & PARENT_TAG == 0 {
-                // Inline-context format.
-                self.data_inline_ctxt()
-            } else {
-                // Inline-parent format.
-                self.data_inline_parent()
-            }
-        } else if self.ctxt_or_parent_or_marker != CTXT_INTERNED_MARKER {
-            // Partially-interned format.
-            self.data_partially_interned()
-        } else {
-            // Interned format.
-            self.data_interned()
+        match_span_kind! {
+            self,
+            InlineCtxt(span) => span.data(),
+            InlineParent(span) => span.data(),
+            PartiallyInterned(span) => span.data(),
+            Interned(span) => span.data(),
         }
     }
 
@@ -247,68 +326,57 @@ impl Span {
     // update doesn't change format. All non-inline or format changing scenarios require accessing
     // interner and can fall back to `Span::new`.
     #[inline]
-    pub fn update_ctxt(&mut self, update: impl FnOnce(SyntaxContext) -> SyntaxContext) {
+    pub fn map_ctxt(self, update: impl FnOnce(SyntaxContext) -> SyntaxContext) -> Span {
         let (updated_ctxt32, data);
-        if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER {
-            if self.len_with_tag_or_marker & PARENT_TAG == 0 {
-                // Inline-context format.
+        match_span_kind! {
+            self,
+            InlineCtxt(span) => {
                 updated_ctxt32 =
-                    update(SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32)).as_u32();
+                    update(SyntaxContext::from_u32(span.ctxt as u32)).as_u32();
                 // Any small new context including zero will preserve the format.
                 if updated_ctxt32 <= MAX_CTXT {
-                    self.ctxt_or_parent_or_marker = updated_ctxt32 as u16;
-                    return;
+                    return InlineCtxt::span(span.lo, span.len, updated_ctxt32 as u16);
                 }
-                data = self.data_inline_ctxt();
-            } else {
-                // Inline-parent format.
+                data = span.data();
+            },
+            InlineParent(span) => {
                 updated_ctxt32 = update(SyntaxContext::root()).as_u32();
                 // Only if the new context is zero the format will be preserved.
                 if updated_ctxt32 == 0 {
                     // Do nothing.
-                    return;
+                    return self;
                 }
-                data = self.data_inline_parent();
-            }
-        } else if self.ctxt_or_parent_or_marker != CTXT_INTERNED_MARKER {
-            // Partially-interned format.
-            updated_ctxt32 =
-                update(SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32)).as_u32();
-            // Any small new context excluding zero will preserve the format.
-            // Zero may change the format to `InlineParent` if parent and len are small enough.
-            if updated_ctxt32 <= MAX_CTXT && updated_ctxt32 != 0 {
-                self.ctxt_or_parent_or_marker = updated_ctxt32 as u16;
-                return;
-            }
-            data = self.data_partially_interned();
-        } else {
-            // Interned format.
-            data = self.data_interned();
-            updated_ctxt32 = update(data.ctxt).as_u32();
+                data = span.data();
+            },
+            PartiallyInterned(span) => {
+                updated_ctxt32 = update(SyntaxContext::from_u32(span.ctxt as u32)).as_u32();
+                // Any small new context excluding zero will preserve the format.
+                // Zero may change the format to `InlineParent` if parent and len are small enough.
+                if updated_ctxt32 <= MAX_CTXT && updated_ctxt32 != 0 {
+                    return PartiallyInterned::span(span.index, updated_ctxt32 as u16);
+                }
+                data = span.data();
+            },
+            Interned(span) => {
+                data = span.data();
+                updated_ctxt32 = update(data.ctxt).as_u32();
+            },
         }
 
         // We could not keep the span in the same inline format, fall back to the complete logic.
-        *self = data.with_ctxt(SyntaxContext::from_u32(updated_ctxt32));
+        data.with_ctxt(SyntaxContext::from_u32(updated_ctxt32))
     }
 
     // Returns either syntactic context, if it can be retrieved without taking the interner lock,
     // or an index into the interner if it cannot.
     #[inline]
     fn inline_ctxt(self) -> Result<SyntaxContext, usize> {
-        if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER {
-            if self.len_with_tag_or_marker & PARENT_TAG == 0 {
-                // Inline-context format.
-                Ok(SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32))
-            } else {
-                // Inline-parent format.
-                Ok(SyntaxContext::root())
-            }
-        } else if self.ctxt_or_parent_or_marker != CTXT_INTERNED_MARKER {
-            // Partially-interned format.
-            Ok(SyntaxContext::from_u32(self.ctxt_or_parent_or_marker as u32))
-        } else {
-            // Interned format.
-            Err(self.lo_or_index as usize)
+        match_span_kind! {
+            self,
+            InlineCtxt(span) => Ok(SyntaxContext::from_u32(span.ctxt as u32)),
+            InlineParent(_span) => Ok(SyntaxContext::root()),
+            PartiallyInterned(span) => Ok(SyntaxContext::from_u32(span.ctxt as u32)),
+            Interned(span) => Err(span.index as usize),
         }
     }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index e245dfb9f5d..f44fa1bcb4f 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -635,7 +635,9 @@ symbols! {
         coroutine,
         coroutine_clone,
         coroutine_resume,
+        coroutine_return,
         coroutine_state,
+        coroutine_yield,
         coroutines,
         cosf128,
         cosf16,
@@ -1116,6 +1118,7 @@ symbols! {
         macro_lifetime_matcher,
         macro_literal_matcher,
         macro_metavar_expr,
+        macro_metavar_expr_concat,
         macro_reexport,
         macro_use,
         macro_vis_matcher,
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index 5f4ce5ed599..b057bf94a08 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -707,15 +707,19 @@ pub enum InlineAsmType {
     I32,
     I64,
     I128,
+    F16,
     F32,
     F64,
+    F128,
     VecI8(u64),
     VecI16(u64),
     VecI32(u64),
     VecI64(u64),
     VecI128(u64),
+    VecF16(u64),
     VecF32(u64),
     VecF64(u64),
+    VecF128(u64),
 }
 
 impl InlineAsmType {
@@ -730,15 +734,19 @@ impl InlineAsmType {
             Self::I32 => 4,
             Self::I64 => 8,
             Self::I128 => 16,
+            Self::F16 => 2,
             Self::F32 => 4,
             Self::F64 => 8,
+            Self::F128 => 16,
             Self::VecI8(n) => n * 1,
             Self::VecI16(n) => n * 2,
             Self::VecI32(n) => n * 4,
             Self::VecI64(n) => n * 8,
             Self::VecI128(n) => n * 16,
+            Self::VecF16(n) => n * 2,
             Self::VecF32(n) => n * 4,
             Self::VecF64(n) => n * 8,
+            Self::VecF128(n) => n * 16,
         })
     }
 }
@@ -751,15 +759,19 @@ impl fmt::Display for InlineAsmType {
             Self::I32 => f.write_str("i32"),
             Self::I64 => f.write_str("i64"),
             Self::I128 => f.write_str("i128"),
+            Self::F16 => f.write_str("f16"),
             Self::F32 => f.write_str("f32"),
             Self::F64 => f.write_str("f64"),
+            Self::F128 => f.write_str("f128"),
             Self::VecI8(n) => write!(f, "i8x{n}"),
             Self::VecI16(n) => write!(f, "i16x{n}"),
             Self::VecI32(n) => write!(f, "i32x{n}"),
             Self::VecI64(n) => write!(f, "i64x{n}"),
             Self::VecI128(n) => write!(f, "i128x{n}"),
+            Self::VecF16(n) => write!(f, "f16x{n}"),
             Self::VecF32(n) => write!(f, "f32x{n}"),
             Self::VecF64(n) => write!(f, "f64x{n}"),
+            Self::VecF128(n) => write!(f, "f128x{n}"),
         }
     }
 }
diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs
index 28413a5bcbd..8452961c17c 100644
--- a/compiler/rustc_target/src/asm/x86.rs
+++ b/compiler/rustc_target/src/asm/x86.rs
@@ -107,26 +107,26 @@ impl X86InlineAsmRegClass {
         match self {
             Self::reg | Self::reg_abcd => {
                 if arch == InlineAsmArch::X86_64 {
-                    types! { _: I16, I32, I64, F32, F64; }
+                    types! { _: I16, I32, I64, F16, F32, F64; }
                 } else {
-                    types! { _: I16, I32, F32; }
+                    types! { _: I16, I32, F16, F32; }
                 }
             }
             Self::reg_byte => types! { _: I8; },
             Self::xmm_reg => types! {
-                sse: I32, I64, F32, F64,
-                  VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
+                sse: I32, I64, F16, F32, F64, F128,
+                  VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2);
             },
             Self::ymm_reg => types! {
-                avx: I32, I64, F32, F64,
-                    VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2),
-                    VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF32(8), VecF64(4);
+                avx: I32, I64, F16, F32, F64, F128,
+                    VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2),
+                    VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF16(16), VecF32(8), VecF64(4);
             },
             Self::zmm_reg => types! {
-                avx512f: I32, I64, F32, F64,
-                    VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2),
-                    VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF32(8), VecF64(4),
-                    VecI8(64), VecI16(32), VecI32(16), VecI64(8), VecF32(16), VecF64(8);
+                avx512f: I32, I64, F16, F32, F64, F128,
+                    VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2),
+                    VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF16(16), VecF32(8), VecF64(4),
+                    VecI8(64), VecI16(32), VecI32(16), VecI64(8), VecF16(32), VecF32(16), VecF64(8);
             },
             Self::kreg => types! {
                 avx512f: I8, I16;
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
index f15a8798940..3e88180012e 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "loongarch64".into(),
         options: TargetOptions {
             cpu: "generic".into(),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
index 032a29708d1..c45bc438350 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "loongarch64".into(),
         options: TargetOptions {
             cpu: "generic".into(),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
index b2bfc8e4272..69533e82c3c 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "loongarch64".into(),
         options: TargetOptions {
             cpu: "generic".into(),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
index 02e44c187ab..bc4c5bcde5e 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
             std: None,
         },
         pointer_width: 64,
-        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "loongarch64".into(),
         options: TargetOptions {
             cpu: "generic".into(),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
index 7cbe9f09e6c..4c2d222b590 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
@@ -18,6 +18,7 @@ pub fn target() -> Target {
     let mut options = base::wasm::options();
 
     options.os = "wasi".into();
+    options.env = "p1".into();
     options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::Yes), &["--target=wasm32-wasi"]);
 
     options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained();
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs
index c592b944d44..38af48ab266 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
     let mut options = base::wasm::options();
 
     options.os = "wasi".into();
+    options.env = "p1".into();
 
     options.add_pre_link_args(
         LinkerFlavor::WasmLld(Cc::No),
diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
index 4d7e2fc2cef..4e52caa5a5b 100644
--- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs
+++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
@@ -48,6 +48,12 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
             rhs
         };
 
+        // Add a `make_canonical_response` probe step so that we treat this as
+        // a candidate, even if `try_evaluate_added_goals` bails due to an error.
+        // It's `Certainty::AMBIGUOUS` because this candidate is not "finished",
+        // since equating the normalized terms will lead to additional constraints.
+        self.inspect.make_canonical_response(Certainty::AMBIGUOUS);
+
         // Apply the constraints.
         self.try_evaluate_added_goals()?;
         let lhs = self.resolve_vars_if_possible(lhs);
@@ -55,8 +61,8 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         trace!(?lhs, ?rhs);
 
         let variance = match direction {
-            ty::AliasRelationDirection::Equate => ty::Variance::Invariant,
-            ty::AliasRelationDirection::Subtype => ty::Variance::Covariant,
+            ty::AliasRelationDirection::Equate => ty::Invariant,
+            ty::AliasRelationDirection::Subtype => ty::Covariant,
         };
         match (lhs.to_alias_term(), rhs.to_alias_term()) {
             (None, None) => {
@@ -72,7 +78,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
                 self.relate_rigid_alias_non_alias(
                     param_env,
                     alias,
-                    variance.xform(ty::Variance::Contravariant),
+                    variance.xform(ty::Contravariant),
                     lhs,
                 )?;
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index b51efd339c4..72cdfb5e57b 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -1,20 +1,21 @@
 //! Code shared by trait and projection goals for candidate assembly.
 
+use derivative::Derivative;
 use rustc_hir::def_id::DefId;
+use rustc_hir::LangItem;
 use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::query::NoSolution;
 use rustc_middle::bug;
 use rustc_middle::traits::solve::inspect::ProbeKind;
-use rustc_middle::traits::solve::{
-    CandidateSource, CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult,
-};
+use rustc_middle::traits::solve::{Certainty, Goal, MaybeCause, QueryResult};
 use rustc_middle::traits::BuiltinImplSource;
 use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{fast_reject, TypeFoldable};
 use rustc_middle::ty::{TypeVisitableExt, Upcast};
 use rustc_span::{ErrorGuaranteed, DUMMY_SP};
-use std::fmt::Debug;
+use rustc_type_ir::solve::{CandidateSource, CanonicalResponse};
+use rustc_type_ir::Interner;
 
 use crate::solve::GoalSource;
 use crate::solve::{EvalCtxt, SolverMode};
@@ -25,10 +26,11 @@ pub(super) mod structural_traits;
 ///
 /// It consists of both the `source`, which describes how that goal would be proven,
 /// and the `result` when using the given `source`.
-#[derive(Debug, Clone)]
-pub(super) struct Candidate<'tcx> {
-    pub(super) source: CandidateSource<'tcx>,
-    pub(super) result: CanonicalResponse<'tcx>,
+#[derive(Derivative)]
+#[derivative(Debug(bound = ""), Clone(bound = ""))]
+pub(super) struct Candidate<I: Interner> {
+    pub(super) source: CandidateSource<I>,
+    pub(super) result: CanonicalResponse<I>,
 }
 
 /// Methods used to assemble candidates for either trait or projection goals.
@@ -49,22 +51,22 @@ pub(super) trait GoalKind<'tcx>:
     /// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]).
     fn probe_and_match_goal_against_assumption(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
-        source: CandidateSource<'tcx>,
+        source: CandidateSource<TyCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
         assumption: ty::Clause<'tcx>,
         then: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> QueryResult<'tcx>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// Consider a clause, which consists of a "assumption" and some "requirements",
     /// to satisfy a goal. If the requirements hold, then attempt to satisfy our
     /// goal by equating it with the assumption.
     fn probe_and_consider_implied_clause(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
-        parent_source: CandidateSource<'tcx>,
+        parent_source: CandidateSource<TyCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
         assumption: ty::Clause<'tcx>,
         requirements: impl IntoIterator<Item = (GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         Self::probe_and_match_goal_against_assumption(ecx, parent_source, goal, assumption, |ecx| {
             for (nested_source, goal) in requirements {
                 ecx.add_goal(nested_source, goal);
@@ -78,10 +80,10 @@ pub(super) trait GoalKind<'tcx>:
     /// since they're not implied by the well-formedness of the object type.
     fn probe_and_consider_object_bound_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
-        source: CandidateSource<'tcx>,
+        source: CandidateSource<TyCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
         assumption: ty::Clause<'tcx>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
             let tcx = ecx.interner();
             let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
@@ -104,7 +106,7 @@ pub(super) trait GoalKind<'tcx>:
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
         impl_def_id: DefId,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// If the predicate contained an error, we want to avoid emitting unnecessary trait
     /// errors but still want to emit errors for other trait goals. We have some special
@@ -115,7 +117,7 @@ pub(super) trait GoalKind<'tcx>:
     fn consider_error_guaranteed_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         guar: ErrorGuaranteed,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A type implements an `auto trait` if its components do as well.
     ///
@@ -124,13 +126,13 @@ pub(super) trait GoalKind<'tcx>:
     fn consider_auto_trait_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A trait alias holds if the RHS traits and `where` clauses hold.
     fn consider_trait_alias_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A type is `Sized` if its tail component is `Sized`.
     ///
@@ -139,7 +141,7 @@ pub(super) trait GoalKind<'tcx>:
     fn consider_builtin_sized_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`.
     ///
@@ -148,20 +150,20 @@ pub(super) trait GoalKind<'tcx>:
     fn consider_builtin_copy_clone_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A type is `PointerLike` if we can compute its layout, and that layout
     /// matches the layout of `usize`.
     fn consider_builtin_pointer_like_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A type is a `FnPtr` if it is of `FnPtr` type.
     fn consider_builtin_fn_ptr_trait_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>`
     /// family of traits where `A` is given by the signature of the type.
@@ -169,7 +171,7 @@ pub(super) trait GoalKind<'tcx>:
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
         kind: ty::ClosureKind,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// An async closure is known to implement the `AsyncFn<A>` family of traits
     /// where `A` is given by the signature of the type.
@@ -177,7 +179,7 @@ pub(super) trait GoalKind<'tcx>:
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
         kind: ty::ClosureKind,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// Compute the built-in logic of the `AsyncFnKindHelper` helper trait, which
     /// is used internally to delay computation for async closures until after
@@ -185,13 +187,13 @@ pub(super) trait GoalKind<'tcx>:
     fn consider_builtin_async_fn_kind_helper_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// `Tuple` is implemented if the `Self` type is a tuple.
     fn consider_builtin_tuple_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// `Pointee` is always implemented.
     ///
@@ -201,7 +203,7 @@ pub(super) trait GoalKind<'tcx>:
     fn consider_builtin_pointee_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A coroutine (that comes from an `async` desugaring) is known to implement
     /// `Future<Output = O>`, where `O` is given by the coroutine's return type
@@ -209,7 +211,7 @@ pub(super) trait GoalKind<'tcx>:
     fn consider_builtin_future_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A coroutine (that comes from a `gen` desugaring) is known to implement
     /// `Iterator<Item = O>`, where `O` is given by the generator's yield type
@@ -217,19 +219,19 @@ pub(super) trait GoalKind<'tcx>:
     fn consider_builtin_iterator_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A coroutine (that comes from a `gen` desugaring) is known to implement
     /// `FusedIterator`
     fn consider_builtin_fused_iterator_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     fn consider_builtin_async_iterator_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// A coroutine (that doesn't come from an `async` or `gen` desugaring) is known to
     /// implement `Coroutine<R, Yield = Y, Return = O>`, given the resume, yield,
@@ -237,27 +239,27 @@ pub(super) trait GoalKind<'tcx>:
     fn consider_builtin_coroutine_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     fn consider_builtin_discriminant_kind_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     fn consider_builtin_async_destruct_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     fn consider_builtin_destruct_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     fn consider_builtin_transmute_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution>;
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;
 
     /// Consider (possibly several) candidates to upcast or unsize a type to another
     /// type, excluding the coercion of a sized type into a `dyn Trait`.
@@ -269,14 +271,14 @@ pub(super) trait GoalKind<'tcx>:
     fn consider_structural_builtin_unsize_candidates(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Vec<Candidate<'tcx>>;
+    ) -> Vec<Candidate<TyCtxt<'tcx>>>;
 }
 
 impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
-    ) -> Vec<Candidate<'tcx>> {
+    ) -> Vec<Candidate<TyCtxt<'tcx>>> {
         let Ok(normalized_self_ty) =
             self.structurally_normalize_ty(goal.param_env, goal.predicate.self_ty())
         else {
@@ -323,7 +325,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     pub(super) fn forced_ambiguity(
         &mut self,
         cause: MaybeCause,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         // This may fail if `try_evaluate_added_goals` overflows because it
         // fails to reach a fixpoint but ends up getting an error after
         // running for some additional step.
@@ -339,7 +341,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     fn assemble_non_blanket_impl_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
-        candidates: &mut Vec<Candidate<'tcx>>,
+        candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
     ) {
         let tcx = self.interner();
         let self_ty = goal.predicate.self_ty();
@@ -455,7 +457,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     fn assemble_blanket_impl_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
-        candidates: &mut Vec<Candidate<'tcx>>,
+        candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
     ) {
         let tcx = self.interner();
         let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx));
@@ -478,10 +480,9 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     fn assemble_builtin_impl_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
-        candidates: &mut Vec<Candidate<'tcx>>,
+        candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
     ) {
         let tcx = self.interner();
-        let lang_items = tcx.lang_items();
         let trait_def_id = goal.predicate.trait_def_id(tcx);
 
         // N.B. When assembling built-in candidates for lang items that are also
@@ -497,43 +498,43 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
             G::consider_auto_trait_candidate(self, goal)
         } else if tcx.trait_is_alias(trait_def_id) {
             G::consider_trait_alias_candidate(self, goal)
-        } else if lang_items.sized_trait() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::Sized) {
             G::consider_builtin_sized_candidate(self, goal)
-        } else if lang_items.copy_trait() == Some(trait_def_id)
-            || lang_items.clone_trait() == Some(trait_def_id)
+        } else if tcx.is_lang_item(trait_def_id, LangItem::Copy)
+            || tcx.is_lang_item(trait_def_id, LangItem::Clone)
         {
             G::consider_builtin_copy_clone_candidate(self, goal)
-        } else if lang_items.pointer_like() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::PointerLike) {
             G::consider_builtin_pointer_like_candidate(self, goal)
-        } else if lang_items.fn_ptr_trait() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::FnPtrTrait) {
             G::consider_builtin_fn_ptr_trait_candidate(self, goal)
         } else if let Some(kind) = self.interner().fn_trait_kind_from_def_id(trait_def_id) {
             G::consider_builtin_fn_trait_candidates(self, goal, kind)
         } else if let Some(kind) = self.interner().async_fn_trait_kind_from_def_id(trait_def_id) {
             G::consider_builtin_async_fn_trait_candidates(self, goal, kind)
-        } else if lang_items.async_fn_kind_helper() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncFnKindHelper) {
             G::consider_builtin_async_fn_kind_helper_candidate(self, goal)
-        } else if lang_items.tuple_trait() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::Tuple) {
             G::consider_builtin_tuple_candidate(self, goal)
-        } else if lang_items.pointee_trait() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::PointeeTrait) {
             G::consider_builtin_pointee_candidate(self, goal)
-        } else if lang_items.future_trait() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::Future) {
             G::consider_builtin_future_candidate(self, goal)
-        } else if lang_items.iterator_trait() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::Iterator) {
             G::consider_builtin_iterator_candidate(self, goal)
-        } else if lang_items.fused_iterator_trait() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::FusedIterator) {
             G::consider_builtin_fused_iterator_candidate(self, goal)
-        } else if lang_items.async_iterator_trait() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncIterator) {
             G::consider_builtin_async_iterator_candidate(self, goal)
-        } else if lang_items.coroutine_trait() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::Coroutine) {
             G::consider_builtin_coroutine_candidate(self, goal)
-        } else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::DiscriminantKind) {
             G::consider_builtin_discriminant_kind_candidate(self, goal)
-        } else if lang_items.async_destruct_trait() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncDestruct) {
             G::consider_builtin_async_destruct_candidate(self, goal)
-        } else if lang_items.destruct_trait() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::Destruct) {
             G::consider_builtin_destruct_candidate(self, goal)
-        } else if lang_items.transmute_trait() == Some(trait_def_id) {
+        } else if tcx.is_lang_item(trait_def_id, LangItem::TransmuteTrait) {
             G::consider_builtin_transmute_candidate(self, goal)
         } else {
             Err(NoSolution)
@@ -543,7 +544,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
 
         // There may be multiple unsize candidates for a trait with several supertraits:
         // `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>`
-        if lang_items.unsize_trait() == Some(trait_def_id) {
+        if tcx.is_lang_item(trait_def_id, LangItem::Unsize) {
             candidates.extend(G::consider_structural_builtin_unsize_candidates(self, goal));
         }
     }
@@ -552,7 +553,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     fn assemble_param_env_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
-        candidates: &mut Vec<Candidate<'tcx>>,
+        candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
     ) {
         for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() {
             candidates.extend(G::probe_and_consider_implied_clause(
@@ -569,7 +570,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     fn assemble_alias_bound_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
-        candidates: &mut Vec<Candidate<'tcx>>,
+        candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
     ) {
         let () = self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| {
             ecx.assemble_alias_bound_candidates_recur(goal.predicate.self_ty(), goal, candidates);
@@ -589,7 +590,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         &mut self,
         self_ty: Ty<'tcx>,
         goal: Goal<'tcx, G>,
-        candidates: &mut Vec<Candidate<'tcx>>,
+        candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
     ) {
         let (kind, alias_ty) = match *self_ty.kind() {
             ty::Bool
@@ -673,7 +674,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     fn assemble_object_bound_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
-        candidates: &mut Vec<Candidate<'tcx>>,
+        candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
     ) {
         let tcx = self.interner();
         if !tcx.trait_def(goal.predicate.trait_def_id(tcx)).implement_via_object {
@@ -764,7 +765,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     fn assemble_coherence_unknowable_candidates<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
-        candidates: &mut Vec<Candidate<'tcx>>,
+        candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
     ) {
         let tcx = self.interner();
 
@@ -793,7 +794,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     fn discard_impls_shadowed_by_env<G: GoalKind<'tcx>>(
         &mut self,
         goal: Goal<'tcx, G>,
-        candidates: &mut Vec<Candidate<'tcx>>,
+        candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
     ) {
         let tcx = self.interner();
         let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> =
@@ -841,7 +842,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     #[instrument(level = "debug", skip(self), ret)]
     pub(super) fn merge_candidates(
         &mut self,
-        candidates: Vec<Candidate<'tcx>>,
+        candidates: Vec<Candidate<TyCtxt<'tcx>>>,
     ) -> QueryResult<'tcx> {
         // First try merging all candidates. This is complete and fully sound.
         let responses = candidates.iter().map(|c| c.result).collect::<Vec<_>>();
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 98f98d9992d..d6074617caf 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -1,14 +1,14 @@
 //! Code which is used by built-in goals that match "structurally", such a auto
 //! traits, `Copy`/`Clone`.
+
+use rustc_ast_ir::{Movability, Mutability};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::LangItem;
-use rustc_hir::{def_id::DefId, Movability, Mutability};
-use rustc_infer::infer::InferCtxt;
-use rustc_infer::traits::query::NoSolution;
-use rustc_macros::{TypeFoldable, TypeVisitable};
-use rustc_middle::bug;
-use rustc_middle::traits::solve::Goal;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, Upcast};
+use rustc_next_trait_solver::solve::{Goal, NoSolution};
+use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
+use rustc_type_ir::inherent::*;
+use rustc_type_ir::lang_items::TraitSolverLangItem;
+use rustc_type_ir::{self as ty, InferCtxtLike, Interner, Upcast};
+use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
 
 use crate::solve::EvalCtxt;
 
@@ -17,12 +17,16 @@ use crate::solve::EvalCtxt;
 // For types with an "existential" binder, i.e. coroutine witnesses, we also
 // instantiate the binder with placeholders eagerly.
 #[instrument(level = "trace", skip(ecx), ret)]
-pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
-    ecx: &EvalCtxt<'_, InferCtxt<'tcx>>,
-    ty: Ty<'tcx>,
-) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution> {
+pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<Infcx, I>(
+    ecx: &EvalCtxt<'_, Infcx>,
+    ty: I::Ty,
+) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution>
+where
+    Infcx: InferCtxtLike<Interner = I>,
+    I: Interner,
+{
     let tcx = ecx.interner();
-    match *ty.kind() {
+    match ty.kind() {
         ty::Uint(_)
         | ty::Int(_)
         | ty::Bool
@@ -34,7 +38,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
         | ty::Char => Ok(vec![]),
 
         // Treat `str` like it's defined as `struct str([u8]);`
-        ty::Str => Ok(vec![ty::Binder::dummy(Ty::new_slice(tcx, tcx.types.u8))]),
+        ty::Str => Ok(vec![ty::Binder::dummy(Ty::new_slice(tcx, Ty::new_u8(tcx)))]),
 
         ty::Dynamic(..)
         | ty::Param(..)
@@ -43,7 +47,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
         | ty::Placeholder(..)
         | ty::Bound(..)
         | ty::Infer(_) => {
-            bug!("unexpected type `{ty}`")
+            panic!("unexpected type `{ty:?}`")
         }
 
         ty::RawPtr(element_ty, _) | ty::Ref(_, element_ty, _) => {
@@ -56,7 +60,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
 
         ty::Tuple(tys) => {
             // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
-            Ok(tys.iter().map(ty::Binder::dummy).collect())
+            Ok(tys.into_iter().map(ty::Binder::dummy).collect())
         }
 
         ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]),
@@ -76,31 +80,38 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
         ty::CoroutineWitness(def_id, args) => Ok(ecx
             .interner()
             .bound_coroutine_hidden_types(def_id)
-            .map(|bty| bty.instantiate(tcx, args))
+            .into_iter()
+            .map(|bty| bty.instantiate(tcx, &args))
             .collect()),
 
         // For `PhantomData<T>`, we pass `T`.
         ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![ty::Binder::dummy(args.type_at(0))]),
 
-        ty::Adt(def, args) => {
-            Ok(def.all_fields().map(|f| ty::Binder::dummy(f.ty(tcx, args))).collect())
-        }
+        ty::Adt(def, args) => Ok(def
+            .all_field_tys(tcx)
+            .iter_instantiated(tcx, &args)
+            .map(ty::Binder::dummy)
+            .collect()),
 
         ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
             // We can resolve the `impl Trait` to its concrete type,
             // which enforces a DAG between the functions requiring
             // the auto trait bounds in question.
-            Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, args))])
+            Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, &args))])
         }
     }
 }
 
 #[instrument(level = "trace", skip(ecx), ret)]
-pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
-    ecx: &EvalCtxt<'_, InferCtxt<'tcx>>,
-    ty: Ty<'tcx>,
-) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution> {
-    match *ty.kind() {
+pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<Infcx, I>(
+    ecx: &EvalCtxt<'_, Infcx>,
+    ty: I::Ty,
+) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution>
+where
+    Infcx: InferCtxtLike<Interner = I>,
+    I: Interner,
+{
+    match ty.kind() {
         // impl Sized for u*, i*, bool, f*, FnDef, FnPtr, *(const/mut) T, char, &mut? T, [T; N], dyn* Trait, !
         // impl Sized for Coroutine, CoroutineWitness, Closure, CoroutineClosure
         ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
@@ -133,7 +144,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
 
         ty::Bound(..)
         | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
-            bug!("unexpected type `{ty}`")
+            panic!("unexpected type `{ty:?}`")
         }
 
         // impl Sized for ()
@@ -151,7 +162,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
         //   if the ADT is sized for all possible args.
         ty::Adt(def, args) => {
             if let Some(sized_crit) = def.sized_constraint(ecx.interner()) {
-                Ok(vec![ty::Binder::dummy(sized_crit.instantiate(ecx.interner(), args))])
+                Ok(vec![ty::Binder::dummy(sized_crit.instantiate(ecx.interner(), &args))])
             } else {
                 Ok(vec![])
             }
@@ -160,11 +171,15 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
 }
 
 #[instrument(level = "trace", skip(ecx), ret)]
-pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
-    ecx: &EvalCtxt<'_, InferCtxt<'tcx>>,
-    ty: Ty<'tcx>,
-) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution> {
-    match *ty.kind() {
+pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<Infcx, I>(
+    ecx: &EvalCtxt<'_, Infcx>,
+    ty: I::Ty,
+) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution>
+where
+    Infcx: InferCtxtLike<Interner = I>,
+    I: Interner,
+{
+    match ty.kind() {
         // impl Copy/Clone for FnDef, FnPtr
         ty::FnDef(..) | ty::FnPtr(_) | ty::Error(_) => Ok(vec![]),
 
@@ -196,11 +211,11 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
 
         ty::Bound(..)
         | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
-            bug!("unexpected type `{ty}`")
+            panic!("unexpected type `{ty:?}`")
         }
 
         // impl Copy/Clone for (T1, T2, .., Tn) where T1: Copy/Clone, T2: Copy/Clone, .. Tn: Copy/Clone
-        ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()),
+        ty::Tuple(tys) => Ok(tys.into_iter().map(ty::Binder::dummy).collect()),
 
         // impl Copy/Clone for Closure where Self::TupledUpvars: Copy/Clone
         ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]),
@@ -212,7 +227,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
         ty::Coroutine(def_id, args) => match ecx.interner().coroutine_movability(def_id) {
             Movability::Static => Err(NoSolution),
             Movability::Movable => {
-                if ecx.interner().features().coroutine_clone {
+                if ecx.interner().features().coroutine_clone() {
                     let coroutine = args.as_coroutine();
                     Ok(vec![
                         ty::Binder::dummy(coroutine.tupled_upvars_ty()),
@@ -228,27 +243,26 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
         ty::CoroutineWitness(def_id, args) => Ok(ecx
             .interner()
             .bound_coroutine_hidden_types(def_id)
-            .map(|bty| bty.instantiate(ecx.interner(), args))
+            .into_iter()
+            .map(|bty| bty.instantiate(ecx.interner(), &args))
             .collect()),
     }
 }
 
 // Returns a binder of the tupled inputs types and output type from a builtin callable type.
-pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    self_ty: Ty<'tcx>,
+pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Interner>(
+    tcx: I,
+    self_ty: I::Ty,
     goal_kind: ty::ClosureKind,
-) -> Result<Option<ty::Binder<'tcx, (Ty<'tcx>, Ty<'tcx>)>>, NoSolution> {
-    match *self_ty.kind() {
+) -> Result<Option<ty::Binder<I, (I::Ty, I::Ty)>>, NoSolution> {
+    match self_ty.kind() {
         // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
         ty::FnDef(def_id, args) => {
             let sig = tcx.fn_sig(def_id);
-            if sig.skip_binder().is_fn_trait_compatible()
-                && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
-            {
+            if sig.skip_binder().is_fn_trait_compatible() && !tcx.has_target_features(def_id) {
                 Ok(Some(
-                    sig.instantiate(tcx, args)
-                        .map_bound(|sig| (Ty::new_tup(tcx, sig.inputs()), sig.output())),
+                    sig.instantiate(tcx, &args)
+                        .map_bound(|sig| (Ty::new_tup(tcx, &sig.inputs()), sig.output())),
                 ))
             } else {
                 Err(NoSolution)
@@ -257,7 +271,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
         // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
         ty::FnPtr(sig) => {
             if sig.is_fn_trait_compatible() {
-                Ok(Some(sig.map_bound(|sig| (Ty::new_tup(tcx, sig.inputs()), sig.output()))))
+                Ok(Some(sig.map_bound(|sig| (Ty::new_tup(tcx, &sig.inputs()), sig.output()))))
             } else {
                 Err(NoSolution)
             }
@@ -311,7 +325,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
                     tcx,
                     goal_kind,
                     // No captures by ref, so this doesn't matter.
-                    tcx.lifetimes.re_static,
+                    Region::new_static(tcx),
                     def_id,
                     args,
                     sig,
@@ -326,7 +340,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
                 coroutine_closure_to_ambiguous_coroutine(
                     tcx,
                     goal_kind, // No captures by ref, so this doesn't matter.
-                    tcx.lifetimes.re_static,
+                    Region::new_static(tcx),
                     def_id,
                     args,
                     sig,
@@ -362,22 +376,24 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
 
         ty::Bound(..)
         | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
-            bug!("unexpected type `{self_ty}`")
+            panic!("unexpected type `{self_ty:?}`")
         }
     }
 }
 
 /// Relevant types for an async callable, including its inputs, output,
 /// and the return type you get from awaiting the output.
-#[derive(Copy, Clone, Debug, TypeVisitable, TypeFoldable)]
-pub(in crate::solve) struct AsyncCallableRelevantTypes<'tcx> {
-    pub tupled_inputs_ty: Ty<'tcx>,
+#[derive(derivative::Derivative)]
+#[derivative(Clone(bound = ""), Copy(bound = ""), Debug(bound = ""))]
+#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
+pub(in crate::solve) struct AsyncCallableRelevantTypes<I: Interner> {
+    pub tupled_inputs_ty: I::Ty,
     /// Type returned by calling the closure
     /// i.e. `f()`.
-    pub output_coroutine_ty: Ty<'tcx>,
+    pub output_coroutine_ty: I::Ty,
     /// Type returned by `await`ing the output
     /// i.e. `f().await`.
-    pub coroutine_return_ty: Ty<'tcx>,
+    pub coroutine_return_ty: I::Ty,
 }
 
 // Returns a binder of the tupled inputs types, output type, and coroutine type
@@ -385,16 +401,13 @@ pub(in crate::solve) struct AsyncCallableRelevantTypes<'tcx> {
 // the coroutine-closure, emit an additional trait predicate for `AsyncFnKindHelper`
 // which enforces the closure is actually callable with the given trait. When we
 // know the kind already, we can short-circuit this check.
-pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    self_ty: Ty<'tcx>,
+pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I: Interner>(
+    tcx: I,
+    self_ty: I::Ty,
     goal_kind: ty::ClosureKind,
-    env_region: ty::Region<'tcx>,
-) -> Result<
-    (ty::Binder<'tcx, AsyncCallableRelevantTypes<'tcx>>, Vec<ty::Predicate<'tcx>>),
-    NoSolution,
-> {
-    match *self_ty.kind() {
+    env_region: I::Region,
+) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
+    match self_ty.kind() {
         ty::CoroutineClosure(def_id, args) => {
             let args = args.as_coroutine_closure();
             let kind_ty = args.kind_ty();
@@ -421,7 +434,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                 nested.push(
                     ty::TraitRef::new(
                         tcx,
-                        tcx.require_lang_item(LangItem::AsyncFnKindHelper, None),
+                        tcx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper),
                         [kind_ty, Ty::from_closure_kind(tcx, goal_kind)],
                     )
                     .upcast(tcx),
@@ -445,7 +458,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
         ty::FnDef(..) | ty::FnPtr(..) => {
             let bound_sig = self_ty.fn_sig(tcx);
             let sig = bound_sig.skip_binder();
-            let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
+            let future_trait_def_id = tcx.require_lang_item(TraitSolverLangItem::Future);
             // `FnDef` and `FnPtr` only implement `AsyncFn*` when their
             // return type implements `Future`.
             let nested = vec![
@@ -453,11 +466,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                     .rebind(ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()]))
                     .upcast(tcx),
             ];
-            let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
+            let future_output_def_id = tcx.require_lang_item(TraitSolverLangItem::FutureOutput);
             let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
             Ok((
                 bound_sig.rebind(AsyncCallableRelevantTypes {
-                    tupled_inputs_ty: Ty::new_tup(tcx, sig.inputs()),
+                    tupled_inputs_ty: Ty::new_tup(tcx, &sig.inputs()),
                     output_coroutine_ty: sig.output(),
                     coroutine_return_ty: future_output_ty,
                 }),
@@ -468,7 +481,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
             let args = args.as_closure();
             let bound_sig = args.sig();
             let sig = bound_sig.skip_binder();
-            let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
+            let future_trait_def_id = tcx.require_lang_item(TraitSolverLangItem::Future);
             // `Closure`s only implement `AsyncFn*` when their return type
             // implements `Future`.
             let mut nested = vec![
@@ -486,7 +499,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                 }
             } else {
                 let async_fn_kind_trait_def_id =
-                    tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
+                    tcx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper);
                 // When we don't know the closure kind (and therefore also the closure's upvars,
                 // which are computed at the same time), we must delay the computation of the
                 // generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
@@ -504,7 +517,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                 );
             }
 
-            let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
+            let future_output_def_id = tcx.require_lang_item(TraitSolverLangItem::FutureOutput);
             let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
             Ok((
                 bound_sig.rebind(AsyncCallableRelevantTypes {
@@ -542,21 +555,21 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
 
         ty::Bound(..)
         | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
-            bug!("unexpected type `{self_ty}`")
+            panic!("unexpected type `{self_ty:?}`")
         }
     }
 }
 
 /// Given a coroutine-closure, project to its returned coroutine when we are *certain*
 /// that the closure's kind is compatible with the goal.
-fn coroutine_closure_to_certain_coroutine<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn coroutine_closure_to_certain_coroutine<I: Interner>(
+    tcx: I,
     goal_kind: ty::ClosureKind,
-    goal_region: ty::Region<'tcx>,
-    def_id: DefId,
-    args: ty::CoroutineClosureArgs<TyCtxt<'tcx>>,
-    sig: ty::CoroutineClosureSignature<TyCtxt<'tcx>>,
-) -> Ty<'tcx> {
+    goal_region: I::Region,
+    def_id: I::DefId,
+    args: ty::CoroutineClosureArgs<I>,
+    sig: ty::CoroutineClosureSignature<I>,
+) -> I::Ty {
     sig.to_coroutine_given_kind_and_upvars(
         tcx,
         args.parent_args(),
@@ -573,20 +586,20 @@ fn coroutine_closure_to_certain_coroutine<'tcx>(
 /// yet what the closure's upvars are.
 ///
 /// Note that we do not also push a `AsyncFnKindHelper` goal here.
-fn coroutine_closure_to_ambiguous_coroutine<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
+    tcx: I,
     goal_kind: ty::ClosureKind,
-    goal_region: ty::Region<'tcx>,
-    def_id: DefId,
-    args: ty::CoroutineClosureArgs<TyCtxt<'tcx>>,
-    sig: ty::CoroutineClosureSignature<TyCtxt<'tcx>>,
-) -> Ty<'tcx> {
-    let upvars_projection_def_id = tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None);
+    goal_region: I::Region,
+    def_id: I::DefId,
+    args: ty::CoroutineClosureArgs<I>,
+    sig: ty::CoroutineClosureSignature<I>,
+) -> I::Ty {
+    let upvars_projection_def_id = tcx.require_lang_item(TraitSolverLangItem::AsyncFnKindUpvars);
     let tupled_upvars_ty = Ty::new_projection(
         tcx,
         upvars_projection_def_id,
         [
-            ty::GenericArg::from(args.kind_ty()),
+            I::GenericArg::from(args.kind_ty()),
             Ty::from_closure_kind(tcx, goal_kind).into(),
             goal_region.into(),
             sig.tupled_inputs_ty.into(),
@@ -643,41 +656,44 @@ fn coroutine_closure_to_ambiguous_coroutine<'tcx>(
 // This is unsound in general and once that is fixed, we don't need to
 // normalize eagerly here. See https://github.com/lcnr/solver-woes/issues/9
 // for more details.
-pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
-    ecx: &EvalCtxt<'_, InferCtxt<'tcx>>,
-    param_env: ty::ParamEnv<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
-    object_bound: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-) -> Vec<Goal<'tcx, ty::Predicate<'tcx>>> {
+pub(in crate::solve) fn predicates_for_object_candidate<Infcx, I>(
+    ecx: &EvalCtxt<'_, Infcx>,
+    param_env: I::ParamEnv,
+    trait_ref: ty::TraitRef<I>,
+    object_bounds: I::BoundExistentialPredicates,
+) -> Vec<Goal<I, I::Predicate>>
+where
+    Infcx: InferCtxtLike<Interner = I>,
+    I: Interner,
+{
     let tcx = ecx.interner();
     let mut requirements = vec![];
-    requirements.extend(
-        tcx.super_predicates_of(trait_ref.def_id).instantiate(tcx, trait_ref.args).predicates,
-    );
-    for item in tcx.associated_items(trait_ref.def_id).in_definition_order() {
-        // FIXME(associated_const_equality): Also add associated consts to
-        // the requirements here.
-        if item.kind == ty::AssocKind::Type {
-            // associated types that require `Self: Sized` do not show up in the built-in
-            // implementation of `Trait for dyn Trait`, and can be dropped here.
-            if tcx.generics_require_sized_self(item.def_id) {
-                continue;
-            }
-
-            requirements
-                .extend(tcx.item_bounds(item.def_id).iter_instantiated(tcx, trait_ref.args));
+    requirements
+        .extend(tcx.super_predicates_of(trait_ref.def_id).iter_instantiated(tcx, &trait_ref.args));
+
+    // FIXME(associated_const_equality): Also add associated consts to
+    // the requirements here.
+    for associated_type_def_id in tcx.associated_type_def_ids(trait_ref.def_id) {
+        // associated types that require `Self: Sized` do not show up in the built-in
+        // implementation of `Trait for dyn Trait`, and can be dropped here.
+        if tcx.generics_require_sized_self(associated_type_def_id) {
+            continue;
         }
+
+        requirements.extend(
+            tcx.item_bounds(associated_type_def_id).iter_instantiated(tcx, &trait_ref.args),
+        );
     }
 
     let mut replace_projection_with = FxHashMap::default();
-    for bound in object_bound {
+    for bound in object_bounds {
         if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
             let proj = proj.with_self_ty(tcx, trait_ref.self_ty());
             let old_ty = replace_projection_with.insert(proj.def_id(), bound.rebind(proj));
             assert_eq!(
                 old_ty,
                 None,
-                "{} has two generic parameters: {} and {}",
+                "{:?} has two generic parameters: {:?} and {:?}",
                 proj.projection_term,
                 proj.term,
                 old_ty.unwrap()
@@ -696,20 +712,22 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
         .collect()
 }
 
-struct ReplaceProjectionWith<'a, 'tcx> {
-    ecx: &'a EvalCtxt<'a, InferCtxt<'tcx>>,
-    param_env: ty::ParamEnv<'tcx>,
-    mapping: FxHashMap<DefId, ty::PolyProjectionPredicate<'tcx>>,
-    nested: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
+struct ReplaceProjectionWith<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> {
+    ecx: &'a EvalCtxt<'a, Infcx>,
+    param_env: I::ParamEnv,
+    mapping: FxHashMap<I::DefId, ty::Binder<I, ty::ProjectionPredicate<I>>>,
+    nested: Vec<Goal<I, I::Predicate>>,
 }
 
-impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceProjectionWith<'_, 'tcx> {
-    fn interner(&self) -> TyCtxt<'tcx> {
+impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
+    for ReplaceProjectionWith<'_, Infcx, I>
+{
+    fn interner(&self) -> I {
         self.ecx.interner()
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
+    fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
+        if let ty::Alias(ty::Projection, alias_ty) = ty.kind()
             && let Some(replacement) = self.mapping.get(&alias_ty.def_id)
         {
             // We may have a case where our object type's projection bound is higher-ranked,
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
index 43013a01069..860c580374d 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
@@ -1,9 +1,6 @@
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::def_id::DefId;
-use rustc_infer::infer::at::ToTrace;
-use rustc_infer::infer::{
-    BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk, TyCtxtInferExt,
-};
+use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::solve::{MaybeCause, NestedNormalizationGoals};
 use rustc_infer::traits::ObligationCause;
@@ -15,11 +12,13 @@ use rustc_middle::traits::solve::{
 use rustc_middle::ty::AliasRelationDirection;
 use rustc_middle::ty::TypeFolder;
 use rustc_middle::ty::{
-    self, InferCtxtLike, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
-    TypeVisitable, TypeVisitableExt, TypeVisitor,
+    self, InferCtxtLike, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
 };
 use rustc_span::DUMMY_SP;
 use rustc_type_ir::fold::TypeSuperFoldable;
+use rustc_type_ir::inherent::*;
+use rustc_type_ir::relate::Relate;
+use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_type_ir::{self as ir, CanonicalVarValues, Interner};
 use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
 use std::ops::ControlFlow;
@@ -456,28 +455,6 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
         }
     }
 
-    #[instrument(level = "trace", skip(self))]
-    pub(super) fn add_normalizes_to_goal(&mut self, mut goal: Goal<'tcx, ty::NormalizesTo<'tcx>>) {
-        goal.predicate = goal
-            .predicate
-            .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env });
-        self.inspect.add_normalizes_to_goal(self.infcx, self.max_input_universe, goal);
-        self.nested_goals.normalizes_to_goals.push(goal);
-    }
-
-    #[instrument(level = "debug", skip(self))]
-    pub(super) fn add_goal(
-        &mut self,
-        source: GoalSource,
-        mut goal: Goal<'tcx, ty::Predicate<'tcx>>,
-    ) {
-        goal.predicate = goal
-            .predicate
-            .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env });
-        self.inspect.add_goal(self.infcx, self.max_input_universe, source, goal);
-        self.nested_goals.goals.push((source, goal));
-    }
-
     // Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning
     // the certainty of all the goals.
     #[instrument(level = "trace", skip(self))]
@@ -600,27 +577,61 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> EvalCtxt<'_, Infcx> {
     pub(super) fn interner(&self) -> I {
         self.infcx.interner()
     }
-}
 
-impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
-    pub(super) fn next_ty_infer(&mut self) -> Ty<'tcx> {
-        let ty = self.infcx.next_ty_var(DUMMY_SP);
+    #[instrument(level = "trace", skip(self))]
+    pub(super) fn add_normalizes_to_goal(
+        &mut self,
+        mut goal: ir::solve::Goal<I, ir::NormalizesTo<I>>,
+    ) {
+        goal.predicate = goal
+            .predicate
+            .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env });
+        self.inspect.add_normalizes_to_goal(self.infcx, self.max_input_universe, goal);
+        self.nested_goals.normalizes_to_goals.push(goal);
+    }
+
+    #[instrument(level = "debug", skip(self))]
+    pub(super) fn add_goal(
+        &mut self,
+        source: GoalSource,
+        mut goal: ir::solve::Goal<I, I::Predicate>,
+    ) {
+        goal.predicate = goal
+            .predicate
+            .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env });
+        self.inspect.add_goal(self.infcx, self.max_input_universe, source, goal);
+        self.nested_goals.goals.push((source, goal));
+    }
+
+    #[instrument(level = "trace", skip(self, goals))]
+    pub(super) fn add_goals(
+        &mut self,
+        source: GoalSource,
+        goals: impl IntoIterator<Item = ir::solve::Goal<I, I::Predicate>>,
+    ) {
+        for goal in goals {
+            self.add_goal(source, goal);
+        }
+    }
+
+    pub(super) fn next_ty_infer(&mut self) -> I::Ty {
+        let ty = self.infcx.next_ty_infer();
         self.inspect.add_var_value(ty);
         ty
     }
 
-    pub(super) fn next_const_infer(&mut self) -> ty::Const<'tcx> {
-        let ct = self.infcx.next_const_var(DUMMY_SP);
+    pub(super) fn next_const_infer(&mut self) -> I::Const {
+        let ct = self.infcx.next_const_infer();
         self.inspect.add_var_value(ct);
         ct
     }
 
     /// Returns a ty infer or a const infer depending on whether `kind` is a `Ty` or `Const`.
     /// If `kind` is an integer inference variable this will still return a ty infer var.
-    pub(super) fn next_term_infer_of_kind(&mut self, kind: ty::Term<'tcx>) -> ty::Term<'tcx> {
-        match kind.unpack() {
-            ty::TermKind::Ty(_) => self.next_ty_infer().into(),
-            ty::TermKind::Const(_) => self.next_const_infer().into(),
+    pub(super) fn next_term_infer_of_kind(&mut self, kind: I::Term) -> I::Term {
+        match kind.kind() {
+            ir::TermKind::Ty(_) => self.next_ty_infer().into(),
+            ir::TermKind::Const(_) => self.next_const_infer().into(),
         }
     }
 
@@ -631,18 +642,18 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     #[instrument(level = "trace", skip(self), ret)]
     pub(super) fn term_is_fully_unconstrained(
         &self,
-        goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
+        goal: ir::solve::Goal<I, ir::NormalizesTo<I>>,
     ) -> bool {
-        let universe_of_term = match goal.predicate.term.unpack() {
-            ty::TermKind::Ty(ty) => {
-                if let &ty::Infer(ty::TyVar(vid)) = ty.kind() {
+        let universe_of_term = match goal.predicate.term.kind() {
+            ir::TermKind::Ty(ty) => {
+                if let ir::Infer(ir::TyVar(vid)) = ty.kind() {
                     self.infcx.universe_of_ty(vid).unwrap()
                 } else {
                     return false;
                 }
             }
-            ty::TermKind::Const(ct) => {
-                if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
+            ir::TermKind::Const(ct) => {
+                if let ir::ConstKind::Infer(ir::InferConst::Var(vid)) = ct.kind() {
                     self.infcx.universe_of_ct(vid).unwrap()
                 } else {
                     return false;
@@ -650,14 +661,14 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
             }
         };
 
-        struct ContainsTermOrNotNameable<'a, 'tcx> {
-            term: ty::Term<'tcx>,
-            universe_of_term: ty::UniverseIndex,
-            infcx: &'a InferCtxt<'tcx>,
+        struct ContainsTermOrNotNameable<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> {
+            term: I::Term,
+            universe_of_term: ir::UniverseIndex,
+            infcx: &'a Infcx,
         }
 
-        impl<'a, 'tcx> ContainsTermOrNotNameable<'a, 'tcx> {
-            fn check_nameable(&self, universe: ty::UniverseIndex) -> ControlFlow<()> {
+        impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> ContainsTermOrNotNameable<'_, Infcx, I> {
+            fn check_nameable(&self, universe: ir::UniverseIndex) -> ControlFlow<()> {
                 if self.universe_of_term.can_name(universe) {
                     ControlFlow::Continue(())
                 } else {
@@ -666,21 +677,23 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
             }
         }
 
-        impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTermOrNotNameable<'_, 'tcx> {
+        impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeVisitor<I>
+            for ContainsTermOrNotNameable<'_, Infcx, I>
+        {
             type Result = ControlFlow<()>;
-            fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
-                match *t.kind() {
-                    ty::Infer(ty::TyVar(vid)) => {
-                        if let ty::TermKind::Ty(term) = self.term.unpack()
-                            && let Some(term_vid) = term.ty_vid()
-                            && self.infcx.root_var(vid) == self.infcx.root_var(term_vid)
+            fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
+                match t.kind() {
+                    ir::Infer(ir::TyVar(vid)) => {
+                        if let ir::TermKind::Ty(term) = self.term.kind()
+                            && let ir::Infer(ir::TyVar(term_vid)) = term.kind()
+                            && self.infcx.root_ty_var(vid) == self.infcx.root_ty_var(term_vid)
                         {
                             ControlFlow::Break(())
                         } else {
                             self.check_nameable(self.infcx.universe_of_ty(vid).unwrap())
                         }
                     }
-                    ty::Placeholder(p) => self.check_nameable(p.universe),
+                    ir::Placeholder(p) => self.check_nameable(p.universe()),
                     _ => {
                         if t.has_non_region_infer() || t.has_placeholders() {
                             t.super_visit_with(self)
@@ -691,11 +704,11 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
                 }
             }
 
-            fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
+            fn visit_const(&mut self, c: I::Const) -> Self::Result {
                 match c.kind() {
-                    ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
-                        if let ty::TermKind::Const(term) = self.term.unpack()
-                            && let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind()
+                    ir::ConstKind::Infer(ir::InferConst::Var(vid)) => {
+                        if let ir::TermKind::Const(term) = self.term.kind()
+                            && let ir::ConstKind::Infer(ir::InferConst::Var(term_vid)) = term.kind()
                             && self.infcx.root_const_var(vid) == self.infcx.root_const_var(term_vid)
                         {
                             ControlFlow::Break(())
@@ -703,7 +716,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
                             self.check_nameable(self.infcx.universe_of_ct(vid).unwrap())
                         }
                     }
-                    ty::ConstKind::Placeholder(p) => self.check_nameable(p.universe),
+                    ir::ConstKind::Placeholder(p) => self.check_nameable(p.universe()),
                     _ => {
                         if c.has_non_region_infer() || c.has_placeholders() {
                             c.super_visit_with(self)
@@ -725,23 +738,13 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     }
 
     #[instrument(level = "trace", skip(self, param_env), ret)]
-    pub(super) fn eq<T: ToTrace<'tcx>>(
+    pub(super) fn eq<T: Relate<I>>(
         &mut self,
-        param_env: ty::ParamEnv<'tcx>,
+        param_env: I::ParamEnv,
         lhs: T,
         rhs: T,
     ) -> Result<(), NoSolution> {
-        self.infcx
-            .at(&ObligationCause::dummy(), param_env)
-            // New solver ignores DefineOpaqueTypes, so choose Yes for consistency
-            .eq(DefineOpaqueTypes::Yes, lhs, rhs)
-            .map(|InferOk { value: (), obligations }| {
-                self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
-            })
-            .map_err(|e| {
-                trace!(?e, "failed to equate");
-                NoSolution
-            })
+        self.relate(param_env, lhs, ir::Variance::Invariant, rhs)
     }
 
     /// This should be used when relating a rigid alias with another type.
@@ -752,10 +755,10 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     #[instrument(level = "trace", skip(self, param_env), ret)]
     pub(super) fn relate_rigid_alias_non_alias(
         &mut self,
-        param_env: ty::ParamEnv<'tcx>,
-        alias: ty::AliasTerm<'tcx>,
-        variance: ty::Variance,
-        term: ty::Term<'tcx>,
+        param_env: I::ParamEnv,
+        alias: ir::AliasTerm<I>,
+        variance: ir::Variance,
+        term: I::Term,
     ) -> Result<(), NoSolution> {
         // NOTE: this check is purely an optimization, the structural eq would
         // always fail if the term is not an inference variable.
@@ -770,12 +773,10 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
             // Alternatively we could modify `Equate` for this case by adding another
             // variant to `StructurallyRelateAliases`.
             let identity_args = self.fresh_args_for_item(alias.def_id);
-            let rigid_ctor = ty::AliasTerm::new(tcx, alias.def_id, identity_args);
+            let rigid_ctor = ir::AliasTerm::new(tcx, alias.def_id, identity_args);
             let ctor_term = rigid_ctor.to_term(tcx);
-            let InferOk { value: (), obligations } = self
-                .infcx
-                .at(&ObligationCause::dummy(), param_env)
-                .eq_structurally_relating_aliases(term, ctor_term)?;
+            let obligations =
+                self.infcx.eq_structurally_relating_aliases(param_env, term, ctor_term)?;
             debug_assert!(obligations.is_empty());
             self.relate(param_env, alias, variance, rigid_ctor)
         } else {
@@ -787,58 +788,38 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     /// unconstrained "return value" or when we're sure that all aliases in
     /// the types are rigid.
     #[instrument(level = "trace", skip(self, param_env), ret)]
-    pub(super) fn eq_structurally_relating_aliases<T: ToTrace<'tcx>>(
+    pub(super) fn eq_structurally_relating_aliases<T: Relate<I>>(
         &mut self,
-        param_env: ty::ParamEnv<'tcx>,
+        param_env: I::ParamEnv,
         lhs: T,
         rhs: T,
     ) -> Result<(), NoSolution> {
-        let cause = ObligationCause::dummy();
-        let InferOk { value: (), obligations } =
-            self.infcx.at(&cause, param_env).eq_structurally_relating_aliases(lhs, rhs)?;
-        assert!(obligations.is_empty());
+        let result = self.infcx.eq_structurally_relating_aliases(param_env, lhs, rhs)?;
+        assert_eq!(result, vec![]);
         Ok(())
     }
 
     #[instrument(level = "trace", skip(self, param_env), ret)]
-    pub(super) fn sub<T: ToTrace<'tcx>>(
+    pub(super) fn sub<T: Relate<I>>(
         &mut self,
-        param_env: ty::ParamEnv<'tcx>,
+        param_env: I::ParamEnv,
         sub: T,
         sup: T,
     ) -> Result<(), NoSolution> {
-        self.infcx
-            .at(&ObligationCause::dummy(), param_env)
-            // New solver ignores DefineOpaqueTypes, so choose Yes for consistency
-            .sub(DefineOpaqueTypes::Yes, sub, sup)
-            .map(|InferOk { value: (), obligations }| {
-                self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
-            })
-            .map_err(|e| {
-                trace!(?e, "failed to subtype");
-                NoSolution
-            })
+        self.relate(param_env, sub, ir::Variance::Covariant, sup)
     }
 
     #[instrument(level = "trace", skip(self, param_env), ret)]
-    pub(super) fn relate<T: ToTrace<'tcx>>(
+    pub(super) fn relate<T: Relate<I>>(
         &mut self,
-        param_env: ty::ParamEnv<'tcx>,
+        param_env: I::ParamEnv,
         lhs: T,
-        variance: ty::Variance,
+        variance: ir::Variance,
         rhs: T,
     ) -> Result<(), NoSolution> {
-        self.infcx
-            .at(&ObligationCause::dummy(), param_env)
-            // New solver ignores DefineOpaqueTypes, so choose Yes for consistency
-            .relate(DefineOpaqueTypes::Yes, lhs, variance, rhs)
-            .map(|InferOk { value: (), obligations }| {
-                self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
-            })
-            .map_err(|e| {
-                trace!(?e, "failed to relate");
-                NoSolution
-            })
+        let goals = self.infcx.relate(param_env, lhs, variance, rhs)?;
+        self.add_goals(GoalSource::Misc, goals);
+        Ok(())
     }
 
     /// Equates two values returning the nested goals without adding them
@@ -847,58 +828,47 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     /// If possible, try using `eq` instead which automatically handles nested
     /// goals correctly.
     #[instrument(level = "trace", skip(self, param_env), ret)]
-    pub(super) fn eq_and_get_goals<T: ToTrace<'tcx>>(
+    pub(super) fn eq_and_get_goals<T: Relate<I>>(
         &self,
-        param_env: ty::ParamEnv<'tcx>,
+        param_env: I::ParamEnv,
         lhs: T,
         rhs: T,
-    ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
-        self.infcx
-            .at(&ObligationCause::dummy(), param_env)
-            // New solver ignores DefineOpaqueTypes, so choose Yes for consistency
-            .eq(DefineOpaqueTypes::Yes, lhs, rhs)
-            .map(|InferOk { value: (), obligations }| {
-                obligations.into_iter().map(|o| o.into()).collect()
-            })
-            .map_err(|e| {
-                trace!(?e, "failed to equate");
-                NoSolution
-            })
+    ) -> Result<Vec<ir::solve::Goal<I, I::Predicate>>, NoSolution> {
+        self.infcx.relate(param_env, lhs, ir::Variance::Invariant, rhs)
     }
 
-    pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<TyCtxt<'tcx>> + Copy>(
+    pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>(
         &self,
-        value: ty::Binder<'tcx, T>,
+        value: ir::Binder<I, T>,
     ) -> T {
-        self.infcx.instantiate_binder_with_fresh_vars(
-            DUMMY_SP,
-            BoundRegionConversionTime::HigherRankedType,
-            value,
-        )
+        self.infcx.instantiate_binder_with_infer(value)
     }
 
-    pub(super) fn enter_forall<T: TypeFoldable<TyCtxt<'tcx>> + Copy, U>(
+    pub(super) fn enter_forall<T: TypeFoldable<I> + Copy, U>(
         &self,
-        value: ty::Binder<'tcx, T>,
+        value: ir::Binder<I, T>,
         f: impl FnOnce(T) -> U,
     ) -> U {
         self.infcx.enter_forall(value, f)
     }
+
     pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T
     where
-        T: TypeFoldable<TyCtxt<'tcx>>,
+        T: TypeFoldable<I>,
     {
         self.infcx.resolve_vars_if_possible(value)
     }
 
-    pub(super) fn fresh_args_for_item(&mut self, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
-        let args = self.infcx.fresh_args_for_item(DUMMY_SP, def_id);
+    pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs {
+        let args = self.infcx.fresh_args_for_item(def_id);
         for arg in args {
             self.inspect.add_var_value(arg);
         }
         args
     }
+}
 
+impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     pub(super) fn register_ty_outlives(&self, ty: Ty<'tcx>, lt: ty::Region<'tcx>) {
         self.infcx.register_region_obligation_with_cause(ty, lt, &ObligationCause::dummy());
     }
@@ -1096,28 +1066,36 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
 ///
 /// This is a performance optimization to more eagerly detect cycles during trait
 /// solving. See tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs.
-struct ReplaceAliasWithInfer<'me, 'a, 'tcx> {
-    ecx: &'me mut EvalCtxt<'a, InferCtxt<'tcx>>,
-    param_env: ty::ParamEnv<'tcx>,
+struct ReplaceAliasWithInfer<'me, 'a, Infcx, I>
+where
+    Infcx: InferCtxtLike<Interner = I>,
+    I: Interner,
+{
+    ecx: &'me mut EvalCtxt<'a, Infcx>,
+    param_env: I::ParamEnv,
 }
 
-impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceAliasWithInfer<'_, '_, 'tcx> {
-    fn interner(&self) -> TyCtxt<'tcx> {
+impl<Infcx, I> TypeFolder<I> for ReplaceAliasWithInfer<'_, '_, Infcx, I>
+where
+    Infcx: InferCtxtLike<Interner = I>,
+    I: Interner,
+{
+    fn interner(&self) -> I {
         self.ecx.interner()
     }
 
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        match *ty.kind() {
-            ty::Alias(..) if !ty.has_escaping_bound_vars() => {
+    fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
+        match ty.kind() {
+            ir::Alias(..) if !ty.has_escaping_bound_vars() => {
                 let infer_ty = self.ecx.next_ty_infer();
-                let normalizes_to = ty::PredicateKind::AliasRelate(
+                let normalizes_to = ir::PredicateKind::AliasRelate(
                     ty.into(),
                     infer_ty.into(),
                     AliasRelationDirection::Equate,
                 );
                 self.ecx.add_goal(
                     GoalSource::Misc,
-                    Goal::new(self.interner(), self.param_env, normalizes_to),
+                    ir::solve::Goal::new(self.interner(), self.param_env, normalizes_to),
                 );
                 infer_ty
             }
@@ -1125,18 +1103,18 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceAliasWithInfer<'_, '_, 'tcx> {
         }
     }
 
-    fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
+    fn fold_const(&mut self, ct: I::Const) -> I::Const {
         match ct.kind() {
-            ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => {
+            ir::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => {
                 let infer_ct = self.ecx.next_const_infer();
-                let normalizes_to = ty::PredicateKind::AliasRelate(
+                let normalizes_to = ir::PredicateKind::AliasRelate(
                     ct.into(),
                     infer_ct.into(),
                     AliasRelationDirection::Equate,
                 );
                 self.ecx.add_goal(
                     GoalSource::Misc,
-                    Goal::new(self.interner(), self.param_env, normalizes_to),
+                    ir::solve::Goal::new(self.interner(), self.param_env, normalizes_to),
                 );
                 infer_ct
             }
@@ -1144,7 +1122,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceAliasWithInfer<'_, '_, 'tcx> {
         }
     }
 
-    fn fold_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+    fn fold_predicate(&mut self, predicate: I::Predicate) -> I::Predicate {
         if predicate.allow_normalization() { predicate.super_fold_with(self) } else { predicate }
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs
index 1748c9be927..ad6fdd2707d 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs
@@ -1,27 +1,29 @@
 use crate::solve::assembly::Candidate;
 
 use super::EvalCtxt;
-use rustc_infer::infer::InferCtxt;
-use rustc_infer::traits::BuiltinImplSource;
-use rustc_middle::traits::query::NoSolution;
-use rustc_middle::traits::solve::{inspect, CandidateSource, QueryResult};
-use rustc_middle::ty::TyCtxt;
+use rustc_next_trait_solver::solve::{
+    inspect, BuiltinImplSource, CandidateSource, NoSolution, QueryResult,
+};
+use rustc_type_ir::{InferCtxtLike, Interner};
 use std::marker::PhantomData;
 
-pub(in crate::solve) struct ProbeCtxt<'me, 'a, 'tcx, F, T> {
-    ecx: &'me mut EvalCtxt<'a, InferCtxt<'tcx>>,
+pub(in crate::solve) struct ProbeCtxt<'me, 'a, Infcx, I, F, T>
+where
+    Infcx: InferCtxtLike<Interner = I>,
+    I: Interner,
+{
+    ecx: &'me mut EvalCtxt<'a, Infcx, I>,
     probe_kind: F,
     _result: PhantomData<T>,
 }
 
-impl<'tcx, F, T> ProbeCtxt<'_, '_, 'tcx, F, T>
+impl<Infcx, I, F, T> ProbeCtxt<'_, '_, Infcx, I, F, T>
 where
-    F: FnOnce(&T) -> inspect::ProbeKind<TyCtxt<'tcx>>,
+    F: FnOnce(&T) -> inspect::ProbeKind<I>,
+    Infcx: InferCtxtLike<Interner = I>,
+    I: Interner,
 {
-    pub(in crate::solve) fn enter(
-        self,
-        f: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> T,
-    ) -> T {
+    pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> T) -> T {
         let ProbeCtxt { ecx: outer_ecx, probe_kind, _result } = self;
 
         let infcx = outer_ecx.infcx;
@@ -38,7 +40,7 @@ where
             tainted: outer_ecx.tainted,
             inspect: outer_ecx.inspect.take_and_enter_probe(),
         };
-        let r = nested_ecx.infcx.probe(|_| {
+        let r = nested_ecx.infcx.probe(|| {
             let r = f(&mut nested_ecx);
             nested_ecx.inspect.probe_final_state(infcx, max_input_universe);
             r
@@ -52,30 +54,43 @@ where
     }
 }
 
-pub(in crate::solve) struct TraitProbeCtxt<'me, 'a, 'tcx, F> {
-    cx: ProbeCtxt<'me, 'a, 'tcx, F, QueryResult<'tcx>>,
-    source: CandidateSource<'tcx>,
+pub(in crate::solve) struct TraitProbeCtxt<'me, 'a, Infcx, I, F>
+where
+    Infcx: InferCtxtLike<Interner = I>,
+    I: Interner,
+{
+    cx: ProbeCtxt<'me, 'a, Infcx, I, F, QueryResult<I>>,
+    source: CandidateSource<I>,
 }
 
-impl<'tcx, F> TraitProbeCtxt<'_, '_, 'tcx, F>
+impl<Infcx, I, F> TraitProbeCtxt<'_, '_, Infcx, I, F>
 where
-    F: FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<TyCtxt<'tcx>>,
+    Infcx: InferCtxtLike<Interner = I>,
+    I: Interner,
+    F: FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>,
 {
     #[instrument(level = "debug", skip_all, fields(source = ?self.source))]
     pub(in crate::solve) fn enter(
         self,
-        f: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> QueryResult<'tcx>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+        f: impl FnOnce(&mut EvalCtxt<'_, Infcx>) -> QueryResult<I>,
+    ) -> Result<Candidate<I>, NoSolution> {
         self.cx.enter(|ecx| f(ecx)).map(|result| Candidate { source: self.source, result })
     }
 }
 
-impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
+impl<'a, Infcx, I> EvalCtxt<'a, Infcx, I>
+where
+    Infcx: InferCtxtLike<Interner = I>,
+    I: Interner,
+{
     /// `probe_kind` is only called when proof tree building is enabled so it can be
     /// as expensive as necessary to output the desired information.
-    pub(in crate::solve) fn probe<F, T>(&mut self, probe_kind: F) -> ProbeCtxt<'_, 'a, 'tcx, F, T>
+    pub(in crate::solve) fn probe<F, T>(
+        &mut self,
+        probe_kind: F,
+    ) -> ProbeCtxt<'_, 'a, Infcx, I, F, T>
     where
-        F: FnOnce(&T) -> inspect::ProbeKind<TyCtxt<'tcx>>,
+        F: FnOnce(&T) -> inspect::ProbeKind<I>,
     {
         ProbeCtxt { ecx: self, probe_kind, _result: PhantomData }
     }
@@ -83,28 +98,20 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
     pub(in crate::solve) fn probe_builtin_trait_candidate(
         &mut self,
         source: BuiltinImplSource,
-    ) -> TraitProbeCtxt<
-        '_,
-        'a,
-        'tcx,
-        impl FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<TyCtxt<'tcx>>,
-    > {
+    ) -> TraitProbeCtxt<'_, 'a, Infcx, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>>
+    {
         self.probe_trait_candidate(CandidateSource::BuiltinImpl(source))
     }
 
     pub(in crate::solve) fn probe_trait_candidate(
         &mut self,
-        source: CandidateSource<'tcx>,
-    ) -> TraitProbeCtxt<
-        '_,
-        'a,
-        'tcx,
-        impl FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<TyCtxt<'tcx>>,
-    > {
+        source: CandidateSource<I>,
+    ) -> TraitProbeCtxt<'_, 'a, Infcx, I, impl FnOnce(&QueryResult<I>) -> inspect::ProbeKind<I>>
+    {
         TraitProbeCtxt {
             cx: ProbeCtxt {
                 ecx: self,
-                probe_kind: move |result: &QueryResult<'tcx>| inspect::ProbeKind::TraitCandidate {
+                probe_kind: move |result: &QueryResult<I>| inspect::ProbeKind::TraitCandidate {
                     source,
                     result: *result,
                 },
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index dc13941e5d7..3c01d1a65f5 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -460,9 +460,10 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
                     polarity: ty::PredicatePolarity::Positive,
                 }))
             }
-            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => {
-                ChildMode::WellFormedObligation
-            }
+            ty::PredicateKind::Clause(
+                ty::ClauseKind::WellFormed(_) | ty::ClauseKind::Projection(..),
+            )
+            | ty::PredicateKind::AliasRelate(..) => ChildMode::PassThrough,
             _ => {
                 return ControlFlow::Break(self.obligation.clone());
             }
@@ -496,7 +497,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
                 (_, GoalSource::InstantiateHigherRanked) => {
                     obligation = self.obligation.clone();
                 }
-                (ChildMode::WellFormedObligation, _) => {
+                (ChildMode::PassThrough, _) => {
                     obligation = make_obligation(self.obligation.cause.clone());
                 }
             }
@@ -514,6 +515,32 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
             self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
         }
 
+        // alias-relate may fail because the lhs or rhs can't be normalized,
+        // and therefore is treated as rigid.
+        if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred_kind.no_bound_vars() {
+            if let Some(obligation) = goal
+                .infcx()
+                .visit_proof_tree_at_depth(
+                    goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(lhs.into())),
+                    goal.depth() + 1,
+                    self,
+                )
+                .break_value()
+            {
+                return ControlFlow::Break(obligation);
+            } else if let Some(obligation) = goal
+                .infcx()
+                .visit_proof_tree_at_depth(
+                    goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(rhs.into())),
+                    goal.depth() + 1,
+                    self,
+                )
+                .break_value()
+            {
+                return ControlFlow::Break(obligation);
+            }
+        }
+
         ControlFlow::Break(self.obligation.clone())
     }
 }
@@ -527,7 +554,7 @@ enum ChildMode<'tcx> {
     // Skip trying to derive an `ObligationCause` from this obligation, and
     // report *all* sub-obligations as if they came directly from the parent
     // obligation.
-    WellFormedObligation,
+    PassThrough,
 }
 
 fn derive_cause<'tcx>(
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 19c95dad48c..464c188b6e3 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -15,7 +15,7 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
 use rustc_macros::extension;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{inspect, QueryResult};
-use rustc_middle::traits::solve::{Certainty, Goal};
+use rustc_middle::traits::solve::{Certainty, Goal, MaybeCause};
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{TyCtxt, TypeFoldable};
 use rustc_middle::{bug, ty};
@@ -278,6 +278,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
         self.source
     }
 
+    pub fn depth(&self) -> usize {
+        self.depth
+    }
+
     fn candidates_recur(
         &'a self,
         candidates: &mut Vec<InspectCandidate<'a, 'tcx>>,
@@ -291,7 +295,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
                     steps.push(step)
                 }
                 inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
-                    assert_eq!(shallow_certainty.replace(c), None);
+                    assert!(matches!(
+                        shallow_certainty.replace(c),
+                        None | Some(Certainty::Maybe(MaybeCause::Ambiguity))
+                    ));
                 }
                 inspect::ProbeStep::NestedProbe(ref probe) => {
                     match probe.kind {
@@ -433,8 +440,17 @@ impl<'tcx> InferCtxt<'tcx> {
         goal: Goal<'tcx, ty::Predicate<'tcx>>,
         visitor: &mut V,
     ) -> V::Result {
+        self.visit_proof_tree_at_depth(goal, 0, visitor)
+    }
+
+    fn visit_proof_tree_at_depth<V: ProofTreeVisitor<'tcx>>(
+        &self,
+        goal: Goal<'tcx, ty::Predicate<'tcx>>,
+        depth: usize,
+        visitor: &mut V,
+    ) -> V::Result {
         let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
         let proof_tree = proof_tree.unwrap();
-        visitor.visit_goal(&InspectGoal::new(self, 0, proof_tree, None, GoalSource::Misc))
+        visitor.visit_goal(&InspectGoal::new(self, depth, proof_tree, None, GoalSource::Misc))
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
index 84c04900ae4..35750598bc7 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
@@ -34,10 +34,11 @@ use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
 /// trees. At the end of trait solving `ProofTreeBuilder::finalize`
 /// is called to recursively convert the whole structure to a
 /// finished proof tree.
-pub(in crate::solve) struct ProofTreeBuilder<
+pub(in crate::solve) struct ProofTreeBuilder<Infcx, I = <Infcx as InferCtxtLike>::Interner>
+where
     Infcx: InferCtxtLike<Interner = I>,
-    I: Interner = <Infcx as InferCtxtLike>::Interner,
-> {
+    I: Interner,
+{
     _infcx: PhantomData<Infcx>,
     state: Option<Box<DebugSolver<I>>>,
 }
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index c47b0194964..fdcf4ff11e4 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -235,17 +235,6 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
 }
 
 impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
-    #[instrument(level = "trace", skip(self, goals))]
-    fn add_goals(
-        &mut self,
-        source: GoalSource,
-        goals: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
-    ) {
-        for goal in goals {
-            self.add_goal(source, goal);
-        }
-    }
-
     /// Try to merge multiple possible ways to prove a goal, if that is not possible returns `None`.
     ///
     /// In this case we tend to flounder and return ambiguity by calling `[EvalCtxt::flounder]`.
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index 787f08a084e..60a15392e0b 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -17,7 +17,7 @@ use rustc_middle::ty::NormalizesTo;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{TypeVisitableExt, Upcast};
 use rustc_middle::{bug, span_bug};
-use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP};
+use rustc_span::{ErrorGuaranteed, DUMMY_SP};
 
 mod anon_const;
 mod inherent;
@@ -40,7 +40,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
             Ok(res) => Ok(res),
             Err(NoSolution) => {
                 let Goal { param_env, predicate: NormalizesTo { alias, term } } = goal;
-                self.relate_rigid_alias_non_alias(param_env, alias, ty::Variance::Invariant, term)?;
+                self.relate_rigid_alias_non_alias(param_env, alias, ty::Invariant, term)?;
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             }
         }
@@ -103,7 +103,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
         goal: Goal<'tcx, Self>,
         assumption: ty::Clause<'tcx>,
         then: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> QueryResult<'tcx>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if let Some(projection_pred) = assumption.as_projection_clause() {
             if projection_pred.projection_def_id() == goal.predicate.def_id() {
                 let tcx = ecx.interner();
@@ -140,7 +140,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, NormalizesTo<'tcx>>,
         impl_def_id: DefId,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let tcx = ecx.interner();
 
         let goal_trait_ref = goal.predicate.alias.trait_ref(tcx);
@@ -267,14 +267,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     fn consider_error_guaranteed_candidate(
         _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         _guar: ErrorGuaranteed,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         Err(NoSolution)
     }
 
     fn consider_auto_trait_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         ecx.interner().dcx().span_delayed_bug(
             ecx.interner().def_span(goal.predicate.def_id()),
             "associated types not allowed on auto traits",
@@ -285,35 +285,35 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     fn consider_trait_alias_candidate(
         _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("trait aliases do not have associated types: {:?}", goal);
     }
 
     fn consider_builtin_sized_candidate(
         _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`Sized` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_copy_clone_candidate(
         _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`Copy`/`Clone` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_pointer_like_candidate(
         _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`PointerLike` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_fn_ptr_trait_candidate(
         _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`FnPtr` does not have an associated type: {:?}", goal);
     }
 
@@ -321,7 +321,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
         goal_kind: ty::ClosureKind,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let tcx = ecx.interner();
         let tupled_inputs_and_output =
             match structural_traits::extract_tupled_inputs_and_output_from_callable(
@@ -364,7 +364,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
         goal_kind: ty::ClosureKind,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let tcx = ecx.interner();
 
         let env_region = match goal_kind {
@@ -392,9 +392,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                      output_coroutine_ty,
                      coroutine_return_ty,
                  }| {
-                    let lang_items = tcx.lang_items();
-                    let (projection_term, term) = if Some(goal.predicate.def_id())
-                        == lang_items.call_once_future()
+                    let (projection_term, term) = if tcx
+                        .is_lang_item(goal.predicate.def_id(), LangItem::CallOnceFuture)
                     {
                         (
                             ty::AliasTerm::new(
@@ -404,7 +403,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                             ),
                             output_coroutine_ty.into(),
                         )
-                    } else if Some(goal.predicate.def_id()) == lang_items.call_ref_future() {
+                    } else if tcx.is_lang_item(goal.predicate.def_id(), LangItem::CallRefFuture) {
                         (
                             ty::AliasTerm::new(
                                 tcx,
@@ -417,7 +416,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                             ),
                             output_coroutine_ty.into(),
                         )
-                    } else if Some(goal.predicate.def_id()) == lang_items.async_fn_once_output() {
+                    } else if tcx.is_lang_item(goal.predicate.def_id(), LangItem::AsyncFnOnceOutput)
+                    {
                         (
                             ty::AliasTerm::new(
                                 tcx,
@@ -454,7 +454,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     fn consider_builtin_async_fn_kind_helper_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let [
             closure_fn_kind_ty,
             goal_kind_ty,
@@ -501,14 +501,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     fn consider_builtin_tuple_candidate(
         _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`Tuple` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_pointee_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let tcx = ecx.interner();
         let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None);
         assert_eq!(metadata_def_id, goal.predicate.def_id());
@@ -590,7 +590,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     fn consider_builtin_future_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
         let ty::Coroutine(def_id, args) = *self_ty.kind() else {
             return Err(NoSolution);
@@ -626,7 +626,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     fn consider_builtin_iterator_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
         let ty::Coroutine(def_id, args) = *self_ty.kind() else {
             return Err(NoSolution);
@@ -662,14 +662,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     fn consider_builtin_fused_iterator_candidate(
         _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`FusedIterator` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_async_iterator_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
         let ty::Coroutine(def_id, args) = *self_ty.kind() else {
             return Err(NoSolution);
@@ -705,7 +705,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     fn consider_builtin_coroutine_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
         let ty::Coroutine(def_id, args) = *self_ty.kind() else {
             return Err(NoSolution);
@@ -719,13 +719,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
 
         let coroutine = args.as_coroutine();
 
-        let name = tcx.associated_item(goal.predicate.def_id()).name;
-        let term = if name == sym::Return {
+        let term = if tcx.is_lang_item(goal.predicate.def_id(), LangItem::CoroutineReturn) {
             coroutine.return_ty().into()
-        } else if name == sym::Yield {
+        } else if tcx.is_lang_item(goal.predicate.def_id(), LangItem::CoroutineYield) {
             coroutine.yield_ty().into()
         } else {
-            bug!("unexpected associated item `<{self_ty} as Coroutine>::{name}`")
+            bug!(
+                "unexpected associated item `<{self_ty} as Coroutine>::{}`",
+                tcx.item_name(goal.predicate.def_id())
+            )
         };
 
         Self::probe_and_consider_implied_clause(
@@ -750,14 +752,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     fn consider_structural_builtin_unsize_candidates(
         _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Vec<Candidate<'tcx>> {
+    ) -> Vec<Candidate<TyCtxt<'tcx>>> {
         bug!("`Unsize` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_discriminant_kind_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
         let discriminant_ty = match *self_ty.kind() {
             ty::Bool
@@ -809,7 +811,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     fn consider_builtin_async_destruct_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
         let async_destructor_ty = match *self_ty.kind() {
             ty::Bool
@@ -862,14 +864,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
     fn consider_builtin_destruct_candidate(
         _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`Destruct` does not have an associated type: {:?}", goal);
     }
 
     fn consider_builtin_transmute_candidate(
         _ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         bug!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal)
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index a741f488901..3fdc11ade5f 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -39,7 +39,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, TraitPredicate<'tcx>>,
         impl_def_id: DefId,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let tcx = ecx.interner();
 
         let impl_trait_header = tcx.impl_trait_header(impl_def_id).unwrap();
@@ -94,7 +94,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_error_guaranteed_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         _guar: ErrorGuaranteed,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         // FIXME: don't need to enter a probe here.
         ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
             .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
@@ -106,7 +106,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         goal: Goal<'tcx, Self>,
         assumption: ty::Clause<'tcx>,
         then: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> QueryResult<'tcx>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if let Some(trait_clause) = assumption.as_trait_clause() {
             if trait_clause.def_id() == goal.predicate.def_id()
                 && trait_clause.polarity() == goal.predicate.polarity
@@ -131,7 +131,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_auto_trait_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -174,7 +174,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_trait_alias_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -197,7 +197,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_sized_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -212,7 +212,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_copy_clone_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -227,7 +227,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_pointer_like_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -257,7 +257,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_fn_ptr_trait_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let self_ty = goal.predicate.self_ty();
         match goal.predicate.polarity {
             // impl FnPtr for FnPtr {}
@@ -289,7 +289,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
         goal_kind: ty::ClosureKind,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -330,7 +330,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
         goal_kind: ty::ClosureKind,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -380,7 +380,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_async_fn_kind_helper_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let [closure_fn_kind_ty, goal_kind_ty] = **goal.predicate.trait_ref.args else {
             bug!();
         };
@@ -407,7 +407,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_tuple_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -423,7 +423,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_pointee_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -435,7 +435,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_future_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -461,7 +461,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_iterator_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -487,7 +487,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_fused_iterator_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -511,7 +511,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_async_iterator_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -537,7 +537,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_coroutine_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -569,7 +569,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_discriminant_kind_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -582,7 +582,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_async_destruct_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -595,7 +595,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_destruct_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -611,7 +611,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_builtin_transmute_candidate(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return Err(NoSolution);
         }
@@ -652,7 +652,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn consider_structural_builtin_unsize_candidates(
         ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
         goal: Goal<'tcx, Self>,
-    ) -> Vec<Candidate<'tcx>> {
+    ) -> Vec<Candidate<TyCtxt<'tcx>>> {
         if goal.predicate.polarity != ty::PredicatePolarity::Positive {
             return vec![];
         }
@@ -738,7 +738,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         a_region: ty::Region<'tcx>,
         b_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
         b_region: ty::Region<'tcx>,
-    ) -> Vec<Candidate<'tcx>> {
+    ) -> Vec<Candidate<TyCtxt<'tcx>>> {
         let tcx = self.interner();
         let Goal { predicate: (a_ty, _b_ty), .. } = goal;
 
@@ -784,7 +784,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>,
         b_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
         b_region: ty::Region<'tcx>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let tcx = self.interner();
         let Goal { predicate: (a_ty, _), .. } = goal;
 
@@ -802,14 +802,13 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
             );
 
             // The type must be `Sized` to be unsized.
-            if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
-                ecx.add_goal(
-                    GoalSource::ImplWhereBound,
-                    goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty])),
-                );
-            } else {
-                return Err(NoSolution);
-            }
+            ecx.add_goal(
+                GoalSource::ImplWhereBound,
+                goal.with(
+                    tcx,
+                    ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, None), [a_ty]),
+                ),
+            );
 
             // The type must outlive the lifetime of the `dyn` we're unsizing into.
             ecx.add_goal(GoalSource::Misc, goal.with(tcx, ty::OutlivesPredicate(a_ty, b_region)));
@@ -826,7 +825,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         b_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
         b_region: ty::Region<'tcx>,
         upcast_principal: Option<ty::PolyExistentialTraitRef<'tcx>>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let param_env = goal.param_env;
 
         // We may upcast to auto traits that are either explicitly listed in
@@ -929,7 +928,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>,
         a_elem_ty: Ty<'tcx>,
         b_elem_ty: Ty<'tcx>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         self.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
         self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
             .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
@@ -954,7 +953,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         def: ty::AdtDef<'tcx>,
         a_args: ty::GenericArgsRef<'tcx>,
         b_args: ty::GenericArgsRef<'tcx>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let tcx = self.interner();
         let Goal { predicate: (_a_ty, b_ty), .. } = goal;
 
@@ -991,7 +990,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
                 tcx,
                 ty::TraitRef::new(
                     tcx,
-                    tcx.lang_items().unsize_trait().unwrap(),
+                    tcx.require_lang_item(LangItem::Unsize, None),
                     [a_tail_ty, b_tail_ty],
                 ),
             ),
@@ -1015,7 +1014,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
         goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>,
         a_tys: &'tcx ty::List<Ty<'tcx>>,
         b_tys: &'tcx ty::List<Ty<'tcx>>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         let tcx = self.interner();
         let Goal { predicate: (_a_ty, b_ty), .. } = goal;
 
@@ -1034,7 +1033,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
                 tcx,
                 ty::TraitRef::new(
                     tcx,
-                    tcx.lang_items().unsize_trait().unwrap(),
+                    tcx.require_lang_item(LangItem::Unsize, None),
                     [a_last_ty, b_last_ty],
                 ),
             ),
@@ -1050,7 +1049,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
     fn disqualify_auto_trait_candidate_due_to_possible_impl(
         &mut self,
         goal: Goal<'tcx, TraitPredicate<'tcx>>,
-    ) -> Option<Result<Candidate<'tcx>, NoSolution>> {
+    ) -> Option<Result<Candidate<TyCtxt<'tcx>>, NoSolution>> {
         let self_ty = goal.predicate.self_ty();
         match *self_ty.kind() {
             // Stall int and float vars until they are resolved to a concrete
@@ -1076,7 +1075,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
             // takes precedence over the structural auto trait candidate being
             // assembled.
             ty::Coroutine(def_id, _)
-                if Some(goal.predicate.def_id()) == self.interner().lang_items().unpin_trait() =>
+                if self.interner().is_lang_item(goal.predicate.def_id(), LangItem::Unpin) =>
             {
                 match self.interner().coroutine_movability(def_id) {
                     Movability::Static => Some(Err(NoSolution)),
@@ -1155,7 +1154,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
             &EvalCtxt<'_, InferCtxt<'tcx>>,
             Ty<'tcx>,
         ) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution>,
-    ) -> Result<Candidate<'tcx>, NoSolution> {
+    ) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
         self.probe_trait_candidate(source).enter(|ecx| {
             ecx.add_goals(
                 GoalSource::ImplWhereBound,
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index fc5c71252e1..a4177d8a93f 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -769,8 +769,8 @@ pub struct UncoveredTyParams<'tcx, T> {
 ///    add "non-blanket" impls without breaking negative reasoning in dependent
 ///    crates. This is the "rebalancing coherence" (RFC 1023) restriction.
 ///
-///    For that, we only a allow crate to perform negative reasoning on
-///    non-local-non-`#[fundamental]` only if there's a local key parameter as per (2).
+///    For that, we only allow a crate to perform negative reasoning on
+///    non-local-non-`#[fundamental]` if there's a local key parameter as per (2).
 ///
 ///    Because we never perform negative reasoning generically (coherence does
 ///    not involve type parameters), this can be interpreted as doing the full
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 087f7fbea00..f632f1ad4f2 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -794,7 +794,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
         if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
             obligation.predicate.kind().skip_binder()
-            && Some(trait_pred.def_id()) == self.tcx.lang_items().sized_trait()
+            && self.tcx.is_lang_item(trait_pred.def_id(), LangItem::Sized)
         {
             // Don't suggest calling to turn an unsized type into a sized type
             return false;
@@ -1106,7 +1106,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             .iter()
                             .find_map(|pred| {
                                 if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
-                        && Some(proj.projection_term.def_id) == self.tcx.lang_items().fn_once_output()
+                        && self.tcx.is_lang_item(proj.projection_term.def_id,LangItem::FnOnceOutput)
                         // args tuple will always be args[1]
                         && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind()
                                 {
@@ -1123,7 +1123,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     ty::Dynamic(data, _, ty::Dyn) => {
                         data.iter().find_map(|pred| {
                             if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
-                        && Some(proj.def_id) == self.tcx.lang_items().fn_once_output()
+                        && self.tcx.is_lang_item(proj.def_id, LangItem::FnOnceOutput)
                         // for existential projection, args are shifted over by 1
                         && let ty::Tuple(args) = proj.args.type_at(0).kind()
                             {
@@ -1150,7 +1150,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         };
                         param_env.caller_bounds().iter().find_map(|pred| {
                             if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
-                        && Some(proj.projection_term.def_id) == self.tcx.lang_items().fn_once_output()
+                        && self.tcx.is_lang_item(proj.projection_term.def_id, LangItem::FnOnceOutput)
                         && proj.projection_term.self_ty() == found
                         // args tuple will always be args[1]
                         && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind()
@@ -1822,7 +1822,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 && box_path
                     .res
                     .opt_def_id()
-                    .is_some_and(|def_id| Some(def_id) == self.tcx.lang_items().owned_box())
+                    .is_some_and(|def_id| self.tcx.is_lang_item(def_id, LangItem::OwnedBox))
             {
                 // Don't box `Box::new`
                 vec![]
@@ -2737,7 +2737,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             | ObligationCauseCode::ObjectTypeBound(..) => {}
             ObligationCauseCode::RustCall => {
                 if let Some(pred) = predicate.as_trait_clause()
-                    && Some(pred.def_id()) == tcx.lang_items().sized_trait()
+                    && tcx.is_lang_item(pred.def_id(), LangItem::Sized)
                 {
                     err.note("argument required to be sized due to `extern \"rust-call\"` ABI");
                 }
@@ -2790,7 +2790,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         // Check for foreign traits being reachable.
                         tcx.visible_parent_map(()).get(&def_id).is_some()
                     };
-                    if Some(def_id) == tcx.lang_items().sized_trait() {
+                    if tcx.is_lang_item(def_id, LangItem::Sized) {
                         // Check if this is an implicit bound, even in foreign crates.
                         if tcx
                             .generics_of(item_def_id)
@@ -3597,7 +3597,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
+        trait_ref: ty::PolyTraitRef<'tcx>,
     ) {
         let rhs_span = match obligation.cause.code() {
             ObligationCauseCode::BinOp { rhs_span: Some(span), rhs_is_lit, .. } if *rhs_is_lit => {
@@ -4592,7 +4592,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         &self,
         obligation: &PredicateObligation<'tcx>,
         err: &mut Diag<'_>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
+        trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) {
         if ObligationCauseCode::QuestionMark != *obligation.cause.code().peel_derives() {
             return;
@@ -4602,10 +4602,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         if let hir::Node::Item(item) = node
             && let hir::ItemKind::Fn(sig, _, body_id) = item.kind
             && let hir::FnRetTy::DefaultReturn(ret_span) = sig.decl.output
-            && self.tcx.is_diagnostic_item(sym::FromResidual, trait_ref.def_id())
-            && let ty::Tuple(l) = trait_ref.skip_binder().args.type_at(0).kind()
-            && l.len() == 0
-            && let ty::Adt(def, _) = trait_ref.skip_binder().args.type_at(1).kind()
+            && self.tcx.is_diagnostic_item(sym::FromResidual, trait_pred.def_id())
+            && trait_pred.skip_binder().trait_ref.args.type_at(0).is_unit()
+            && let ty::Adt(def, _) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
             && self.tcx.is_diagnostic_item(sym::Result, def.did())
         {
             let body = self.tcx.hir().body(body_id);
@@ -4863,14 +4862,13 @@ impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> {
 pub(super) fn get_explanation_based_on_obligation<'tcx>(
     tcx: TyCtxt<'tcx>,
     obligation: &PredicateObligation<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-    trait_predicate: &ty::PolyTraitPredicate<'tcx>,
+    trait_predicate: ty::PolyTraitPredicate<'tcx>,
     pre_message: String,
 ) -> String {
     if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
         "consider using `()`, or a `Result`".to_owned()
     } else {
-        let ty_desc = match trait_ref.skip_binder().self_ty().kind() {
+        let ty_desc = match trait_predicate.self_ty().skip_binder().kind() {
             ty::FnDef(_, _) => Some("fn item"),
             ty::Closure(_, _) => Some("closure"),
             _ => None,
@@ -4895,7 +4893,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
             format!(
                 "{pre_message}the trait `{}` is not implemented for{desc} `{}`{post}",
                 trait_predicate.print_modifiers_and_trait_path(),
-                tcx.short_ty_string(trait_ref.skip_binder().self_ty(), &mut None),
+                tcx.short_ty_string(trait_predicate.self_ty().skip_binder(), &mut None),
             )
         } else {
             // "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 6b6438a7887..9cd69f54c12 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -24,10 +24,10 @@ use rustc_data_structures::unord::UnordSet;
 use rustc_errors::codes::*;
 use rustc_errors::{pluralize, struct_span_code_err, Applicability, MultiSpan, StringPart};
 use rustc_errors::{Diag, EmissionGuarantee, ErrorGuaranteed, FatalError, StashKey};
-use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
+use rustc_hir::{self as hir, LangItem};
 use rustc_hir::{GenericParam, Item, Node};
 use rustc_infer::infer::error_reporting::TypeErrCtxt;
 use rustc_infer::infer::{InferOk, TypeTrace};
@@ -118,7 +118,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         // with more relevant type information and hide redundant E0282 errors.
         errors.sort_by_key(|e| match e.obligation.predicate.kind().skip_binder() {
             ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
-                if Some(pred.def_id()) == self.tcx.lang_items().sized_trait() =>
+                if self.tcx.is_lang_item(pred.def_id(), LangItem::Sized) =>
             {
                 1
             }
@@ -412,8 +412,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 let bound_predicate = obligation.predicate.kind();
                 match bound_predicate.skip_binder() {
                     ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
-                        let trait_predicate = bound_predicate.rebind(trait_predicate);
-                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
+                        let leaf_trait_predicate =
+                            self.resolve_vars_if_possible(bound_predicate.rebind(trait_predicate));
 
                         // Let's use the root obligation as the main message, when we care about the
                         // most general case ("X doesn't implement Pattern<'_>") over the case that
@@ -424,7 +424,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         let (main_trait_predicate, o) = if let ty::PredicateKind::Clause(
                             ty::ClauseKind::Trait(root_pred)
                         ) = root_obligation.predicate.kind().skip_binder()
-                            && !trait_predicate.self_ty().skip_binder().has_escaping_bound_vars()
+                            && !leaf_trait_predicate.self_ty().skip_binder().has_escaping_bound_vars()
                             && !root_pred.self_ty().has_escaping_bound_vars()
                             // The type of the leaf predicate is (roughly) the same as the type
                             // from the root predicate, as a proxy for "we care about the root"
@@ -434,20 +434,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 // `T: Trait` && `&&T: OtherTrait`, we want `OtherTrait`
                                 self.can_eq(
                                     obligation.param_env,
-                                    trait_predicate.self_ty().skip_binder(),
+                                    leaf_trait_predicate.self_ty().skip_binder(),
                                     root_pred.self_ty().peel_refs(),
                                 )
                                 // `&str: Iterator` && `&str: IntoIterator`, we want `IntoIterator`
                                 || self.can_eq(
                                     obligation.param_env,
-                                    trait_predicate.self_ty().skip_binder(),
+                                    leaf_trait_predicate.self_ty().skip_binder(),
                                     root_pred.self_ty(),
                                 )
                             )
                             // The leaf trait and the root trait are different, so as to avoid
                             // talking about `&mut T: Trait` and instead remain talking about
                             // `T: Trait` instead
-                            && trait_predicate.def_id() != root_pred.def_id()
+                            && leaf_trait_predicate.def_id() != root_pred.def_id()
                             // The root trait is not `Unsize`, as to avoid talking about it in
                             // `tests/ui/coercion/coerce-issue-49593-box-never.rs`.
                             && Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait()
@@ -459,13 +459,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 root_obligation,
                             )
                         } else {
-                            (trait_predicate, &obligation)
+                            (leaf_trait_predicate, &obligation)
                         };
-                        let trait_ref = main_trait_predicate.to_poly_trait_ref();
+                        let main_trait_ref = main_trait_predicate.to_poly_trait_ref();
+                        let leaf_trait_ref = leaf_trait_predicate.to_poly_trait_ref();
 
                         if let Some(guar) = self.emit_specialized_closure_kind_error(
                             &obligation,
-                            trait_ref,
+                            leaf_trait_ref,
                         ) {
                             return guar;
                         }
@@ -473,7 +474,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         // FIXME(effects)
                         let predicate_is_const = false;
 
-                        if let Err(guar) = trait_predicate.error_reported()
+                        if let Err(guar) = leaf_trait_predicate.error_reported()
                         {
                             return guar;
                         }
@@ -507,16 +508,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             notes,
                             parent_label,
                             append_const_msg,
-                        } = self.on_unimplemented_note(trait_ref, o, &mut long_ty_file);
+                        } = self.on_unimplemented_note(main_trait_ref, o, &mut long_ty_file);
+
                         let have_alt_message = message.is_some() || label.is_some();
-                        let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id());
+                        let is_try_conversion = self.is_try_conversion(span, main_trait_ref.def_id());
                         let is_unsize =
-                            Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait();
+                            self.tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Unsize);
                         let (message, notes, append_const_msg) = if is_try_conversion {
                             (
                                 Some(format!(
                                     "`?` couldn't convert the error to `{}`",
-                                    trait_ref.skip_binder().self_ty(),
+                                    main_trait_ref.skip_binder().self_ty(),
                                 )),
                                 vec![
                                     "the question mark operation (`?`) implicitly performs a \
@@ -530,20 +532,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         };
 
                         let err_msg = self.get_standard_error_message(
-                            &main_trait_predicate,
+                            main_trait_predicate,
                             message,
                             predicate_is_const,
                             append_const_msg,
                             post_message,
                         );
 
-                        let (err_msg, safe_transmute_explanation) = if Some(trait_ref.def_id())
+                        let (err_msg, safe_transmute_explanation) = if Some(main_trait_ref.def_id())
                             == self.tcx.lang_items().transmute_trait()
                         {
                             // Recompute the safe transmute reason and use that for the error reporting
                             match self.get_safe_transmute_error_and_reason(
                                 obligation.clone(),
-                                trait_ref,
+                                main_trait_ref,
                                 span,
                             ) {
                                 GetSafeTransmuteErrorAndReason::Silent => {
@@ -571,7 +573,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         }
                         let mut suggested = false;
                         if is_try_conversion {
-                            suggested = self.try_conversion_context(&obligation, trait_ref.skip_binder(), &mut err);
+                            suggested = self.try_conversion_context(&obligation, main_trait_ref.skip_binder(), &mut err);
                         }
 
                         if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) {
@@ -579,19 +581,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 ret_span,
                                 format!(
                                     "expected `{}` because of this",
-                                    trait_ref.skip_binder().self_ty()
+                                    main_trait_ref.skip_binder().self_ty()
                                 ),
                             );
                         }
 
-                        if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() {
+                        if tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Tuple) {
                             self.add_tuple_trait_message(
                                 obligation.cause.code().peel_derives(),
                                 &mut err,
                             );
                         }
 
-                        if Some(trait_ref.def_id()) == tcx.lang_items().drop_trait()
+                        if tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Drop)
                             && predicate_is_const
                         {
                             err.note("`~const Drop` was renamed to `~const Destruct`");
@@ -601,24 +603,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         let explanation = get_explanation_based_on_obligation(
                             self.tcx,
                             &obligation,
-                            trait_ref,
-                            &trait_predicate,
+                            leaf_trait_predicate,
                             pre_message,
                         );
 
                         self.check_for_binding_assigned_block_without_tail_expression(
                             &obligation,
                             &mut err,
-                            trait_predicate,
+                            leaf_trait_predicate,
                         );
-                        self.suggest_add_result_as_return_type(&obligation,
+                        self.suggest_add_result_as_return_type(
+                            &obligation,
                             &mut err,
-                            trait_ref);
+                            leaf_trait_predicate,
+                        );
 
                         if self.suggest_add_reference_to_arg(
                             &obligation,
                             &mut err,
-                            trait_predicate,
+                            leaf_trait_predicate,
                             have_alt_message,
                         ) {
                             self.note_obligation_cause(&mut err, &obligation);
@@ -630,7 +633,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             // If it has a custom `#[rustc_on_unimplemented]`
                             // error message, let's display it as the label!
                             err.span_label(span, s);
-                            if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
+                            if !matches!(leaf_trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
                                 // When the self type is a type param We don't need to "the trait
                                 // `std::marker::Sized` is not implemented for `T`" as we will point
                                 // at the type param with a label to suggest constraining it.
@@ -645,7 +648,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         if let ObligationCauseCode::Coercion { source, target } =
                             *obligation.cause.code().peel_derives()
                         {
-                            if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
+                            if self.tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Sized) {
                                 self.suggest_borrowing_for_object_cast(
                                     &mut err,
                                     root_obligation,
@@ -657,7 +660,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
                         let UnsatisfiedConst(unsatisfied_const) = self
                             .maybe_add_note_for_unsatisfied_const(
-                                &trait_predicate,
+                                leaf_trait_predicate,
                                 &mut err,
                                 span,
                             );
@@ -674,15 +677,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             err.span_label(tcx.def_span(body), s);
                         }
 
-                        self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref);
-                        self.suggest_dereferencing_index(&obligation, &mut err, trait_predicate);
-                        suggested |= self.suggest_dereferences(&obligation, &mut err, trait_predicate);
-                        suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate);
-                        let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
+                        self.suggest_floating_point_literal(&obligation, &mut err, leaf_trait_ref);
+                        self.suggest_dereferencing_index(&obligation, &mut err, leaf_trait_predicate);
+                        suggested |= self.suggest_dereferences(&obligation, &mut err, leaf_trait_predicate);
+                        suggested |= self.suggest_fn_call(&obligation, &mut err, leaf_trait_predicate);
+                        let impl_candidates = self.find_similar_impl_candidates(leaf_trait_predicate);
                         suggested = if let &[cand] = &impl_candidates[..] {
                             let cand = cand.trait_ref;
                             if let (ty::FnPtr(_), ty::FnDef(..)) =
-                                (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind())
+                                (cand.self_ty().kind(), main_trait_ref.self_ty().skip_binder().kind())
                             {
                                 err.span_suggestion(
                                     span.shrink_to_hi(),
@@ -702,31 +705,31 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             false
                         } || suggested;
                         suggested |=
-                            self.suggest_remove_reference(&obligation, &mut err, trait_predicate);
+                            self.suggest_remove_reference(&obligation, &mut err, leaf_trait_predicate);
                         suggested |= self.suggest_semicolon_removal(
                             &obligation,
                             &mut err,
                             span,
-                            trait_predicate,
+                            leaf_trait_predicate,
                         );
-                        self.note_version_mismatch(&mut err, &trait_ref);
+                        self.note_version_mismatch(&mut err, leaf_trait_ref);
                         self.suggest_remove_await(&obligation, &mut err);
-                        self.suggest_derive(&obligation, &mut err, trait_predicate);
+                        self.suggest_derive(&obligation, &mut err, leaf_trait_predicate);
 
-                        if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() {
+                        if tcx.is_lang_item(leaf_trait_ref.def_id(), LangItem::Try) {
                             self.suggest_await_before_try(
                                 &mut err,
                                 &obligation,
-                                trait_predicate,
+                                leaf_trait_predicate,
                                 span,
                             );
                         }
 
-                        if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) {
+                        if self.suggest_add_clone_to_arg(&obligation, &mut err, leaf_trait_predicate) {
                             return err.emit();
                         }
 
-                        if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) {
+                        if self.suggest_impl_trait(&mut err, &obligation, leaf_trait_predicate) {
                             return err.emit();
                         }
 
@@ -741,9 +744,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             );
                         }
 
-                        let is_fn_trait = tcx.is_fn_trait(trait_ref.def_id());
+                        let is_fn_trait = tcx.is_fn_trait(leaf_trait_ref.def_id());
                         let is_target_feature_fn = if let ty::FnDef(def_id, _) =
-                            *trait_ref.skip_binder().self_ty().kind()
+                            *leaf_trait_ref.skip_binder().self_ty().kind()
                         {
                             !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
                         } else {
@@ -757,8 +760,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
                         self.try_to_add_help_message(
                             &obligation,
-                            trait_ref,
-                            &trait_predicate,
+                            leaf_trait_predicate,
                             &mut err,
                             span,
                             is_fn_trait,
@@ -769,17 +771,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         // Changing mutability doesn't make a difference to whether we have
                         // an `Unsize` impl (Fixes ICE in #71036)
                         if !is_unsize {
-                            self.suggest_change_mut(&obligation, &mut err, trait_predicate);
+                            self.suggest_change_mut(&obligation, &mut err, leaf_trait_predicate);
                         }
 
                         // If this error is due to `!: Trait` not implemented but `(): Trait` is
                         // implemented, and fallback has occurred, then it could be due to a
                         // variable that used to fallback to `()` now falling back to `!`. Issue a
                         // note informing about the change in behaviour.
-                        if trait_predicate.skip_binder().self_ty().is_never()
+                        if leaf_trait_predicate.skip_binder().self_ty().is_never()
                             && self.fallback_has_occurred
                         {
-                            let predicate = trait_predicate.map_bound(|trait_pred| {
+                            let predicate = leaf_trait_predicate.map_bound(|trait_pred| {
                                 trait_pred.with_self_ty(self.tcx, tcx.types.unit)
                             });
                             let unit_obligation = obligation.with(tcx, predicate);
@@ -794,8 +796,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             }
                         }
 
-                        self.explain_hrtb_projection(&mut err, trait_predicate, obligation.param_env, &obligation.cause);
-                        self.suggest_desugaring_async_fn_in_trait(&mut err, trait_ref);
+                        self.explain_hrtb_projection(&mut err, leaf_trait_predicate, obligation.param_env, &obligation.cause);
+                        self.suggest_desugaring_async_fn_in_trait(&mut err, main_trait_ref);
 
                         // Return early if the trait is Debug or Display and the invocation
                         // originates within a standard library macro, because the output
@@ -813,15 +815,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
                         if in_std_macro
                             && matches!(
-                                self.tcx.get_diagnostic_name(trait_ref.def_id()),
+                                self.tcx.get_diagnostic_name(leaf_trait_ref.def_id()),
                                 Some(sym::Debug | sym::Display)
                             )
                         {
                             return err.emit();
                         }
 
-
-
                         err
                     }
 
@@ -1020,7 +1020,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         // doesn't extend the goal kind. This is worth reporting, but we can only do so
         // if we actually know which closure this goal comes from, so look at the cause
         // to see if we can extract that information.
-        if Some(trait_ref.def_id()) == self.tcx.lang_items().async_fn_kind_helper()
+        if self.tcx.is_lang_item(trait_ref.def_id(), LangItem::AsyncFnKindHelper)
             && let Some(found_kind) = trait_ref.skip_binder().args.type_at(0).to_opt_closure_kind()
             && let Some(expected_kind) =
                 trait_ref.skip_binder().args.type_at(1).to_opt_closure_kind()
@@ -1744,7 +1744,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         let self_ty = pred.projection_term.self_ty();
 
         with_forced_trimmed_paths! {
-            if Some(pred.projection_term.def_id) == self.tcx.lang_items().fn_once_output() {
+            if self.tcx.is_lang_item(pred.projection_term.def_id,LangItem::FnOnceOutput) {
                 let fn_kind = self_ty.prefix_string(self.tcx);
                 let item = match self_ty.kind() {
                     ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
@@ -1754,7 +1754,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     "expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \
                      returns `{normalized_ty}`",
                 ))
-            } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
+            } else if self.tcx.is_lang_item(trait_def_id, LangItem::Future) {
                 Some(format!(
                     "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \
                      resolves to `{normalized_ty}`"
@@ -1783,7 +1783,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 ty::Bool => Some(0),
                 ty::Char => Some(1),
                 ty::Str => Some(2),
-                ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().string() => Some(2),
+                ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => Some(2),
                 ty::Int(..)
                 | ty::Uint(..)
                 | ty::Float(..)
@@ -2236,11 +2236,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
     /// with the same path as `trait_ref`, a help message about
     /// a probable version mismatch is added to `err`
-    fn note_version_mismatch(
-        &self,
-        err: &mut Diag<'_>,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
-    ) -> bool {
+    fn note_version_mismatch(&self, err: &mut Diag<'_>, trait_ref: ty::PolyTraitRef<'tcx>) -> bool {
         let get_trait_impls = |trait_def_id| {
             let mut trait_impls = vec![];
             self.tcx.for_each_relevant_impl(
@@ -2346,7 +2342,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 // avoid inundating the user with unnecessary errors, but we now
                 // check upstream for type errors and don't add the obligations to
                 // begin with in those cases.
-                if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
+                if self.tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) {
                     match self.tainted_by_errors() {
                         None => {
                             let err = self.emit_inference_failure_err(
@@ -2705,6 +2701,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     ),
                 );
             }
+
+            ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })
+                if term.is_infer() =>
+            {
+                if let Some(e) = self.tainted_by_errors() {
+                    return e;
+                }
+                struct_span_code_err!(
+                    self.dcx(),
+                    span,
+                    E0284,
+                    "type annotations needed: cannot normalize `{alias}`",
+                )
+                .with_span_label(span, format!("cannot normalize `{alias}`"))
+            }
+
             _ => {
                 if let Some(e) = self.tainted_by_errors() {
                     return e;
@@ -2913,7 +2925,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
         let (Some(node), true) = (
             self.tcx.hir().get_if_local(item_def_id),
-            Some(pred.def_id()) == self.tcx.lang_items().sized_trait(),
+            self.tcx.is_lang_item(pred.def_id(), LangItem::Sized),
         ) else {
             return;
         };
@@ -3044,7 +3056,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
     fn get_standard_error_message(
         &self,
-        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
+        trait_predicate: ty::PolyTraitPredicate<'tcx>,
         message: Option<String>,
         predicate_is_const: bool,
         append_const_msg: Option<AppendConstMessage>,
@@ -3215,8 +3227,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     fn try_to_add_help_message(
         &self,
         obligation: &PredicateObligation<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
+        trait_predicate: ty::PolyTraitPredicate<'tcx>,
         err: &mut Diag<'_>,
         span: Span,
         is_fn_trait: bool,
@@ -3233,16 +3244,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         };
 
         // Try to report a help message
+        let trait_def_id = trait_predicate.def_id();
         if is_fn_trait
             && let Ok((implemented_kind, params)) = self.type_implements_fn_trait(
                 obligation.param_env,
-                trait_ref.self_ty(),
+                trait_predicate.self_ty(),
                 trait_predicate.skip_binder().polarity,
             )
         {
-            self.add_help_message_for_fn_trait(trait_ref, err, implemented_kind, params);
-        } else if !trait_ref.has_non_region_infer()
-            && self.predicate_can_apply(obligation.param_env, *trait_predicate)
+            self.add_help_message_for_fn_trait(
+                trait_predicate.to_poly_trait_ref(),
+                err,
+                implemented_kind,
+                params,
+            );
+        } else if !trait_predicate.has_non_region_infer()
+            && self.predicate_can_apply(obligation.param_env, trait_predicate)
         {
             // If a where-clause may be useful, remind the
             // user that they can add it.
@@ -3253,25 +3270,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             // which is somewhat confusing.
             self.suggest_restricting_param_bound(
                 err,
-                *trait_predicate,
+                trait_predicate,
                 None,
                 obligation.cause.body_id,
             );
-        } else if trait_ref.def_id().is_local()
-            && self.tcx.trait_impls_of(trait_ref.def_id()).is_empty()
-            && !self.tcx.trait_is_auto(trait_ref.def_id())
-            && !self.tcx.trait_is_alias(trait_ref.def_id())
+        } else if trait_def_id.is_local()
+            && self.tcx.trait_impls_of(trait_def_id).is_empty()
+            && !self.tcx.trait_is_auto(trait_def_id)
+            && !self.tcx.trait_is_alias(trait_def_id)
         {
             err.span_help(
-                self.tcx.def_span(trait_ref.def_id()),
+                self.tcx.def_span(trait_def_id),
                 crate::fluent_generated::trait_selection_trait_has_no_impls,
             );
         } else if !suggested && !unsatisfied_const {
             // Can't show anything else useful, try to find similar impls.
-            let impl_candidates = self.find_similar_impl_candidates(*trait_predicate);
+            let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
             if !self.report_similar_impl_candidates(
                 &impl_candidates,
-                trait_ref,
+                trait_predicate.to_poly_trait_ref(),
                 body_def_id,
                 err,
                 true,
@@ -3279,7 +3296,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             ) {
                 self.report_similar_impl_candidates_for_root_obligation(
                     obligation,
-                    *trait_predicate,
+                    trait_predicate,
                     body_def_id,
                     err,
                 );
@@ -3288,7 +3305,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             self.suggest_convert_to_slice(
                 err,
                 obligation,
-                trait_ref,
+                trait_predicate.to_poly_trait_ref(),
                 impl_candidates.as_slice(),
                 span,
             );
@@ -3353,7 +3370,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
     fn maybe_add_note_for_unsatisfied_const(
         &self,
-        _trait_predicate: &ty::PolyTraitPredicate<'tcx>,
+        _trait_predicate: ty::PolyTraitPredicate<'tcx>,
         _err: &mut Diag<'_>,
         _span: Span,
     ) -> UnsatisfiedConst {
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 08355ef55c4..fc5a2875b67 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -194,7 +194,7 @@ fn predicates_reference_self(
     predicates
         .predicates
         .iter()
-        .map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, &trait_ref), sp))
+        .map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, trait_ref), sp))
         .filter_map(|predicate| predicate_references_self(tcx, predicate))
         .collect()
 }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 2c9cb79664b..8ab324e6601 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1015,6 +1015,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // not eligible.
                 let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
 
+                let tcx = selcx.tcx();
                 let lang_items = selcx.tcx().lang_items();
                 if [
                     lang_items.coroutine_trait(),
@@ -1031,7 +1032,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 .contains(&Some(trait_ref.def_id))
                 {
                     true
-                } else if lang_items.async_fn_kind_helper() == Some(trait_ref.def_id) {
+                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::AsyncFnKindHelper) {
                     // FIXME(async_closures): Validity constraints here could be cleaned up.
                     if obligation.predicate.args.type_at(0).is_ty_var()
                         || obligation.predicate.args.type_at(4).is_ty_var()
@@ -1043,7 +1044,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         obligation.predicate.args.type_at(0).to_opt_closure_kind().is_some()
                             && obligation.predicate.args.type_at(1).to_opt_closure_kind().is_some()
                     }
-                } else if lang_items.discriminant_kind_trait() == Some(trait_ref.def_id) {
+                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::DiscriminantKind) {
                     match self_ty.kind() {
                         ty::Bool
                         | ty::Char
@@ -1080,7 +1081,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         | ty::Infer(..)
                         | ty::Error(_) => false,
                     }
-                } else if lang_items.async_destruct_trait() == Some(trait_ref.def_id) {
+                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::AsyncDestruct) {
                     match self_ty.kind() {
                         ty::Bool
                         | ty::Char
@@ -1116,7 +1117,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         | ty::Infer(_)
                         | ty::Error(_) => false,
                     }
-                } else if lang_items.pointee_trait() == Some(trait_ref.def_id) {
+                } else if tcx.is_lang_item(trait_ref.def_id, LangItem::PointeeTrait) {
                     let tail = selcx.tcx().struct_tail_with_normalize(
                         self_ty,
                         |ty| {
@@ -1300,15 +1301,15 @@ fn confirm_select_candidate<'cx, 'tcx>(
     match impl_source {
         ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
         ImplSource::Builtin(BuiltinImplSource::Misc, data) => {
-            let trait_def_id = obligation.predicate.trait_def_id(selcx.tcx());
-            let lang_items = selcx.tcx().lang_items();
-            if lang_items.coroutine_trait() == Some(trait_def_id) {
+            let tcx = selcx.tcx();
+            let trait_def_id = obligation.predicate.trait_def_id(tcx);
+            if tcx.is_lang_item(trait_def_id, LangItem::Coroutine) {
                 confirm_coroutine_candidate(selcx, obligation, data)
-            } else if lang_items.future_trait() == Some(trait_def_id) {
+            } else if tcx.is_lang_item(trait_def_id, LangItem::Future) {
                 confirm_future_candidate(selcx, obligation, data)
-            } else if lang_items.iterator_trait() == Some(trait_def_id) {
+            } else if tcx.is_lang_item(trait_def_id, LangItem::Iterator) {
                 confirm_iterator_candidate(selcx, obligation, data)
-            } else if lang_items.async_iterator_trait() == Some(trait_def_id) {
+            } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncIterator) {
                 confirm_async_iterator_candidate(selcx, obligation, data)
             } else if selcx.tcx().fn_trait_kind_from_def_id(trait_def_id).is_some() {
                 if obligation.predicate.self_ty().is_closure()
@@ -1320,7 +1321,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
                 }
             } else if selcx.tcx().async_fn_trait_kind_from_def_id(trait_def_id).is_some() {
                 confirm_async_closure_candidate(selcx, obligation, data)
-            } else if lang_items.async_fn_kind_helper() == Some(trait_def_id) {
+            } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncFnKindHelper) {
                 confirm_async_fn_kind_helper_candidate(selcx, obligation, data)
             } else {
                 confirm_builtin_candidate(selcx, obligation, data)
@@ -1373,15 +1374,15 @@ fn confirm_coroutine_candidate<'cx, 'tcx>(
         coroutine_sig,
     );
 
-    let name = tcx.associated_item(obligation.predicate.def_id).name;
-    let ty = if name == sym::Return {
+    let ty = if tcx.is_lang_item(obligation.predicate.def_id, LangItem::CoroutineReturn) {
         return_ty
-    } else if name == sym::Yield {
+    } else if tcx.is_lang_item(obligation.predicate.def_id, LangItem::CoroutineYield) {
         yield_ty
     } else {
         span_bug!(
             tcx.def_span(obligation.predicate.def_id),
-            "unexpected associated type: `Coroutine::{name}`"
+            "unexpected associated type: `Coroutine::{}`",
+            tcx.item_name(obligation.predicate.def_id),
         );
     };
 
@@ -1538,21 +1539,20 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
 ) -> Progress<'tcx> {
     let tcx = selcx.tcx();
     let self_ty = obligation.predicate.self_ty();
-    let lang_items = tcx.lang_items();
     let item_def_id = obligation.predicate.def_id;
     let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
     let args = tcx.mk_args(&[self_ty.into()]);
-    let (term, obligations) = if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
+    let (term, obligations) = if tcx.is_lang_item(trait_def_id, LangItem::DiscriminantKind) {
         let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
         assert_eq!(discriminant_def_id, item_def_id);
 
         (self_ty.discriminant_ty(tcx).into(), Vec::new())
-    } else if lang_items.async_destruct_trait() == Some(trait_def_id) {
+    } else if tcx.is_lang_item(trait_def_id, LangItem::AsyncDestruct) {
         let destructor_def_id = tcx.associated_item_def_ids(trait_def_id)[0];
         assert_eq!(destructor_def_id, item_def_id);
 
         (self_ty.async_destructor_ty(tcx).into(), Vec::new())
-    } else if lang_items.pointee_trait() == Some(trait_def_id) {
+    } else if tcx.is_lang_item(trait_def_id, LangItem::PointeeTrait) {
         let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None);
         assert_eq!(metadata_def_id, item_def_id);
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 326c68e01db..7dc051e6fe9 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -55,7 +55,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
         }
 
         ty::Adt(def, _) => {
-            if Some(def.did()) == tcx.lang_items().manually_drop() {
+            if def.is_manually_drop() {
                 // `ManuallyDrop` never has a dtor.
                 true
             } else {
diff --git a/compiler/rustc_infer/src/infer/relate/_match.rs b/compiler/rustc_trait_selection/src/traits/select/_match.rs
index 30a066a265a..50d8e96aaf9 100644
--- a/compiler/rustc_infer/src/infer/relate/_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/_match.rs
@@ -1,10 +1,10 @@
+use rustc_infer::infer::relate::{
+    self, structurally_relate_tys, Relate, RelateResult, TypeRelation,
+};
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
 use tracing::{debug, instrument};
 
-use super::{structurally_relate_tys, Relate, RelateResult, TypeRelation};
-use crate::infer::relate;
-
 /// A type "A" *matches* "B" if the fresh types in B could be
 /// instantiated with values so as to make it equal to A. Matching is
 /// intended to be used only on freshened types, and it basically
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 6db5fa0e4e5..c53939bfe60 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -67,9 +67,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             // Other bounds. Consider both in-scope bounds from fn decl
             // and applicable impls. There is a certain set of precedence rules here.
             let def_id = obligation.predicate.def_id();
-            let lang_items = self.tcx().lang_items();
+            let tcx = self.tcx();
 
-            if lang_items.copy_trait() == Some(def_id) {
+            if tcx.is_lang_item(def_id, LangItem::Copy) {
                 debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty());
 
                 // User-defined copy impls are permitted, but only for
@@ -79,16 +79,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // For other types, we'll use the builtin rules.
                 let copy_conditions = self.copy_clone_conditions(obligation);
                 self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates);
-            } else if lang_items.discriminant_kind_trait() == Some(def_id) {
+            } else if tcx.is_lang_item(def_id, LangItem::DiscriminantKind) {
                 // `DiscriminantKind` is automatically implemented for every type.
                 candidates.vec.push(BuiltinCandidate { has_nested: false });
-            } else if lang_items.async_destruct_trait() == Some(def_id) {
+            } else if tcx.is_lang_item(def_id, LangItem::AsyncDestruct) {
                 // `AsyncDestruct` is automatically implemented for every type.
                 candidates.vec.push(BuiltinCandidate { has_nested: false });
-            } else if lang_items.pointee_trait() == Some(def_id) {
+            } else if tcx.is_lang_item(def_id, LangItem::PointeeTrait) {
                 // `Pointee` is automatically implemented for every type.
                 candidates.vec.push(BuiltinCandidate { has_nested: false });
-            } else if lang_items.sized_trait() == Some(def_id) {
+            } else if tcx.is_lang_item(def_id, LangItem::Sized) {
                 // Sized is never implementable by end-users, it is
                 // always automatically computed.
 
@@ -101,22 +101,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
                 let sized_conditions = self.sized_conditions(obligation);
                 self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
-            } else if lang_items.unsize_trait() == Some(def_id) {
+            } else if tcx.is_lang_item(def_id, LangItem::Unsize) {
                 self.assemble_candidates_for_unsizing(obligation, &mut candidates);
-            } else if lang_items.destruct_trait() == Some(def_id) {
+            } else if tcx.is_lang_item(def_id, LangItem::Destruct) {
                 self.assemble_const_destruct_candidates(obligation, &mut candidates);
-            } else if lang_items.transmute_trait() == Some(def_id) {
+            } else if tcx.is_lang_item(def_id, LangItem::TransmuteTrait) {
                 // User-defined transmutability impls are permitted.
                 self.assemble_candidates_from_impls(obligation, &mut candidates);
                 self.assemble_candidates_for_transmutability(obligation, &mut candidates);
-            } else if lang_items.tuple_trait() == Some(def_id) {
+            } else if tcx.is_lang_item(def_id, LangItem::Tuple) {
                 self.assemble_candidate_for_tuple(obligation, &mut candidates);
-            } else if lang_items.pointer_like() == Some(def_id) {
+            } else if tcx.is_lang_item(def_id, LangItem::PointerLike) {
                 self.assemble_candidate_for_pointer_like(obligation, &mut candidates);
-            } else if lang_items.fn_ptr_trait() == Some(def_id) {
+            } else if tcx.is_lang_item(def_id, LangItem::FnPtrTrait) {
                 self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates);
             } else {
-                if lang_items.clone_trait() == Some(def_id) {
+                if tcx.is_lang_item(def_id, LangItem::Clone) {
                     // Same builtin conditions as `Copy`, i.e., every type which has builtin support
                     // for `Copy` also has builtin support for `Clone`, and tuples/arrays of `Clone`
                     // types have builtin support for `Clone`.
@@ -124,17 +124,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates);
                 }
 
-                if lang_items.coroutine_trait() == Some(def_id) {
+                if tcx.is_lang_item(def_id, LangItem::Coroutine) {
                     self.assemble_coroutine_candidates(obligation, &mut candidates);
-                } else if lang_items.future_trait() == Some(def_id) {
+                } else if tcx.is_lang_item(def_id, LangItem::Future) {
                     self.assemble_future_candidates(obligation, &mut candidates);
-                } else if lang_items.iterator_trait() == Some(def_id) {
+                } else if tcx.is_lang_item(def_id, LangItem::Iterator) {
                     self.assemble_iterator_candidates(obligation, &mut candidates);
-                } else if lang_items.fused_iterator_trait() == Some(def_id) {
+                } else if tcx.is_lang_item(def_id, LangItem::FusedIterator) {
                     self.assemble_fused_iterator_candidates(obligation, &mut candidates);
-                } else if lang_items.async_iterator_trait() == Some(def_id) {
+                } else if tcx.is_lang_item(def_id, LangItem::AsyncIterator) {
                     self.assemble_async_iterator_candidates(obligation, &mut candidates);
-                } else if lang_items.async_fn_kind_helper() == Some(def_id) {
+                } else if tcx.is_lang_item(def_id, LangItem::AsyncFnKindHelper) {
                     self.assemble_async_fn_kind_helper_candidates(obligation, &mut candidates);
                 }
 
@@ -239,24 +239,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return Ok(());
         }
 
-        let all_bounds = stack
+        let bounds = stack
             .obligation
             .param_env
             .caller_bounds()
             .iter()
             .filter(|p| !p.references_error())
-            .filter_map(|p| p.as_trait_clause());
-
-        // Micro-optimization: filter out predicates relating to different traits.
-        let matching_bounds =
-            all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id());
+            .filter_map(|p| p.as_trait_clause())
+            // Micro-optimization: filter out predicates relating to different traits.
+            .filter(|p| p.def_id() == stack.obligation.predicate.def_id())
+            .filter(|p| p.polarity() == stack.obligation.predicate.polarity());
 
         // Keep only those bounds which may apply, and propagate overflow if it occurs.
-        for bound in matching_bounds {
-            if bound.skip_binder().polarity != stack.obligation.predicate.skip_binder().polarity {
-                continue;
-            }
-
+        for bound in bounds {
             // FIXME(oli-obk): it is suspicious that we are dropping the constness and
             // polarity here.
             let wc = self.where_clause_may_apply(stack, bound.map_bound(|t| t.trait_ref))?;
@@ -755,7 +750,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     candidates.ambiguous = true;
                 }
                 ty::Coroutine(coroutine_def_id, _)
-                    if self.tcx().lang_items().unpin_trait() == Some(def_id) =>
+                    if self.tcx().is_lang_item(def_id, LangItem::Unpin) =>
                 {
                     match self.tcx().coroutine_movability(coroutine_def_id) {
                         hir::Movability::Static => {
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 749081006f3..074fd487888 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -258,16 +258,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     ) -> Vec<PredicateObligation<'tcx>> {
         debug!(?obligation, ?has_nested, "confirm_builtin_candidate");
 
-        let lang_items = self.tcx().lang_items();
+        let tcx = self.tcx();
         let obligations = if has_nested {
             let trait_def = obligation.predicate.def_id();
-            let conditions = if Some(trait_def) == lang_items.sized_trait() {
+            let conditions = if tcx.is_lang_item(trait_def, LangItem::Sized) {
                 self.sized_conditions(obligation)
-            } else if Some(trait_def) == lang_items.copy_trait() {
+            } else if tcx.is_lang_item(trait_def, LangItem::Copy) {
                 self.copy_clone_conditions(obligation)
-            } else if Some(trait_def) == lang_items.clone_trait() {
+            } else if tcx.is_lang_item(trait_def, LangItem::Clone) {
                 self.copy_clone_conditions(obligation)
-            } else if Some(trait_def) == lang_items.fused_iterator_trait() {
+            } else if tcx.is_lang_item(trait_def, LangItem::FusedIterator) {
                 self.fused_iterator_conditions(obligation)
             } else {
                 bug!("unexpected builtin trait {:?}", trait_def)
@@ -338,7 +338,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     let make_freeze_obl = |ty| {
                         let trait_ref = ty::TraitRef::new(
                             tcx,
-                            tcx.lang_items().freeze_trait().unwrap(),
+                            tcx.require_lang_item(LangItem::Freeze, None),
                             [ty::GenericArg::from(ty)],
                         );
                         Obligation::with_depth(
@@ -1444,7 +1444,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | ty::Foreign(_) => {}
 
                 // `ManuallyDrop` is trivially drop
-                ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().manually_drop() => {}
+                ty::Adt(def, _) if def.is_manually_drop() => {}
 
                 // These types are built-in, so we can fast-track by registering
                 // nested predicates for their constituent type(s)
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 4306a803524..b4019585771 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -32,7 +32,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{Diag, EmissionGuarantee};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_infer::infer::relate::MatchAgainstFreshVars;
+use rustc_hir::LangItem;
 use rustc_infer::infer::relate::TypeRelation;
 use rustc_infer::infer::BoundRegionConversionTime;
 use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType;
@@ -60,6 +60,7 @@ use std::ops::ControlFlow;
 pub use rustc_middle::traits::select::*;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 
+mod _match;
 mod candidate_assembly;
 mod confirmation;
 
@@ -1866,7 +1867,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         // the param_env so that it can be given the lowest priority. See
         // #50825 for the motivation for this.
         let is_global =
-            |cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars();
+            |cand: ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars();
 
         // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
         // `DiscriminantKindCandidate`, `ConstDestructCandidate`
@@ -1909,7 +1910,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
             }
 
             (
-                ParamCandidate(ref other_cand),
+                ParamCandidate(other_cand),
                 ImplCandidate(..)
                 | AutoImplCandidate
                 | ClosureCandidate { .. }
@@ -1934,12 +1935,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 //
                 // Global bounds from the where clause should be ignored
                 // here (see issue #50825).
-                DropVictim::drop_if(!is_global(other_cand))
+                DropVictim::drop_if(!is_global(*other_cand))
             }
-            (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref victim_cand)) => {
+            (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(victim_cand)) => {
                 // Prefer these to a global where-clause bound
                 // (see issue #50825).
-                if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No }
+                if is_global(*victim_cand) { DropVictim::Yes } else { DropVictim::No }
             }
             (
                 ImplCandidate(_)
@@ -1957,12 +1958,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 | TraitUpcastingUnsizeCandidate(_)
                 | BuiltinCandidate { has_nested: true }
                 | TraitAliasCandidate,
-                ParamCandidate(ref victim_cand),
+                ParamCandidate(victim_cand),
             ) => {
                 // Prefer these to a global where-clause bound
                 // (see issue #50825).
                 DropVictim::drop_if(
-                    is_global(victim_cand) && other.evaluation.must_apply_modulo_regions(),
+                    is_global(*victim_cand) && other.evaluation.must_apply_modulo_regions(),
                 )
             }
 
@@ -2719,7 +2720,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         previous: ty::PolyTraitPredicate<'tcx>,
         current: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
-        let mut matcher = MatchAgainstFreshVars::new(self.tcx());
+        let mut matcher = _match::MatchAgainstFreshVars::new(self.tcx());
         matcher.relate(previous, current).is_ok()
     }
 
@@ -2800,19 +2801,18 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         let predicates = predicates.instantiate_own(tcx, args);
         let mut obligations = Vec::with_capacity(predicates.len());
         for (index, (predicate, span)) in predicates.into_iter().enumerate() {
-            let cause =
-                if Some(parent_trait_pred.def_id()) == tcx.lang_items().coerce_unsized_trait() {
-                    cause.clone()
-                } else {
-                    cause.clone().derived_cause(parent_trait_pred, |derived| {
-                        ObligationCauseCode::ImplDerived(Box::new(ImplDerivedCause {
-                            derived,
-                            impl_or_alias_def_id: def_id,
-                            impl_def_predicate_index: Some(index),
-                            span,
-                        }))
-                    })
-                };
+            let cause = if tcx.is_lang_item(parent_trait_pred.def_id(), LangItem::CoerceUnsized) {
+                cause.clone()
+            } else {
+                cause.clone().derived_cause(parent_trait_pred, |derived| {
+                    ObligationCauseCode::ImplDerived(Box::new(ImplDerivedCause {
+                        derived,
+                        impl_or_alias_def_id: def_id,
+                        impl_def_predicate_index: Some(index),
+                        span,
+                    }))
+                })
+            };
             let clause = normalize_with_depth_to(
                 self,
                 param_env,
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 960c27b636e..ce7245d93a4 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -132,7 +132,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
         debug!(?predicates);
 
         let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
-            pred.instantiate_supertrait(tcx, &trait_ref)
+            pred.instantiate_supertrait(tcx, trait_ref)
                 .as_trait_clause()
                 .map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span))
         });
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index c93ec43944a..9bd4a9aab0a 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -125,7 +125,7 @@ fn prepare_vtable_segments_inner<'tcx, T>(
                 .predicates
                 .into_iter()
                 .filter_map(move |(pred, _)| {
-                    pred.instantiate_supertrait(tcx, &inner_most_trait_ref).as_trait_clause()
+                    pred.instantiate_supertrait(tcx, inner_most_trait_ref).as_trait_clause()
                 });
 
             // Find an unvisited supertrait
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index eae1a9dfaa2..241381f5875 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -331,30 +331,63 @@ pub(crate) mod rustc {
             assert!(def.is_enum());
             let layout = ty_and_layout.layout;
 
-            if let Variants::Multiple { tag_field, .. } = layout.variants() {
-                // For enums (but not coroutines), the tag field is
-                // currently always the first field of the layout.
-                assert_eq!(*tag_field, 0);
-            }
+            // Computes the variant of a given index.
+            let layout_of_variant = |index| {
+                let tag = cx.tcx.tag_for_variant((ty_and_layout.ty, index));
+                let variant_def = Def::Variant(def.variant(index));
+                let variant_ty_and_layout = ty_and_layout.for_variant(&cx, index);
+                Self::from_variant(variant_def, tag, variant_ty_and_layout, layout.size, cx)
+            };
 
-            let variants = def.discriminants(cx.tcx()).try_fold(
-                Self::uninhabited(),
-                |variants, (idx, ref discriminant)| {
-                    let tag = cx.tcx.tag_for_variant((ty_and_layout.ty, idx));
-                    let variant_def = Def::Variant(def.variant(idx));
-                    let variant_ty_and_layout = ty_and_layout.for_variant(&cx, idx);
-                    let variant = Self::from_variant(
-                        variant_def,
-                        tag,
-                        variant_ty_and_layout,
-                        layout.size,
-                        cx,
+            // We consider three kinds of enums, each demanding a different
+            // treatment of their layout computation:
+            // 1. enums that are uninhabited
+            // 2. enums for which all but one variant is uninhabited
+            // 3. enums with multiple inhabited variants
+            match layout.variants() {
+                _ if layout.abi.is_uninhabited() => {
+                    // Uninhabited enums are usually (always?) zero-sized. In
+                    // the (unlikely?) event that an uninhabited enum is
+                    // non-zero-sized, this assert will trigger an ICE, and this
+                    // code should be modified such that a `layout.size` amount
+                    // of uninhabited bytes is returned instead.
+                    //
+                    // Uninhabited enums are currently implemented such that
+                    // their layout is described with `Variants::Single`, even
+                    // though they don't necessarily have a 'single' variant to
+                    // defer to. That said, we don't bother specifically
+                    // matching on `Variants::Single` in this arm because the
+                    // behavioral principles here remain true even if, for
+                    // whatever reason, the compiler describes an uninhabited
+                    // enum with `Variants::Multiple`.
+                    assert_eq!(layout.size, Size::ZERO);
+                    Ok(Self::uninhabited())
+                }
+                Variants::Single { index } => {
+                    // `Variants::Single` on non-uninhabited enums denotes that
+                    // the enum delegates its layout to the variant at `index`.
+                    layout_of_variant(*index)
+                }
+                Variants::Multiple { tag_field, .. } => {
+                    // `Variants::Multiple` denotes an enum with multiple
+                    // inhabited variants. The layout of such an enum is the
+                    // disjunction of the layouts of its tagged variants.
+
+                    // For enums (but not coroutines), the tag field is
+                    // currently always the first field of the layout.
+                    assert_eq!(*tag_field, 0);
+
+                    let variants = def.discriminants(cx.tcx()).try_fold(
+                        Self::uninhabited(),
+                        |variants, (idx, ref discriminant)| {
+                            let variant = layout_of_variant(idx)?;
+                            Result::<Self, Err>::Ok(variants.or(variant))
+                        },
                     )?;
-                    Result::<Self, Err>::Ok(variants.or(variant))
-                },
-            )?;
 
-            return Ok(Self::def(Def::Adt(def)).then(variants));
+                    return Ok(Self::def(Def::Adt(def)).then(variants));
+                }
+            }
         }
 
         /// Constructs a `Tree` from a 'variant-like' layout.
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index e4dcea785d4..094903f61d4 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -1,5 +1,6 @@
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::DefId;
+use rustc_hir::LangItem;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
@@ -34,7 +35,7 @@ fn resolve_instance<'tcx>(
         let def = if tcx.intrinsic(def_id).is_some() {
             debug!(" => intrinsic");
             ty::InstanceDef::Intrinsic(def_id)
-        } else if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
+        } else if tcx.is_lang_item(def_id, LangItem::DropInPlace) {
             let ty = args.type_at(0);
 
             if ty.needs_drop(tcx, param_env) {
@@ -57,7 +58,7 @@ fn resolve_instance<'tcx>(
                 debug!(" => trivial drop glue");
                 ty::InstanceDef::DropGlue(def_id, None)
             }
-        } else if Some(def_id) == tcx.lang_items().async_drop_in_place_fn() {
+        } else if tcx.is_lang_item(def_id, LangItem::AsyncDropInPlace) {
             let ty = args.type_at(0);
 
             if ty.async_drop_glue_morphology(tcx) != AsyncDropGlueMorphology::Noop {
@@ -221,8 +222,7 @@ fn resolve_associated_item<'tcx>(
             )
         }
         traits::ImplSource::Builtin(BuiltinImplSource::Misc, _) => {
-            let lang_items = tcx.lang_items();
-            if Some(trait_ref.def_id) == lang_items.clone_trait() {
+            if tcx.is_lang_item(trait_ref.def_id, LangItem::Clone) {
                 // FIXME(eddyb) use lang items for methods instead of names.
                 let name = tcx.item_name(trait_item_id);
                 if name == sym::clone {
@@ -248,8 +248,8 @@ fn resolve_associated_item<'tcx>(
                     let args = tcx.erase_regions(rcvr_args);
                     Some(ty::Instance::new(trait_item_id, args))
                 }
-            } else if Some(trait_ref.def_id) == lang_items.fn_ptr_trait() {
-                if lang_items.fn_ptr_addr() == Some(trait_item_id) {
+            } else if tcx.is_lang_item(trait_ref.def_id, LangItem::FnPtrTrait) {
+                if tcx.is_lang_item(trait_item_id, LangItem::FnPtrAddr) {
                     let self_ty = trait_ref.self_ty();
                     if !matches!(self_ty.kind(), ty::FnPtr(..)) {
                         return Ok(None);
diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs
index 24e10722448..4a5f34e3542 100644
--- a/compiler/rustc_type_ir/src/infcx.rs
+++ b/compiler/rustc_type_ir/src/infcx.rs
@@ -1,23 +1,77 @@
-use crate::{ConstVid, EffectVid, FloatVid, IntVid, Interner, RegionVid, TyVid, UniverseIndex};
+use crate::fold::TypeFoldable;
+use crate::relate::Relate;
+use crate::solve::{Goal, NoSolution};
+use crate::{self as ty, Interner};
 
-pub trait InferCtxtLike {
+pub trait InferCtxtLike: Sized {
     type Interner: Interner;
 
     fn interner(&self) -> Self::Interner;
 
-    fn universe_of_ty(&self, ty: TyVid) -> Option<UniverseIndex>;
-    fn universe_of_lt(&self, lt: RegionVid) -> Option<UniverseIndex>;
-    fn universe_of_ct(&self, ct: ConstVid) -> Option<UniverseIndex>;
+    fn universe_of_ty(&self, ty: ty::TyVid) -> Option<ty::UniverseIndex>;
+    fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex>;
+    fn universe_of_ct(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex>;
 
-    fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> <Self::Interner as Interner>::Ty;
-    fn opportunistic_resolve_int_var(&self, vid: IntVid) -> <Self::Interner as Interner>::Ty;
-    fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> <Self::Interner as Interner>::Ty;
-    fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> <Self::Interner as Interner>::Const;
+    fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
+    fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid;
+
+    fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> <Self::Interner as Interner>::Ty;
+    fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> <Self::Interner as Interner>::Ty;
+    fn opportunistic_resolve_float_var(
+        &self,
+        vid: ty::FloatVid,
+    ) -> <Self::Interner as Interner>::Ty;
+    fn opportunistic_resolve_ct_var(
+        &self,
+        vid: ty::ConstVid,
+    ) -> <Self::Interner as Interner>::Const;
     fn opportunistic_resolve_effect_var(
         &self,
-        vid: EffectVid,
+        vid: ty::EffectVid,
     ) -> <Self::Interner as Interner>::Const;
-    fn opportunistic_resolve_lt_var(&self, vid: RegionVid) -> <Self::Interner as Interner>::Region;
+    fn opportunistic_resolve_lt_var(
+        &self,
+        vid: ty::RegionVid,
+    ) -> <Self::Interner as Interner>::Region;
 
     fn defining_opaque_types(&self) -> <Self::Interner as Interner>::DefiningOpaqueTypes;
+
+    fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
+    fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
+    fn fresh_args_for_item(
+        &self,
+        def_id: <Self::Interner as Interner>::DefId,
+    ) -> <Self::Interner as Interner>::GenericArgs;
+
+    fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
+        &self,
+        value: ty::Binder<Self::Interner, T>,
+    ) -> T;
+
+    fn enter_forall<T: TypeFoldable<Self::Interner> + Copy, U>(
+        &self,
+        value: ty::Binder<Self::Interner, T>,
+        f: impl FnOnce(T) -> U,
+    ) -> U;
+
+    fn relate<T: Relate<Self::Interner>>(
+        &self,
+        param_env: <Self::Interner as Interner>::ParamEnv,
+        lhs: T,
+        variance: ty::Variance,
+        rhs: T,
+    ) -> Result<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>, NoSolution>;
+
+    fn eq_structurally_relating_aliases<T: Relate<Self::Interner>>(
+        &self,
+        param_env: <Self::Interner as Interner>::ParamEnv,
+        lhs: T,
+        rhs: T,
+    ) -> Result<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>, NoSolution>;
+
+    fn resolve_vars_if_possible<T>(&self, value: T) -> T
+    where
+        T: TypeFoldable<Self::Interner>;
+
+    fn probe<T>(&self, probe: impl FnOnce() -> T) -> T;
 }
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 2fc765f1c8f..6b84592978a 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -29,6 +29,8 @@ pub trait Ty<I: Interner<Ty = Self>>:
 {
     fn new_bool(interner: I) -> Self;
 
+    fn new_u8(interner: I) -> Self;
+
     fn new_infer(interner: I, var: ty::InferTy) -> Self;
 
     fn new_var(interner: I, var: ty::TyVid) -> Self;
@@ -39,6 +41,18 @@ pub trait Ty<I: Interner<Ty = Self>>:
 
     fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy<I>) -> Self;
 
+    fn new_projection(
+        interner: I,
+        def_id: I::DefId,
+        args: impl IntoIterator<Item: Into<I::GenericArg>>,
+    ) -> Self {
+        Ty::new_alias(
+            interner,
+            ty::AliasTyKind::Projection,
+            ty::AliasTy::new(interner, def_id, args),
+        )
+    }
+
     fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self;
 
     fn new_adt(interner: I, adt_def: I::AdtDef, args: I::GenericArgs) -> Self;
@@ -75,6 +89,12 @@ pub trait Ty<I: Interner<Ty = Self>>:
         It: Iterator<Item = T>,
         T: CollectAndApply<Self, Self>;
 
+    fn new_fn_def(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
+
+    fn new_fn_ptr(interner: I, sig: ty::Binder<I, ty::FnSig<I>>) -> Self;
+
+    fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self;
+
     fn tuple_fields(self) -> I::Tys;
 
     fn to_opt_closure_kind(self) -> Option<ty::ClosureKind>;
@@ -83,11 +103,29 @@ pub trait Ty<I: Interner<Ty = Self>>:
 
     fn from_coroutine_closure_kind(interner: I, kind: ty::ClosureKind) -> Self;
 
-    fn new_fn_def(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
-
-    fn new_fn_ptr(interner: I, sig: ty::Binder<I, ty::FnSig<I>>) -> Self;
-
-    fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self;
+    fn is_ty_var(self) -> bool {
+        matches!(self.kind(), ty::Infer(ty::TyVar(_)))
+    }
+
+    fn fn_sig(self, interner: I) -> ty::Binder<I, ty::FnSig<I>> {
+        match self.kind() {
+            ty::FnPtr(sig) => sig,
+            ty::FnDef(def_id, args) => interner.fn_sig(def_id).instantiate(interner, &args),
+            ty::Error(_) => {
+                // ignore errors (#54954)
+                ty::Binder::dummy(ty::FnSig {
+                    inputs_and_output: Default::default(),
+                    c_variadic: false,
+                    safety: I::Safety::safe(),
+                    abi: I::Abi::rust(),
+                })
+            }
+            ty::Closure(..) => panic!(
+                "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",
+            ),
+            _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self),
+        }
+    }
 }
 
 pub trait Tys<I: Interner<Tys = Self>>:
@@ -103,12 +141,16 @@ pub trait Tys<I: Interner<Tys = Self>>:
     fn split_inputs_and_output(self) -> (I::FnInputTys, I::Ty);
 }
 
-pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq + TypeVisitable<I> {
+pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq + Relate<I> {
+    fn rust() -> Self;
+
     /// Whether this ABI is `extern "Rust"`.
     fn is_rust(self) -> bool;
 }
 
-pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq + TypeVisitable<I> {
+pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq + Relate<I> {
+    fn safe() -> Self;
+
     fn is_safe(self) -> bool;
 
     fn prefix_str(self) -> &'static str;
@@ -122,7 +164,6 @@ pub trait Region<I: Interner<Region = Self>>:
     + Into<I::GenericArg>
     + IntoKind<Kind = ty::RegionKind<I>>
     + Flags
-    + TypeVisitable<I>
     + Relate<I>
 {
     fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundRegion) -> Self;
@@ -158,12 +199,57 @@ pub trait Const<I: Interner<Const = Self>>:
     fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>) -> Self;
 
     fn new_expr(interner: I, expr: I::ExprConst) -> Self;
+
+    fn is_ct_var(self) -> bool {
+        matches!(self.kind(), ty::ConstKind::Infer(ty::InferConst::Var(_)))
+    }
 }
 
 pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
     fn count(&self) -> usize;
 }
 
+pub trait GenericArg<I: Interner<GenericArg = Self>>:
+    Copy
+    + Debug
+    + Hash
+    + Eq
+    + IntoKind<Kind = ty::GenericArgKind<I>>
+    + TypeVisitable<I>
+    + Relate<I>
+    + From<I::Ty>
+    + From<I::Region>
+    + From<I::Const>
+{
+}
+
+pub trait Term<I: Interner<Term = Self>>:
+    Copy + Debug + Hash + Eq + IntoKind<Kind = ty::TermKind<I>> + TypeFoldable<I> + Relate<I>
+{
+    fn as_type(&self) -> Option<I::Ty> {
+        if let ty::TermKind::Ty(ty) = self.kind() { Some(ty) } else { None }
+    }
+
+    fn expect_type(&self) -> I::Ty {
+        self.as_type().expect("expected a type, but found a const")
+    }
+
+    fn as_const(&self) -> Option<I::Const> {
+        if let ty::TermKind::Const(c) = self.kind() { Some(c) } else { None }
+    }
+
+    fn expect_const(&self) -> I::Const {
+        self.as_const().expect("expected a const, but found a type")
+    }
+
+    fn is_infer(self) -> bool {
+        match self.kind() {
+            ty::TermKind::Ty(ty) => ty.is_ty_var(),
+            ty::TermKind::Const(ct) => ct.is_ct_var(),
+        }
+    }
+}
+
 pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
     Copy
     + Debug
@@ -172,7 +258,6 @@ pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
     + IntoIterator<Item = I::GenericArg>
     + Deref<Target: Deref<Target = [I::GenericArg]>>
     + Default
-    + TypeFoldable<I>
     + Relate<I>
 {
     fn type_at(self, i: usize) -> I::Ty;
@@ -188,6 +273,16 @@ pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
     fn split_closure_args(self) -> ty::ClosureArgsParts<I>;
     fn split_coroutine_closure_args(self) -> ty::CoroutineClosureArgsParts<I>;
     fn split_coroutine_args(self) -> ty::CoroutineArgsParts<I>;
+
+    fn as_closure(self) -> ty::ClosureArgs<I> {
+        ty::ClosureArgs { args: self }
+    }
+    fn as_coroutine_closure(self) -> ty::CoroutineClosureArgs<I> {
+        ty::CoroutineClosureArgs { args: self }
+    }
+    fn as_coroutine(self) -> ty::CoroutineArgs<I> {
+        ty::CoroutineArgs { args: self }
+    }
 }
 
 pub trait Predicate<I: Interner<Predicate = Self>>:
@@ -198,9 +293,20 @@ pub trait Predicate<I: Interner<Predicate = Self>>:
     + TypeSuperVisitable<I>
     + TypeSuperFoldable<I>
     + Flags
+    + UpcastFrom<I, ty::PredicateKind<I>>
+    + UpcastFrom<I, ty::Binder<I, ty::PredicateKind<I>>>
+    + UpcastFrom<I, ty::ClauseKind<I>>
+    + UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
+    + UpcastFrom<I, I::Clause>
     + UpcastFrom<I, ty::NormalizesTo<I>>
+    + UpcastFrom<I, ty::TraitRef<I>>
+    + UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
+    + IntoKind<Kind = ty::Binder<I, ty::PredicateKind<I>>>
 {
     fn is_coinductive(self, interner: I) -> bool;
+
+    // FIXME: Eventually uplift the impl out of rustc and make this defaulted.
+    fn allow_normalization(self) -> bool;
 }
 
 pub trait Clause<I: Interner<Clause = Self>>:
@@ -208,6 +314,7 @@ pub trait Clause<I: Interner<Clause = Self>>:
     + Debug
     + Hash
     + Eq
+    + TypeFoldable<I>
     // FIXME: Remove these, uplift the `Upcast` impls.
     + UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
     + UpcastFrom<I, ty::Binder<I, ty::ProjectionPredicate<I>>>
@@ -242,8 +349,17 @@ pub trait ParamLike {
 
 pub trait AdtDef<I: Interner>: Copy + Debug + Hash + Eq {
     fn def_id(self) -> I::DefId;
+
+    fn is_phantom_data(self) -> bool;
+
+    // FIXME: perhaps use `all_fields` and expose `FieldDef`.
+    fn all_field_tys(self, interner: I) -> ty::EarlyBinder<I, impl Iterator<Item = I::Ty>>;
+
+    fn sized_constraint(self, interner: I) -> Option<ty::EarlyBinder<I, I::Ty>>;
 }
 
 pub trait Features<I: Interner>: Copy {
     fn generic_const_exprs(self) -> bool;
+
+    fn coroutine_clone(self) -> bool;
 }
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index b7f412ecb8e..a2b71e1fc25 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -1,3 +1,4 @@
+use rustc_ast_ir::Movability;
 use smallvec::SmallVec;
 use std::fmt::Debug;
 use std::hash::Hash;
@@ -6,6 +7,7 @@ use std::ops::Deref;
 use crate::fold::TypeFoldable;
 use crate::inherent::*;
 use crate::ir_print::IrPrint;
+use crate::lang_items::TraitSolverLangItem;
 use crate::relate::Relate;
 use crate::solve::inspect::CanonicalGoalEvaluationStep;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
@@ -31,20 +33,8 @@ pub trait Interner:
 
     type GenericArgs: GenericArgs<Self>;
     type GenericArgsSlice: Copy + Debug + Hash + Eq + Deref<Target = [Self::GenericArg]>;
-    type GenericArg: Copy
-        + Debug
-        + Hash
-        + Eq
-        + IntoKind<Kind = ty::GenericArgKind<Self>>
-        + TypeVisitable<Self>
-        + Relate<Self>;
-    type Term: Copy
-        + Debug
-        + Hash
-        + Eq
-        + IntoKind<Kind = ty::TermKind<Self>>
-        + TypeFoldable<Self>
-        + Relate<Self>;
+    type GenericArg: GenericArg<Self>;
+    type Term: Term<Self>;
 
     type BoundVarKinds: Copy
         + Debug
@@ -74,11 +64,16 @@ pub trait Interner:
 
     // Things stored inside of tys
     type ErrorGuaranteed: Copy + Debug + Hash + Eq;
-    type BoundExistentialPredicates: Copy + Debug + Hash + Eq + Relate<Self>;
+    type BoundExistentialPredicates: Copy
+        + Debug
+        + Hash
+        + Eq
+        + Relate<Self>
+        + IntoIterator<Item = ty::Binder<Self, ty::ExistentialPredicate<Self>>>;
     type AllocId: Copy + Debug + Hash + Eq;
     type Pat: Copy + Debug + Hash + Eq + Debug + Relate<Self>;
-    type Safety: Safety<Self> + TypeFoldable<Self> + Relate<Self>;
-    type Abi: Abi<Self> + TypeFoldable<Self> + Relate<Self>;
+    type Safety: Safety<Self>;
+    type Abi: Abi<Self>;
 
     // Kinds of consts
     type Const: Const<Self>;
@@ -153,6 +148,38 @@ pub trait Interner:
 
     type Features: Features<Self>;
     fn features(self) -> Self::Features;
+
+    fn bound_coroutine_hidden_types(
+        self,
+        def_id: Self::DefId,
+    ) -> impl IntoIterator<Item = ty::EarlyBinder<Self, ty::Binder<Self, Self::Ty>>>;
+
+    fn fn_sig(
+        self,
+        def_id: Self::DefId,
+    ) -> ty::EarlyBinder<Self, ty::Binder<Self, ty::FnSig<Self>>>;
+
+    fn coroutine_movability(self, def_id: Self::DefId) -> Movability;
+
+    fn coroutine_for_closure(self, def_id: Self::DefId) -> Self::DefId;
+
+    fn generics_require_sized_self(self, def_id: Self::DefId) -> bool;
+
+    fn item_bounds(
+        self,
+        def_id: Self::DefId,
+    ) -> ty::EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>>;
+
+    fn super_predicates_of(
+        self,
+        def_id: Self::DefId,
+    ) -> ty::EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>>;
+
+    fn has_target_features(self, def_id: Self::DefId) -> bool;
+
+    fn require_lang_item(self, lang_item: TraitSolverLangItem) -> Self::DefId;
+
+    fn associated_type_def_ids(self, def_id: Self::DefId) -> impl IntoIterator<Item = Self::DefId>;
 }
 
 /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
diff --git a/compiler/rustc_type_ir/src/lang_items.rs b/compiler/rustc_type_ir/src/lang_items.rs
new file mode 100644
index 00000000000..9a3b324fcd7
--- /dev/null
+++ b/compiler/rustc_type_ir/src/lang_items.rs
@@ -0,0 +1,8 @@
+/// Lang items used by the new trait solver. This can be mapped to whatever internal
+/// representation of `LangItem`s used in the underlying compiler implementation.
+pub enum TraitSolverLangItem {
+    Future,
+    FutureOutput,
+    AsyncFnKindHelper,
+    AsyncFnKindUpvars,
+}
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index a76e278cc05..4775a0f8cbb 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -32,6 +32,7 @@ pub mod error;
 pub mod fold;
 pub mod inherent;
 pub mod ir_print;
+pub mod lang_items;
 pub mod lift;
 pub mod relate;
 pub mod solve;
@@ -73,6 +74,7 @@ pub use DynKind::*;
 pub use InferTy::*;
 pub use RegionKind::*;
 pub use TyKind::*;
+pub use Variance::*;
 
 rustc_index::newtype_index! {
     /// A [De Bruijn index][dbi] is a standard means of representing
diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs
index cae1d13020d..8a6ba87b60e 100644
--- a/compiler/rustc_type_ir/src/relate.rs
+++ b/compiler/rustc_type_ir/src/relate.rs
@@ -128,7 +128,7 @@ pub fn relate_args_invariantly<I: Interner, R: TypeRelation<I>>(
     b_arg: I::GenericArgs,
 ) -> RelateResult<I, I::GenericArgs> {
     relation.tcx().mk_args_from_iter(iter::zip(a_arg, b_arg).map(|(a, b)| {
-        relation.relate_with_variance(ty::Variance::Invariant, VarianceDiagInfo::default(), a, b)
+        relation.relate_with_variance(ty::Invariant, VarianceDiagInfo::default(), a, b)
     }))
 }
 
@@ -145,7 +145,7 @@ pub fn relate_args_with_variances<I: Interner, R: TypeRelation<I>>(
     let mut cached_ty = None;
     let params = iter::zip(a_arg, b_arg).enumerate().map(|(i, (a, b))| {
         let variance = variances[i];
-        let variance_info = if variance == ty::Variance::Invariant && fetch_ty_for_diag {
+        let variance_info = if variance == ty::Invariant && fetch_ty_for_diag {
             let ty =
                 *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).instantiate(tcx, &a_arg));
             VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
@@ -191,7 +191,7 @@ impl<I: Interner> Relate<I> for ty::FnSig<I> {
                     relation.relate(a, b)
                 } else {
                     relation.relate_with_variance(
-                        ty::Variance::Contravariant,
+                        ty::Contravariant,
                         VarianceDiagInfo::default(),
                         a,
                         b,
@@ -311,13 +311,13 @@ impl<I: Interner> Relate<I> for ty::ExistentialProjection<I> {
             }))
         } else {
             let term = relation.relate_with_variance(
-                ty::Variance::Invariant,
+                ty::Invariant,
                 VarianceDiagInfo::default(),
                 a.term,
                 b.term,
             )?;
             let args = relation.relate_with_variance(
-                ty::Variance::Invariant,
+                ty::Invariant,
                 VarianceDiagInfo::default(),
                 a.args,
                 b.args,
@@ -466,9 +466,9 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
             }
 
             let (variance, info) = match a_mutbl {
-                Mutability::Not => (ty::Variance::Covariant, VarianceDiagInfo::None),
+                Mutability::Not => (ty::Covariant, VarianceDiagInfo::None),
                 Mutability::Mut => {
-                    (ty::Variance::Invariant, VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
+                    (ty::Invariant, VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
                 }
             };
 
@@ -483,9 +483,9 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
             }
 
             let (variance, info) = match a_mutbl {
-                Mutability::Not => (ty::Variance::Covariant, VarianceDiagInfo::None),
+                Mutability::Not => (ty::Covariant, VarianceDiagInfo::None),
                 Mutability::Mut => {
-                    (ty::Variance::Invariant, VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
+                    (ty::Invariant, VarianceDiagInfo::Invariant { ty: a, param_index: 0 })
                 }
             };
 
@@ -612,7 +612,7 @@ pub fn structurally_relate_consts<I: Interner, R: TypeRelation<I>>(
             }
 
             let args = relation.relate_with_variance(
-                ty::Variance::Invariant,
+                ty::Invariant,
                 VarianceDiagInfo::default(),
                 au.args,
                 bu.args,
diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs
index 085dfd9ea89..3e138e3c2e0 100644
--- a/compiler/stable_mir/src/compiler_interface.rs
+++ b/compiler/stable_mir/src/compiler_interface.rs
@@ -94,10 +94,6 @@ pub trait Context {
     /// Retrieve the plain function name of an intrinsic.
     fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol;
 
-    /// Returns whether the intrinsic has no meaningful body and all backends
-    /// need to shim all calls to it.
-    fn intrinsic_must_be_overridden(&self, def: IntrinsicDef) -> bool;
-
     /// Retrieve the closure signature for the given generic arguments.
     fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig;
 
diff --git a/compiler/stable_mir/src/crate_def.rs b/compiler/stable_mir/src/crate_def.rs
index 70ca9e6825e..67752a5e629 100644
--- a/compiler/stable_mir/src/crate_def.rs
+++ b/compiler/stable_mir/src/crate_def.rs
@@ -1,7 +1,7 @@
 //! Module that define a common trait for things that represent a crate definition,
 //! such as, a function, a trait, an enum, and any other definitions.
 
-use crate::ty::Span;
+use crate::ty::{GenericArgs, Span, Ty};
 use crate::{with, Crate, Symbol};
 
 /// A unique identification number for each item accessible for the current compilation unit.
@@ -52,6 +52,23 @@ pub trait CrateDef {
     }
 }
 
+/// A trait that can be used to retrieve a definition's type.
+///
+/// Note that not every CrateDef has a type `Ty`. They should not implement this trait.
+pub trait CrateDefType: CrateDef {
+    /// Returns the type of this crate item.
+    fn ty(&self) -> Ty {
+        with(|cx| cx.def_ty(self.def_id()))
+    }
+
+    /// Retrieve the type of this definition by instantiating and normalizing it with `args`.
+    ///
+    /// This will panic if instantiation fails.
+    fn ty_with_args(&self, args: &GenericArgs) -> Ty {
+        with(|cx| cx.def_ty_with_args(self.def_id(), args))
+    }
+}
+
 macro_rules! crate_def {
     ( $(#[$attr:meta])*
       $vis:vis $name:ident $(;)?
@@ -67,3 +84,21 @@ macro_rules! crate_def {
         }
     };
 }
+
+macro_rules! crate_def_with_ty {
+    ( $(#[$attr:meta])*
+      $vis:vis $name:ident $(;)?
+    ) => {
+        $(#[$attr])*
+        #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
+        $vis struct $name(pub DefId);
+
+        impl CrateDef for $name {
+            fn def_id(&self) -> DefId {
+                self.0
+            }
+        }
+
+        impl CrateDefType for $name {}
+    };
+}
diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs
index d9f988935ab..8385856ae53 100644
--- a/compiler/stable_mir/src/lib.rs
+++ b/compiler/stable_mir/src/lib.rs
@@ -22,8 +22,7 @@ use std::fmt::Debug;
 use std::io;
 
 use crate::compiler_interface::with;
-pub use crate::crate_def::CrateDef;
-pub use crate::crate_def::DefId;
+pub use crate::crate_def::{CrateDef, CrateDefType, DefId};
 pub use crate::error::*;
 use crate::mir::Body;
 use crate::mir::Mutability;
@@ -115,12 +114,15 @@ pub enum CtorKind {
 
 pub type Filename = String;
 
-crate_def! {
+crate_def_with_ty! {
     /// Holds information about an item in a crate.
     pub CrateItem;
 }
 
 impl CrateItem {
+    /// This will return the body of an item.
+    ///
+    /// This will panic if no body is available.
     pub fn body(&self) -> mir::Body {
         with(|cx| cx.mir_body(self.0))
     }
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index 43e4682dc10..e0f9e7ae67a 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -637,7 +637,7 @@ pub enum AggregateKind {
 pub enum Operand {
     Copy(Place),
     Move(Place),
-    Constant(Constant),
+    Constant(ConstOperand),
 }
 
 #[derive(Clone, Eq, PartialEq)]
@@ -653,6 +653,13 @@ impl From<Local> for Place {
     }
 }
 
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ConstOperand {
+    pub span: Span,
+    pub user_ty: Option<UserTypeAnnotationIndex>,
+    pub const_: MirConst,
+}
+
 /// Debug information pertaining to a user variable.
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub struct VarDebugInfo {
@@ -714,13 +721,6 @@ pub enum VarDebugInfoContents {
     Const(ConstOperand),
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct ConstOperand {
-    pub span: Span,
-    pub user_ty: Option<UserTypeAnnotationIndex>,
-    pub const_: MirConst,
-}
-
 // In MIR ProjectionElem is parameterized on the second Field argument and the Index argument. This
 // is so it can be used for both Places (for which the projection elements are of type
 // ProjectionElem<Local, Ty>) and user-provided type annotations (for which the projection elements
@@ -829,13 +829,6 @@ pub type FieldIdx = usize;
 
 type UserTypeAnnotationIndex = usize;
 
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Constant {
-    pub span: Span,
-    pub user_ty: Option<UserTypeAnnotationIndex>,
-    pub literal: MirConst,
-}
-
 /// The possible branch sites of a [TerminatorKind::SwitchInt].
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub struct SwitchTargets {
@@ -1001,9 +994,9 @@ impl Operand {
     }
 }
 
-impl Constant {
+impl ConstOperand {
     pub fn ty(&self) -> Ty {
-        self.literal.ty()
+        self.const_.ty()
     }
 }
 
diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs
index 2fb180b84c7..83734a0d138 100644
--- a/compiler/stable_mir/src/mir/pretty.rs
+++ b/compiler/stable_mir/src/mir/pretty.rs
@@ -310,7 +310,7 @@ fn pretty_operand(operand: &Operand) -> String {
         Operand::Move(mv) => {
             format!("move {:?}", mv)
         }
-        Operand::Constant(cnst) => pretty_mir_const(&cnst.literal),
+        Operand::Constant(cnst) => pretty_mir_const(&cnst.const_),
     }
 }
 
diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs
index 10f30083dc2..50d7bae21db 100644
--- a/compiler/stable_mir/src/mir/visit.rs
+++ b/compiler/stable_mir/src/mir/visit.rs
@@ -108,8 +108,8 @@ pub trait MirVisitor {
         self.super_ty(ty)
     }
 
-    fn visit_constant(&mut self, constant: &Constant, location: Location) {
-        self.super_constant(constant, location)
+    fn visit_const_operand(&mut self, constant: &ConstOperand, location: Location) {
+        self.super_const_operand(constant, location)
     }
 
     fn visit_mir_const(&mut self, constant: &MirConst, location: Location) {
@@ -366,7 +366,7 @@ pub trait MirVisitor {
                 self.visit_place(place, PlaceContext::NON_MUTATING, location)
             }
             Operand::Constant(constant) => {
-                self.visit_constant(constant, location);
+                self.visit_const_operand(constant, location);
             }
         }
     }
@@ -380,10 +380,10 @@ pub trait MirVisitor {
         let _ = ty;
     }
 
-    fn super_constant(&mut self, constant: &Constant, location: Location) {
-        let Constant { span, user_ty: _, literal } = constant;
+    fn super_const_operand(&mut self, constant: &ConstOperand, location: Location) {
+        let ConstOperand { span, user_ty: _, const_ } = constant;
         self.visit_span(span);
-        self.visit_mir_const(literal, location);
+        self.visit_mir_const(const_, location);
     }
 
     fn super_mir_const(&mut self, constant: &MirConst, location: Location) {
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index bcbe87f7303..35927237281 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -3,9 +3,10 @@ use super::{
     with, DefId, Error, Symbol,
 };
 use crate::abi::Layout;
+use crate::crate_def::{CrateDef, CrateDefType};
 use crate::mir::alloc::{read_target_int, read_target_uint, AllocId};
+use crate::mir::mono::StaticDef;
 use crate::target::MachineInfo;
-use crate::{crate_def::CrateDef, mir::mono::StaticDef};
 use crate::{Filename, Opaque};
 use std::fmt::{self, Debug, Display, Formatter};
 use std::ops::Range;
@@ -122,7 +123,7 @@ impl TyConst {
     }
 
     /// Creates an interned usize constant.
-    fn try_from_target_usize(val: u64) -> Result<Self, Error> {
+    pub fn try_from_target_usize(val: u64) -> Result<Self, Error> {
         with(|cx| cx.try_new_ty_const_uint(val.into(), UintTy::Usize))
     }
 
@@ -504,6 +505,15 @@ impl TyKind {
     pub fn discriminant_ty(&self) -> Option<Ty> {
         self.rigid().map(|ty| with(|cx| cx.rigid_ty_discriminant_ty(ty)))
     }
+
+    /// Deconstruct a function type if this is one.
+    pub fn fn_def(&self) -> Option<(FnDef, &GenericArgs)> {
+        if let TyKind::RigidTy(RigidTy::FnDef(def, args)) = self {
+            Some((*def, args))
+        } else {
+            None
+        }
+    }
 }
 
 pub struct TypeAndMut {
@@ -629,7 +639,7 @@ impl ForeignModule {
     }
 }
 
-crate_def! {
+crate_def_with_ty! {
     /// Hold information about a ForeignItem in a crate.
     pub ForeignDef;
 }
@@ -647,7 +657,7 @@ pub enum ForeignItemKind {
     Type(Ty),
 }
 
-crate_def! {
+crate_def_with_ty! {
     /// Hold information about a function definition in a crate.
     pub FnDef;
 }
@@ -658,6 +668,11 @@ impl FnDef {
         with(|ctx| ctx.has_body(self.0).then(|| ctx.mir_body(self.0)))
     }
 
+    // Check if the function body is available.
+    pub fn has_body(&self) -> bool {
+        with(|ctx| ctx.has_body(self.0))
+    }
+
     /// Get the information of the intrinsic if this function is a definition of one.
     pub fn as_intrinsic(&self) -> Option<IntrinsicDef> {
         with(|cx| cx.intrinsic(self.def_id()))
@@ -668,9 +683,15 @@ impl FnDef {
     pub fn is_intrinsic(&self) -> bool {
         self.as_intrinsic().is_some()
     }
+
+    /// Get the function signature for this function definition.
+    pub fn fn_sig(&self) -> PolyFnSig {
+        let kind = self.ty().kind();
+        kind.fn_sig().unwrap()
+    }
 }
 
-crate_def! {
+crate_def_with_ty! {
     pub IntrinsicDef;
 }
 
@@ -684,7 +705,7 @@ impl IntrinsicDef {
     /// Returns whether the intrinsic has no meaningful body and all backends
     /// need to shim all calls to it.
     pub fn must_be_overridden(&self) -> bool {
-        with(|cx| cx.intrinsic_must_be_overridden(*self))
+        with(|cx| !cx.has_body(self.0))
     }
 }
 
@@ -710,7 +731,7 @@ crate_def! {
     pub BrNamedDef;
 }
 
-crate_def! {
+crate_def_with_ty! {
     pub AdtDef;
 }
 
@@ -866,7 +887,7 @@ crate_def! {
     pub GenericDef;
 }
 
-crate_def! {
+crate_def_with_ty! {
     pub ConstDef;
 }
 
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 21d00503001..01a954ed75b 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -145,8 +145,7 @@
 //! to `into_iter()` for boxed slices will defer to the slice implementation on editions before
 //! 2024:
 //!
-#![cfg_attr(bootstrap, doc = "```rust,edition2021,ignore")]
-#![cfg_attr(not(bootstrap), doc = "```rust,edition2021")]
+//! ```rust,edition2021
 //! // Rust 2015, 2018, and 2021:
 //!
 //! # #![allow(boxed_slice_into_iter)] // override our `deny(warnings)`
@@ -2123,23 +2122,23 @@ impl<I> FromIterator<I> for Box<[I]> {
 
 /// This implementation is required to make sure that the `Box<[I]>: IntoIterator`
 /// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
-#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
 impl<I, A: Allocator> !Iterator for Box<[I], A> {}
 
 /// This implementation is required to make sure that the `&Box<[I]>: IntoIterator`
 /// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
-#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
 impl<'a, I, A: Allocator> !Iterator for &'a Box<[I], A> {}
 
 /// This implementation is required to make sure that the `&mut Box<[I]>: IntoIterator`
 /// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
-#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
 impl<'a, I, A: Allocator> !Iterator for &'a mut Box<[I], A> {}
 
 // Note: the `#[rustc_skip_during_method_dispatch(boxed_slice)]` on `trait IntoIterator`
 // hides this implementation from explicit `.into_iter()` calls on editions < 2024,
 // so those calls will still resolve to the slice implementation, by reference.
-#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
 impl<I, A: Allocator> IntoIterator for Box<[I], A> {
     type IntoIter = vec::IntoIter<I, A>;
     type Item = I;
@@ -2148,7 +2147,7 @@ impl<I, A: Allocator> IntoIterator for Box<[I], A> {
     }
 }
 
-#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
 impl<'a, I, A: Allocator> IntoIterator for &'a Box<[I], A> {
     type IntoIter = slice::Iter<'a, I>;
     type Item = &'a I;
@@ -2157,7 +2156,7 @@ impl<'a, I, A: Allocator> IntoIterator for &'a Box<[I], A> {
     }
 }
 
-#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
 impl<'a, I, A: Allocator> IntoIterator for &'a mut Box<[I], A> {
     type IntoIter = slice::IterMut<'a, I>;
     type Item = &'a mut I;
@@ -2167,7 +2166,7 @@ impl<'a, I, A: Allocator> IntoIterator for &'a mut Box<[I], A> {
 }
 
 #[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_str_from_iter", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
 impl FromIterator<char> for Box<str> {
     fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
         String::from_iter(iter).into_boxed_str()
@@ -2175,7 +2174,7 @@ impl FromIterator<char> for Box<str> {
 }
 
 #[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_str_from_iter", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
 impl<'a> FromIterator<&'a char> for Box<str> {
     fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
         String::from_iter(iter).into_boxed_str()
@@ -2183,7 +2182,7 @@ impl<'a> FromIterator<&'a char> for Box<str> {
 }
 
 #[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_str_from_iter", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
 impl<'a> FromIterator<&'a str> for Box<str> {
     fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
         String::from_iter(iter).into_boxed_str()
@@ -2191,7 +2190,7 @@ impl<'a> FromIterator<&'a str> for Box<str> {
 }
 
 #[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_str_from_iter", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
 impl FromIterator<String> for Box<str> {
     fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
         String::from_iter(iter).into_boxed_str()
@@ -2199,7 +2198,7 @@ impl FromIterator<String> for Box<str> {
 }
 
 #[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_str_from_iter", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
 impl<A: Allocator> FromIterator<Box<str, A>> for Box<str> {
     fn from_iter<T: IntoIterator<Item = Box<str, A>>>(iter: T) -> Self {
         String::from_iter(iter).into_boxed_str()
@@ -2207,7 +2206,7 @@ impl<A: Allocator> FromIterator<Box<str, A>> for Box<str> {
 }
 
 #[cfg(not(no_global_oom_handling))]
-#[stable(feature = "boxed_str_from_iter", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "boxed_str_from_iter", since = "1.80.0")]
 impl<'a> FromIterator<Cow<'a, str>> for Box<str> {
     fn from_iter<T: IntoIterator<Item = Cow<'a, str>>>(iter: T) -> Self {
         String::from_iter(iter).into_boxed_str()
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index a391141827e..af01db19139 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -440,10 +440,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// heap.push(4);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(
-        feature = "const_binary_heap_constructor",
-        since = "CURRENT_RUSTC_VERSION"
-    )]
+    #[rustc_const_stable(feature = "const_binary_heap_constructor", since = "1.80.0")]
     #[must_use]
     pub const fn new() -> BinaryHeap<T> {
         BinaryHeap { data: vec![] }
@@ -1224,7 +1221,7 @@ impl<T, A: Allocator> BinaryHeap<T, A> {
     /// io::sink().write(heap.as_slice()).unwrap();
     /// ```
     #[must_use]
-    #[stable(feature = "binary_heap_as_slice", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "binary_heap_as_slice", since = "1.80.0")]
     pub fn as_slice(&self) -> &[T] {
         self.data.as_slice()
     }
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index b13af93d06c..f1eb195b884 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -911,7 +911,7 @@ impl From<&CStr> for Rc<CStr> {
 }
 
 #[cfg(not(no_global_oom_handling))]
-#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "more_rc_default_impls", since = "1.80.0")]
 impl Default for Rc<CStr> {
     /// Creates an empty CStr inside an Rc
     ///
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 4749b8880fb..895d1b8d59f 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -165,7 +165,6 @@
 //
 // Language features:
 // tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(exclusive_range_pattern))]
 #![cfg_attr(not(test), feature(coroutine_trait))]
 #![cfg_attr(test, feature(panic_update_hook))]
 #![cfg_attr(test, feature(test))]
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index f3a4803e0d4..2b7ab2f6e25 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -2250,7 +2250,7 @@ impl<T: Default> Default for Rc<T> {
 }
 
 #[cfg(not(no_global_oom_handling))]
-#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "more_rc_default_impls", since = "1.80.0")]
 impl Default for Rc<str> {
     /// Creates an empty str inside an Rc
     ///
@@ -2262,7 +2262,7 @@ impl Default for Rc<str> {
 }
 
 #[cfg(not(no_global_oom_handling))]
-#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "more_rc_default_impls", since = "1.80.0")]
 impl<T> Default for Rc<[T]> {
     /// Creates an empty `[T]` inside an Rc
     ///
@@ -3516,7 +3516,7 @@ fn data_offset_align(align: usize) -> usize {
     layout.size() + layout.padding_needed_for(align)
 }
 
-/// A uniquely owned `Rc`
+/// A uniquely owned [`Rc`].
 ///
 /// This represents an `Rc` that is known to be uniquely owned -- that is, have exactly one strong
 /// reference. Multiple weak pointers can be created, but attempts to upgrade those to strong
@@ -3554,13 +3554,24 @@ fn data_offset_align(align: usize) -> usize {
 /// including fallible or async constructors.
 #[unstable(feature = "unique_rc_arc", issue = "112566")]
 #[derive(Debug)]
-pub struct UniqueRc<T> {
+pub struct UniqueRc<
+    T: ?Sized,
+    #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
+> {
     ptr: NonNull<RcBox<T>>,
     phantom: PhantomData<RcBox<T>>,
+    alloc: A,
 }
 
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<UniqueRc<U, A>>
+    for UniqueRc<T, A>
+{
+}
+
+// Depends on A = Global
 impl<T> UniqueRc<T> {
-    /// Creates a new `UniqueRc`
+    /// Creates a new `UniqueRc`.
     ///
     /// Weak references to this `UniqueRc` can be created with [`UniqueRc::downgrade`]. Upgrading
     /// these weak references will fail before the `UniqueRc` has been converted into an [`Rc`].
@@ -3569,34 +3580,36 @@ impl<T> UniqueRc<T> {
     #[cfg(not(no_global_oom_handling))]
     #[unstable(feature = "unique_rc_arc", issue = "112566")]
     pub fn new(value: T) -> Self {
-        Self {
-            ptr: Box::leak(Box::new(RcBox {
+        Self::new_in(value, Global)
+    }
+}
+
+impl<T, A: Allocator> UniqueRc<T, A> {
+    /// Creates a new `UniqueRc` in the provided allocator.
+    ///
+    /// Weak references to this `UniqueRc` can be created with [`UniqueRc::downgrade`]. Upgrading
+    /// these weak references will fail before the `UniqueRc` has been converted into an [`Rc`].
+    /// After converting the `UniqueRc` into an [`Rc`], any weak references created beforehand will
+    /// point to the new [`Rc`].
+    #[cfg(not(no_global_oom_handling))]
+    #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    pub fn new_in(value: T, alloc: A) -> Self {
+        let (ptr, alloc) = Box::into_unique(Box::new_in(
+            RcBox {
                 strong: Cell::new(0),
                 // keep one weak reference so if all the weak pointers that are created are dropped
                 // the UniqueRc still stays valid.
                 weak: Cell::new(1),
                 value,
-            }))
-            .into(),
-            phantom: PhantomData,
-        }
-    }
-
-    /// Creates a new weak reference to the `UniqueRc`
-    ///
-    /// Attempting to upgrade this weak reference will fail before the `UniqueRc` has been converted
-    /// to a [`Rc`] using [`UniqueRc::into_rc`].
-    #[unstable(feature = "unique_rc_arc", issue = "112566")]
-    pub fn downgrade(this: &Self) -> Weak<T> {
-        // SAFETY: This pointer was allocated at creation time and we guarantee that we only have
-        // one strong reference before converting to a regular Rc.
-        unsafe {
-            this.ptr.as_ref().inc_weak();
-        }
-        Weak { ptr: this.ptr, alloc: Global }
+            },
+            alloc,
+        ));
+        Self { ptr: ptr.into(), phantom: PhantomData, alloc }
     }
+}
 
-    /// Converts the `UniqueRc` into a regular [`Rc`]
+impl<T: ?Sized, A: Allocator> UniqueRc<T, A> {
+    /// Converts the `UniqueRc` into a regular [`Rc`].
     ///
     /// This consumes the `UniqueRc` and returns a regular [`Rc`] that contains the `value` that
     /// is passed to `into_rc`.
@@ -3604,19 +3617,41 @@ impl<T> UniqueRc<T> {
     /// Any weak references created before this method is called can now be upgraded to strong
     /// references.
     #[unstable(feature = "unique_rc_arc", issue = "112566")]
-    pub fn into_rc(this: Self) -> Rc<T> {
+    pub fn into_rc(this: Self) -> Rc<T, A> {
         let mut this = ManuallyDrop::new(this);
+
+        // Move the allocator out.
+        // SAFETY: `this.alloc` will not be accessed again, nor dropped because it is in
+        // a `ManuallyDrop`.
+        let alloc: A = unsafe { ptr::read(&this.alloc) };
+
         // SAFETY: This pointer was allocated at creation time so we know it is valid.
         unsafe {
             // Convert our weak reference into a strong reference
             this.ptr.as_mut().strong.set(1);
-            Rc::from_inner(this.ptr)
+            Rc::from_inner_in(this.ptr, alloc)
+        }
+    }
+}
+
+impl<T: ?Sized, A: Allocator + Clone> UniqueRc<T, A> {
+    /// Creates a new weak reference to the `UniqueRc`.
+    ///
+    /// Attempting to upgrade this weak reference will fail before the `UniqueRc` has been converted
+    /// to a [`Rc`] using [`UniqueRc::into_rc`].
+    #[unstable(feature = "unique_rc_arc", issue = "112566")]
+    pub fn downgrade(this: &Self) -> Weak<T, A> {
+        // SAFETY: This pointer was allocated at creation time and we guarantee that we only have
+        // one strong reference before converting to a regular Rc.
+        unsafe {
+            this.ptr.as_ref().inc_weak();
         }
+        Weak { ptr: this.ptr, alloc: this.alloc.clone() }
     }
 }
 
 #[unstable(feature = "unique_rc_arc", issue = "112566")]
-impl<T> Deref for UniqueRc<T> {
+impl<T: ?Sized, A: Allocator> Deref for UniqueRc<T, A> {
     type Target = T;
 
     fn deref(&self) -> &T {
@@ -3626,7 +3661,7 @@ impl<T> Deref for UniqueRc<T> {
 }
 
 #[unstable(feature = "unique_rc_arc", issue = "112566")]
-impl<T> DerefMut for UniqueRc<T> {
+impl<T: ?Sized, A: Allocator> DerefMut for UniqueRc<T, A> {
     fn deref_mut(&mut self) -> &mut T {
         // SAFETY: This pointer was allocated at creation time so we know it is valid. We know we
         // have unique ownership and therefore it's safe to make a mutable reference because
@@ -3636,7 +3671,7 @@ impl<T> DerefMut for UniqueRc<T> {
 }
 
 #[unstable(feature = "unique_rc_arc", issue = "112566")]
-unsafe impl<#[may_dangle] T> Drop for UniqueRc<T> {
+unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueRc<T, A> {
     fn drop(&mut self) {
         unsafe {
             // destroy the contained object
@@ -3646,7 +3681,7 @@ unsafe impl<#[may_dangle] T> Drop for UniqueRc<T> {
             self.ptr.as_ref().dec_weak();
 
             if self.ptr.as_ref().weak() == 0 {
-                Global.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr()));
+                self.alloc.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr()));
             }
         }
     }
diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs
index c8a40603d9d..0f09be7721f 100644
--- a/library/alloc/src/rc/tests.rs
+++ b/library/alloc/src/rc/tests.rs
@@ -606,6 +606,23 @@ fn test_unique_rc_drops_contents() {
     assert!(dropped);
 }
 
+/// Exercise the non-default allocator usage.
+#[test]
+fn test_unique_rc_with_alloc_drops_contents() {
+    let mut dropped = false;
+    struct DropMe<'a>(&'a mut bool);
+    impl Drop for DropMe<'_> {
+        fn drop(&mut self) {
+            *self.0 = true;
+        }
+    }
+    {
+        let rc = UniqueRc::new_in(DropMe(&mut dropped), std::alloc::System);
+        drop(rc);
+    }
+    assert!(dropped);
+}
+
 #[test]
 fn test_unique_rc_weak_clone_holding_ref() {
     let mut v = UniqueRc::new(0u8);
@@ -614,3 +631,12 @@ fn test_unique_rc_weak_clone_holding_ref() {
     let _ = w.clone(); // touch weak count
     *r = 123;
 }
+
+#[test]
+fn test_unique_rc_unsizing_coercion() {
+    let mut rc: UniqueRc<[u8]> = UniqueRc::new([0u8; 3]);
+    assert_eq!(rc.len(), 3);
+    rc[0] = 123;
+    let rc: Rc<[u8]> = UniqueRc::into_rc(rc);
+    assert_eq!(*rc, [123, 0, 0]);
+}
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 5a4f9df614e..60e3918157e 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -3405,7 +3405,7 @@ static STATIC_INNER_SLICE: SliceArcInnerForStatic = SliceArcInnerForStatic {
 };
 
 #[cfg(not(no_global_oom_handling))]
-#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "more_rc_default_impls", since = "1.80.0")]
 impl Default for Arc<str> {
     /// Creates an empty str inside an Arc
     ///
@@ -3420,7 +3420,7 @@ impl Default for Arc<str> {
 }
 
 #[cfg(not(no_global_oom_handling))]
-#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "more_rc_default_impls", since = "1.80.0")]
 impl Default for Arc<core::ffi::CStr> {
     /// Creates an empty CStr inside an Arc
     ///
@@ -3439,7 +3439,7 @@ impl Default for Arc<core::ffi::CStr> {
 }
 
 #[cfg(not(no_global_oom_handling))]
-#[stable(feature = "more_rc_default_impls", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "more_rc_default_impls", since = "1.80.0")]
 impl<T> Default for Arc<[T]> {
     /// Creates an empty `[T]` inside an Arc
     ///
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index aa9b632cbed..743429d26db 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -2649,7 +2649,7 @@ impl<T, A: Allocator, const N: usize> Vec<[T; N], A> {
     /// let mut flattened = vec.into_flattened();
     /// assert_eq!(flattened.pop(), Some(6));
     /// ```
-    #[stable(feature = "slice_flatten", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "slice_flatten", since = "1.80.0")]
     pub fn into_flattened(self) -> Vec<T, A> {
         let (ptr, len, cap, alloc) = self.into_raw_parts_with_alloc();
         let (new_len, new_cap) = if T::IS_ZST {
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index efa0fd7b56c..b3189f14f9e 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -260,7 +260,7 @@ use crate::ptr::{self, NonNull};
 mod lazy;
 mod once;
 
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 pub use lazy::LazyCell;
 #[stable(feature = "once_cell", since = "1.70.0")]
 pub use once::OnceCell;
diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs
index 80b85b95446..7c7130ec075 100644
--- a/library/core/src/cell/lazy.rs
+++ b/library/core/src/cell/lazy.rs
@@ -34,7 +34,7 @@ enum State<T, F> {
 /// //   92
 /// //   92
 /// ```
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 pub struct LazyCell<T, F = fn() -> T> {
     state: UnsafeCell<State<T, F>>,
 }
@@ -54,8 +54,8 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     /// assert_eq!(&*lazy, "HELLO, WORLD!");
     /// ```
     #[inline]
-    #[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "lazy_cell", since = "1.80.0")]
+    #[rustc_const_stable(feature = "lazy_cell", since = "1.80.0")]
     pub const fn new(f: F) -> LazyCell<T, F> {
         LazyCell { state: UnsafeCell::new(State::Uninit(f)) }
     }
@@ -103,7 +103,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     /// assert_eq!(&*lazy, &92);
     /// ```
     #[inline]
-    #[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "lazy_cell", since = "1.80.0")]
     pub fn force(this: &LazyCell<T, F>) -> &T {
         // SAFETY:
         // This invalidates any mutable references to the data. The resulting
@@ -167,7 +167,7 @@ impl<T, F> LazyCell<T, F> {
     }
 }
 
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
     type Target = T;
     #[inline]
@@ -176,7 +176,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
     }
 }
 
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 impl<T: Default> Default for LazyCell<T> {
     /// Creates a new lazy value using `Default` as the initializing function.
     #[inline]
@@ -185,7 +185,7 @@ impl<T: Default> Default for LazyCell<T> {
     }
 }
 
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 impl<T: fmt::Debug, F> fmt::Debug for LazyCell<T, F> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut d = f.debug_tuple("LazyCell");
diff --git a/library/core/src/future/async_drop.rs b/library/core/src/future/async_drop.rs
index 25138c445c4..5c3a0a98b10 100644
--- a/library/core/src/future/async_drop.rs
+++ b/library/core/src/future/async_drop.rs
@@ -256,7 +256,6 @@ async unsafe fn either<O: IntoFuture<Output = ()>, M: IntoFuture<Output = ()>, T
     }
 }
 
-#[cfg(not(bootstrap))]
 #[lang = "async_drop_deferred_drop_in_place"]
 async unsafe fn deferred_drop_in_place<T>(to_drop: *mut T) {
     // SAFETY: same safety requirements as with drop_in_place (implied by
diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs
index 86963b548b9..c80cfdcebf7 100644
--- a/library/core/src/future/future.rs
+++ b/library/core/src/future/future.rs
@@ -35,7 +35,7 @@ use crate::task::{Context, Poll};
 pub trait Future {
     /// The type of value produced on completion.
     #[stable(feature = "futures_api", since = "1.36.0")]
-    #[cfg_attr(not(bootstrap), lang = "future_output")]
+    #[lang = "future_output"]
     type Output;
 
     /// Attempt to resolve the future to a final value, registering
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 28397fe4619..6b5054a9f06 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -986,7 +986,7 @@ pub const unsafe fn assume(b: bool) {
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
 #[rustc_nounwind]
-#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)]
+#[miri::intrinsic_fallback_is_spec]
 pub const fn likely(b: bool) -> bool {
     b
 }
@@ -1006,7 +1006,7 @@ pub const fn likely(b: bool) -> bool {
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
 #[rustc_nounwind]
-#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)]
+#[miri::intrinsic_fallback_is_spec]
 pub const fn unlikely(b: bool) -> bool {
     b
 }
@@ -2482,7 +2482,7 @@ extern "rust-intrinsic" {
 #[rustc_nounwind]
 #[rustc_do_not_const_check]
 #[inline]
-#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)]
+#[miri::intrinsic_fallback_is_spec]
 pub const fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8 {
     (ptr == other) as u8
 }
@@ -2747,7 +2747,7 @@ pub const fn ub_checks() -> bool {
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)]
+#[miri::intrinsic_fallback_is_spec]
 pub const unsafe fn const_allocate(_size: usize, _align: usize) -> *mut u8 {
     // const eval overrides this function, but runtime code for now just returns null pointers.
     // See <https://github.com/rust-lang/rust/issues/93935>.
@@ -2768,7 +2768,7 @@ pub const unsafe fn const_allocate(_size: usize, _align: usize) -> *mut u8 {
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)]
+#[miri::intrinsic_fallback_is_spec]
 pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {
     // Runtime NOP
 }
@@ -2828,7 +2828,6 @@ impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P {
 #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
 pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *const P) -> M {
     // To implement a fallback we'd have to assume the layout of the pointer,
     // but the whole point of this intrinsic is that we shouldn't do that.
@@ -3044,8 +3043,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
     unsafe {
         ub_checks::assert_unsafe_precondition!(
             check_language_ub,
-            "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
-            and the specified memory ranges do not overlap",
+            "ptr::copy requires that both pointer arguments are aligned and non-null",
             (
                 src: *const () = src as *const (),
                 dst: *mut () = dst as *mut (),
diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs
index 820f6b2cddc..4be5e62ea5b 100644
--- a/library/core/src/intrinsics/simd.rs
+++ b/library/core/src/intrinsics/simd.rs
@@ -573,7 +573,6 @@ extern "rust-intrinsic" {
     ///
     /// `T` must be a vector of integers.
     #[rustc_nounwind]
-    #[cfg(not(bootstrap))]
     pub fn simd_ctpop<T>(x: T) -> T;
 
     /// Count the trailing zeros of each element.
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index d9d860c7b6c..61a45789013 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -311,8 +311,7 @@ where
     label = "`{Self}` is not an iterator",
     message = "`{Self}` is not an iterator"
 )]
-#[cfg_attr(bootstrap, rustc_skip_array_during_method_dispatch)]
-#[cfg_attr(not(bootstrap), rustc_skip_during_method_dispatch(array, boxed_slice))]
+#[rustc_skip_during_method_dispatch(array, boxed_slice)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait IntoIterator {
     /// The type of the elements being iterated over.
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index cee99e28b5a..733d414d444 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -2080,8 +2080,7 @@ pub trait Iterator {
     fn try_collect<B>(&mut self) -> ChangeOutputType<Self::Item, B>
     where
         Self: Sized,
-        <Self as Iterator>::Item: Try,
-        <<Self as Iterator>::Item as Try>::Residual: Residual<B>,
+        Self::Item: Try<Residual: Residual<B>>,
         B: FromIterator<<Self::Item as Try>::Output>,
     {
         try_process(ByRefSized(self), |i| i.collect())
@@ -2689,12 +2688,13 @@ pub trait Iterator {
     #[inline]
     #[unstable(feature = "iterator_try_reduce", reason = "new API", issue = "87053")]
     #[rustc_do_not_const_check]
-    fn try_reduce<F, R>(&mut self, f: F) -> ChangeOutputType<R, Option<R::Output>>
+    fn try_reduce<R>(
+        &mut self,
+        f: impl FnMut(Self::Item, Self::Item) -> R,
+    ) -> ChangeOutputType<R, Option<R::Output>>
     where
         Self: Sized,
-        F: FnMut(Self::Item, Self::Item) -> R,
-        R: Try<Output = Self::Item>,
-        R::Residual: Residual<Option<Self::Item>>,
+        R: Try<Output = Self::Item, Residual: Residual<Option<Self::Item>>>,
     {
         let first = match self.next() {
             Some(i) => i,
@@ -2956,12 +2956,13 @@ pub trait Iterator {
     #[inline]
     #[unstable(feature = "try_find", reason = "new API", issue = "63178")]
     #[rustc_do_not_const_check]
-    fn try_find<F, R>(&mut self, f: F) -> ChangeOutputType<R, Option<Self::Item>>
+    fn try_find<R>(
+        &mut self,
+        f: impl FnMut(&Self::Item) -> R,
+    ) -> ChangeOutputType<R, Option<Self::Item>>
     where
         Self: Sized,
-        F: FnMut(&Self::Item) -> R,
-        R: Try<Output = bool>,
-        R::Residual: Residual<Option<Self::Item>>,
+        R: Try<Output = bool, Residual: Residual<Option<Self::Item>>>,
     {
         #[inline]
         fn check<I, V, R>(
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
index e008215ebe9..b578756e46a 100644
--- a/library/core/src/net/ip_addr.rs
+++ b/library/core/src/net/ip_addr.rs
@@ -464,7 +464,7 @@ impl Ipv4Addr {
     ///
     /// assert_eq!(Ipv4Addr::BITS, 32);
     /// ```
-    #[stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "ip_bits", since = "1.80.0")]
     pub const BITS: u32 = 32;
 
     /// Converts an IPv4 address into a `u32` representation using native byte order.
@@ -492,8 +492,8 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x00), Ipv4Addr::from_bits(addr_bits));
     ///
     /// ```
-    #[rustc_const_stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")]
-    #[stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
+    #[stable(feature = "ip_bits", since = "1.80.0")]
     #[must_use]
     #[inline]
     pub const fn to_bits(self) -> u32 {
@@ -512,8 +512,8 @@ impl Ipv4Addr {
     /// let addr = Ipv4Addr::from(0x12345678);
     /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr);
     /// ```
-    #[rustc_const_stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")]
-    #[stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
+    #[stable(feature = "ip_bits", since = "1.80.0")]
     #[must_use]
     #[inline]
     pub const fn from_bits(bits: u32) -> Ipv4Addr {
@@ -1238,7 +1238,7 @@ impl Ipv6Addr {
     ///
     /// assert_eq!(Ipv6Addr::BITS, 128);
     /// ```
-    #[stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "ip_bits", since = "1.80.0")]
     pub const BITS: u32 = 128;
 
     /// Converts an IPv6 address into a `u128` representation using native byte order.
@@ -1277,8 +1277,8 @@ impl Ipv6Addr {
     ///     Ipv6Addr::from_bits(addr_bits));
     ///
     /// ```
-    #[rustc_const_stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")]
-    #[stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
+    #[stable(feature = "ip_bits", since = "1.80.0")]
     #[must_use]
     #[inline]
     pub const fn to_bits(self) -> u128 {
@@ -1302,8 +1302,8 @@ impl Ipv6Addr {
     ///     ),
     ///     addr);
     /// ```
-    #[rustc_const_stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")]
-    #[stable(feature = "ip_bits", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
+    #[stable(feature = "ip_bits", since = "1.80.0")]
     #[must_use]
     #[inline]
     pub const fn from_bits(bits: u128) -> Ipv6Addr {
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 96510ee4dca..55bb6166f10 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -1165,17 +1165,13 @@ macro_rules! int_impl {
         #[inline(always)]
         #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
         pub const unsafe fn unchecked_neg(self) -> Self {
-            // ICE resolved by #125184 isn't in bootstrap compiler
-            #[cfg(not(bootstrap))]
-            {
-                assert_unsafe_precondition!(
-                    check_language_ub,
-                    concat!(stringify!($SelfT), "::unchecked_neg cannot overflow"),
-                    (
-                        lhs: $SelfT = self,
-                    ) => !lhs.overflowing_neg().1,
-                );
-            }
+            assert_unsafe_precondition!(
+                check_language_ub,
+                concat!(stringify!($SelfT), "::unchecked_neg cannot overflow"),
+                (
+                    lhs: $SelfT = self,
+                ) => !lhs.overflowing_neg().1,
+            );
 
             // SAFETY: this is guaranteed to be safe by the caller.
             unsafe {
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 863f0d61df3..5956a08593a 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -1059,7 +1059,7 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
             unsafe { Self::new_unchecked(self.get().unchecked_add(other)) }
         }
 
-        /// Returns the smallest power of two greater than or equal to n.
+        /// Returns the smallest power of two greater than or equal to `self`.
         /// Checks for overflow and returns [`None`]
         /// if the next power of two is greater than the type’s maximum value.
         /// As a consequence, the result cannot wrap to zero.
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 1491c27372b..cdbd695008e 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -2830,7 +2830,7 @@ macro_rules! uint_impl {
         ///
         /// When return value overflows (i.e., `self > (1 << (N-1))` for type
         /// `uN`), it panics in debug mode and the return value is wrapped to 0 in
-        /// release mode (the only situation in which method can return 0).
+        /// release mode (the only situation in which this method can return 0).
         ///
         /// # Examples
         ///
@@ -2851,7 +2851,7 @@ macro_rules! uint_impl {
             self.one_less_than_next_power_of_two() + 1
         }
 
-        /// Returns the smallest power of two greater than or equal to `n`. If
+        /// Returns the smallest power of two greater than or equal to `self`. If
         /// the next power of two is greater than the type's maximum value,
         /// `None` is returned, otherwise the power of two is wrapped in `Some`.
         ///
diff --git a/library/core/src/ops/async_function.rs b/library/core/src/ops/async_function.rs
index f4e9d1a63ac..48d1042d9df 100644
--- a/library/core/src/ops/async_function.rs
+++ b/library/core/src/ops/async_function.rs
@@ -26,7 +26,7 @@ pub trait AsyncFn<Args: Tuple>: AsyncFnMut<Args> {
 pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> {
     /// Future returned by [`AsyncFnMut::async_call_mut`] and [`AsyncFn::async_call`].
     #[unstable(feature = "async_fn_traits", issue = "none")]
-    #[cfg_attr(not(bootstrap), lang = "call_ref_future")]
+    #[lang = "call_ref_future"]
     type CallRefFuture<'a>: Future<Output = Self::Output>
     where
         Self: 'a;
@@ -47,12 +47,12 @@ pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> {
 pub trait AsyncFnOnce<Args: Tuple> {
     /// Future returned by [`AsyncFnOnce::async_call_once`].
     #[unstable(feature = "async_fn_traits", issue = "none")]
-    #[cfg_attr(not(bootstrap), lang = "call_once_future")]
+    #[lang = "call_once_future"]
     type CallOnceFuture: Future<Output = Self::Output>;
 
     /// Output type of the called closure's future.
     #[unstable(feature = "async_fn_traits", issue = "none")]
-    #[cfg_attr(not(bootstrap), lang = "async_fn_once_output")]
+    #[lang = "async_fn_once_output"]
     type Output;
 
     /// Call the [`AsyncFnOnce`], returning a future which may move out of the called closure.
@@ -146,7 +146,7 @@ mod internal_implementation_detail {
         // `for<'env> fn() -> (&'env T, ...)`. This allows us to represent the binder
         // of the closure's self-capture, and these upvar types will be instantiated with
         // the `'closure_env` region provided to the associated type.
-        #[cfg_attr(not(bootstrap), lang = "async_fn_kind_upvars")]
+        #[lang = "async_fn_kind_upvars"]
         type Upvars<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>;
     }
 }
diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs
index 6a6c5db1ab1..753f14c6b85 100644
--- a/library/core/src/ops/coroutine.rs
+++ b/library/core/src/ops/coroutine.rs
@@ -76,6 +76,7 @@ pub trait Coroutine<R = ()> {
     /// values which are allowed to be returned each time a coroutine yields.
     /// For example an iterator-as-a-coroutine would likely have this type as
     /// `T`, the type being iterated over.
+    #[cfg_attr(not(bootstrap), lang = "coroutine_yield")]
     type Yield;
 
     /// The type of value this coroutine returns.
@@ -84,6 +85,7 @@ pub trait Coroutine<R = ()> {
     /// `return` statement or implicitly as the last expression of a coroutine
     /// literal. For example futures would use this as `Result<T, E>` as it
     /// represents a completed future.
+    #[cfg_attr(not(bootstrap), lang = "coroutine_return")]
     type Return;
 
     /// Resumes the execution of this coroutine.
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index e253cfd2822..4d6ba2fa3b3 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -654,6 +654,32 @@ impl<T> Option<T> {
         !self.is_some()
     }
 
+    /// Returns `true` if the option is a [`None`] or the value inside of it matches a predicate.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(is_none_or)]
+    ///
+    /// let x: Option<u32> = Some(2);
+    /// assert_eq!(x.is_none_or(|x| x > 1), true);
+    ///
+    /// let x: Option<u32> = Some(0);
+    /// assert_eq!(x.is_none_or(|x| x > 1), false);
+    ///
+    /// let x: Option<u32> = None;
+    /// assert_eq!(x.is_none_or(|x| x > 1), true);
+    /// ```
+    #[must_use]
+    #[inline]
+    #[unstable(feature = "is_none_or", issue = "126383")]
+    pub fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool {
+        match self {
+            None => true,
+            Some(x) => f(x),
+        }
+    }
+
     /////////////////////////////////////////////////////////////////////////
     // Adapter for working with references
     /////////////////////////////////////////////////////////////////////////
@@ -1724,7 +1750,7 @@ impl<T> Option<T> {
     /// assert_eq!(prev, Some(43));
     /// ```
     #[inline]
-    #[stable(feature = "option_take_if", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "option_take_if", since = "1.80.0")]
     pub fn take_if<P>(&mut self, predicate: P) -> Option<T>
     where
         P: FnOnce(&mut T) -> bool,
diff --git a/library/core/src/prelude/common.rs b/library/core/src/prelude/common.rs
index 2a0331ef7b2..a6a1a055e29 100644
--- a/library/core/src/prelude/common.rs
+++ b/library/core/src/prelude/common.rs
@@ -14,7 +14,7 @@ pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
 #[stable(feature = "core_prelude", since = "1.4.0")]
 #[doc(no_inline)]
 pub use crate::mem::drop;
-#[stable(feature = "size_of_prelude", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "size_of_prelude", since = "1.80.0")]
 #[doc(no_inline)]
 pub use crate::mem::{align_of, align_of_val, size_of, size_of_val};
 
diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs
index 78fe0c5add5..eb86bf66206 100644
--- a/library/core/src/ptr/metadata.rs
+++ b/library/core/src/ptr/metadata.rs
@@ -3,7 +3,6 @@
 use crate::fmt;
 use crate::hash::{Hash, Hasher};
 use crate::intrinsics::aggregate_raw_ptr;
-#[cfg(not(bootstrap))]
 use crate::intrinsics::ptr_metadata;
 use crate::marker::Freeze;
 
@@ -96,17 +95,7 @@ pub trait Thin = Pointee<Metadata = ()>;
 #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
 #[inline]
 pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
-    #[cfg(bootstrap)]
-    {
-        // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
-        // and PtrComponents<T> have the same memory layouts. Only std can make this
-        // guarantee.
-        unsafe { PtrRepr { const_ptr: ptr }.components.metadata }
-    }
-    #[cfg(not(bootstrap))]
-    {
-        ptr_metadata(ptr)
-    }
+    ptr_metadata(ptr)
 }
 
 /// Forms a (possibly-wide) raw pointer from a data pointer and metadata.
@@ -140,33 +129,6 @@ pub const fn from_raw_parts_mut<T: ?Sized>(
     aggregate_raw_ptr(data_pointer, metadata)
 }
 
-#[repr(C)]
-#[cfg(bootstrap)]
-union PtrRepr<T: ?Sized> {
-    const_ptr: *const T,
-    mut_ptr: *mut T,
-    components: PtrComponents<T>,
-}
-
-#[repr(C)]
-#[cfg(bootstrap)]
-struct PtrComponents<T: ?Sized> {
-    data_pointer: *const (),
-    metadata: <T as Pointee>::Metadata,
-}
-
-// Manual impl needed to avoid `T: Copy` bound.
-#[cfg(bootstrap)]
-impl<T: ?Sized> Copy for PtrComponents<T> {}
-
-// Manual impl needed to avoid `T: Clone` bound.
-#[cfg(bootstrap)]
-impl<T: ?Sized> Clone for PtrComponents<T> {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
-
 /// The metadata for a `Dyn = dyn SomeTrait` trait object type.
 ///
 /// It is a pointer to a vtable (virtual call table)
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index aac5c745d63..0504a0fc32f 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -525,8 +525,8 @@ impl<T: ?Sized> NonNull<T> {
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
+    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
     pub const unsafe fn offset(self, count: isize) -> Self
     where
         T: Sized,
@@ -551,8 +551,8 @@ impl<T: ?Sized> NonNull<T> {
     #[must_use]
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
+    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
     pub const unsafe fn byte_offset(self, count: isize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `offset` and `byte_offset` has
         // the same safety contract.
@@ -611,8 +611,8 @@ impl<T: ?Sized> NonNull<T> {
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
+    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
     pub const unsafe fn add(self, count: usize) -> Self
     where
         T: Sized,
@@ -638,8 +638,8 @@ impl<T: ?Sized> NonNull<T> {
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     #[rustc_allow_const_fn_unstable(set_ptr_value)]
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
+    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
     pub const unsafe fn byte_add(self, count: usize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `add` and `byte_add` has the same
         // safety contract.
@@ -699,8 +699,8 @@ impl<T: ?Sized> NonNull<T> {
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
+    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
     #[rustc_allow_const_fn_unstable(unchecked_neg)]
     pub const unsafe fn sub(self, count: usize) -> Self
     where
@@ -732,8 +732,8 @@ impl<T: ?Sized> NonNull<T> {
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     #[rustc_allow_const_fn_unstable(set_ptr_value)]
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
+    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
     pub const unsafe fn byte_sub(self, count: usize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `sub` and `byte_sub` has the same
         // safety contract.
@@ -847,8 +847,8 @@ impl<T: ?Sized> NonNull<T> {
     /// ```
     #[inline]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
+    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
     pub const unsafe fn offset_from(self, origin: NonNull<T>) -> isize
     where
         T: Sized,
@@ -868,8 +868,8 @@ impl<T: ?Sized> NonNull<T> {
     /// ignoring the metadata.
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
+    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
     pub const unsafe fn byte_offset_from<U: ?Sized>(self, origin: NonNull<U>) -> isize {
         // SAFETY: the caller must uphold the safety contract for `byte_offset_from`.
         unsafe { self.pointer.byte_offset_from(origin.pointer) }
@@ -958,8 +958,8 @@ impl<T: ?Sized> NonNull<T> {
     /// [`ptr::read`]: crate::ptr::read()
     #[inline]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
+    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
     pub const unsafe fn read(self) -> T
     where
         T: Sized,
@@ -980,7 +980,7 @@ impl<T: ?Sized> NonNull<T> {
     /// [`ptr::read_volatile`]: crate::ptr::read_volatile()
     #[inline]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
     pub unsafe fn read_volatile(self) -> T
     where
         T: Sized,
@@ -999,8 +999,8 @@ impl<T: ?Sized> NonNull<T> {
     /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned()
     #[inline]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
+    #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
     pub const unsafe fn read_unaligned(self) -> T
     where
         T: Sized,
@@ -1019,7 +1019,7 @@ impl<T: ?Sized> NonNull<T> {
     /// [`ptr::copy`]: crate::ptr::copy()
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
     #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
     pub const unsafe fn copy_to(self, dest: NonNull<T>, count: usize)
     where
@@ -1039,7 +1039,7 @@ impl<T: ?Sized> NonNull<T> {
     /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
     #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
     pub const unsafe fn copy_to_nonoverlapping(self, dest: NonNull<T>, count: usize)
     where
@@ -1059,7 +1059,7 @@ impl<T: ?Sized> NonNull<T> {
     /// [`ptr::copy`]: crate::ptr::copy()
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
     #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
     pub const unsafe fn copy_from(self, src: NonNull<T>, count: usize)
     where
@@ -1079,7 +1079,7 @@ impl<T: ?Sized> NonNull<T> {
     /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
     #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
     pub const unsafe fn copy_from_nonoverlapping(self, src: NonNull<T>, count: usize)
     where
@@ -1095,7 +1095,7 @@ impl<T: ?Sized> NonNull<T> {
     ///
     /// [`ptr::drop_in_place`]: crate::ptr::drop_in_place()
     #[inline(always)]
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
     pub unsafe fn drop_in_place(self) {
         // SAFETY: the caller must uphold the safety contract for `drop_in_place`.
         unsafe { ptr::drop_in_place(self.as_ptr()) }
@@ -1109,7 +1109,7 @@ impl<T: ?Sized> NonNull<T> {
     /// [`ptr::write`]: crate::ptr::write()
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
     #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
     pub const unsafe fn write(self, val: T)
     where
@@ -1128,7 +1128,7 @@ impl<T: ?Sized> NonNull<T> {
     #[inline(always)]
     #[doc(alias = "memset")]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
     #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
     pub const unsafe fn write_bytes(self, val: u8, count: usize)
     where
@@ -1150,7 +1150,7 @@ impl<T: ?Sized> NonNull<T> {
     /// [`ptr::write_volatile`]: crate::ptr::write_volatile()
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
     pub unsafe fn write_volatile(self, val: T)
     where
         T: Sized,
@@ -1169,7 +1169,7 @@ impl<T: ?Sized> NonNull<T> {
     /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned()
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
     #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
     pub const unsafe fn write_unaligned(self, val: T)
     where
@@ -1186,7 +1186,7 @@ impl<T: ?Sized> NonNull<T> {
     ///
     /// [`ptr::replace`]: crate::ptr::replace()
     #[inline(always)]
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
     pub unsafe fn replace(self, src: T) -> T
     where
         T: Sized,
@@ -1203,7 +1203,7 @@ impl<T: ?Sized> NonNull<T> {
     ///
     /// [`ptr::swap`]: crate::ptr::swap()
     #[inline(always)]
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
     #[rustc_const_unstable(feature = "const_swap", issue = "83163")]
     pub const unsafe fn swap(self, with: NonNull<T>)
     where
@@ -1255,7 +1255,7 @@ impl<T: ?Sized> NonNull<T> {
     /// ```
     #[inline]
     #[must_use]
-    #[stable(feature = "non_null_convenience", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "non_null_convenience", since = "1.80.0")]
     #[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
     pub const fn align_offset(self, align: usize) -> usize
     where
diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs
index 8ad045275ad..bf444d2f68a 100644
--- a/library/core/src/slice/ascii.rs
+++ b/library/core/src/slice/ascii.rs
@@ -123,8 +123,8 @@ impl [u8] {
     /// assert_eq!(b"  ".trim_ascii_start(), b"");
     /// assert_eq!(b"".trim_ascii_start(), b"");
     /// ```
-    #[stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
+    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
     #[inline]
     pub const fn trim_ascii_start(&self) -> &[u8] {
         let mut bytes = self;
@@ -152,8 +152,8 @@ impl [u8] {
     /// assert_eq!(b"  ".trim_ascii_end(), b"");
     /// assert_eq!(b"".trim_ascii_end(), b"");
     /// ```
-    #[stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
+    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
     #[inline]
     pub const fn trim_ascii_end(&self) -> &[u8] {
         let mut bytes = self;
@@ -182,8 +182,8 @@ impl [u8] {
     /// assert_eq!(b"  ".trim_ascii(), b"");
     /// assert_eq!(b"".trim_ascii(), b"");
     /// ```
-    #[stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
+    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
     #[inline]
     pub const fn trim_ascii(&self) -> &[u8] {
         self.trim_ascii_start().trim_ascii_end()
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 96fc87ab2e9..ca1920f9812 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -16,7 +16,7 @@ use crate::ptr::{self, without_provenance, without_provenance_mut, NonNull};
 
 use super::{from_raw_parts, from_raw_parts_mut};
 
-#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
 impl<T> !Iterator for [T] {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 503107c7480..17b4f9ece9d 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -2082,8 +2082,8 @@ impl<T> [T] {
     ///
     /// assert_eq!(None, v.split_at_checked(7));
     /// ```
-    #[stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "split_at_checked", since = "1.80.0")]
+    #[rustc_const_stable(feature = "split_at_checked", since = "1.80.0")]
     #[inline]
     #[must_use]
     pub const fn split_at_checked(&self, mid: usize) -> Option<(&[T], &[T])> {
@@ -2121,7 +2121,7 @@ impl<T> [T] {
     ///
     /// assert_eq!(None, v.split_at_mut_checked(7));
     /// ```
-    #[stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "split_at_checked", since = "1.80.0")]
     #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")]
     #[inline]
     #[must_use]
@@ -4544,7 +4544,7 @@ impl<T, const N: usize> [[T; N]] {
     /// let empty_slice_of_arrays: &[[u32; 10]] = &[];
     /// assert!(empty_slice_of_arrays.as_flattened().is_empty());
     /// ```
-    #[stable(feature = "slice_flatten", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "slice_flatten", since = "1.80.0")]
     #[rustc_const_unstable(feature = "const_slice_flatten", issue = "95629")]
     pub const fn as_flattened(&self) -> &[T] {
         let len = if T::IS_ZST {
@@ -4581,7 +4581,7 @@ impl<T, const N: usize> [[T; N]] {
     /// add_5_to_all(array.as_flattened_mut());
     /// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]);
     /// ```
-    #[stable(feature = "slice_flatten", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "slice_flatten", since = "1.80.0")]
     pub fn as_flattened_mut(&mut self) -> &mut [T] {
         let len = if T::IS_ZST {
             self.len().checked_mul(N).expect("slice len overflow")
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 669cdc92e35..68310938043 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -732,7 +732,7 @@ impl str {
     /// ```
     #[inline]
     #[must_use]
-    #[stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "split_at_checked", since = "1.80.0")]
     pub fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)> {
         // is_char_boundary checks that the index is in [0, .len()]
         if self.is_char_boundary(mid) {
@@ -772,7 +772,7 @@ impl str {
     /// ```
     #[inline]
     #[must_use]
-    #[stable(feature = "split_at_checked", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "split_at_checked", since = "1.80.0")]
     pub fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut str, &mut str)> {
         // is_char_boundary checks that the index is in [0, .len()]
         if self.is_char_boundary(mid) {
@@ -2537,8 +2537,8 @@ impl str {
     /// ```
     #[must_use = "this returns the trimmed string as a new slice, \
                   without modifying the original"]
-    #[stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
+    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
     #[inline]
     pub const fn trim_ascii_start(&self) -> &str {
         // SAFETY: Removing ASCII characters from a `&str` does not invalidate
@@ -2562,8 +2562,8 @@ impl str {
     /// ```
     #[must_use = "this returns the trimmed string as a new slice, \
                   without modifying the original"]
-    #[stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
+    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
     #[inline]
     pub const fn trim_ascii_end(&self) -> &str {
         // SAFETY: Removing ASCII characters from a `&str` does not invalidate
@@ -2588,8 +2588,8 @@ impl str {
     /// ```
     #[must_use = "this returns the trimmed string as a new slice, \
                   without modifying the original"]
-    #[stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
+    #[rustc_const_stable(feature = "byte_slice_trim_ascii", since = "1.80.0")]
     #[inline]
     pub const fn trim_ascii(&self) -> &str {
         // SAFETY: Removing ASCII characters from a `&str` does not invalidate
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index dfa58e4f46d..bc0fa3f0968 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -1090,7 +1090,7 @@ impl Duration {
     /// let dur2 = Duration::new(5, 400_000_000);
     /// assert_eq!(dur1.div_duration_f64(dur2), 0.5);
     /// ```
-    #[stable(feature = "div_duration", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "div_duration", since = "1.80.0")]
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[inline]
@@ -1111,7 +1111,7 @@ impl Duration {
     /// let dur2 = Duration::new(5, 400_000_000);
     /// assert_eq!(dur1.div_duration_f32(dur2), 0.5);
     /// ```
-    #[stable(feature = "div_duration", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "div_duration", since = "1.80.0")]
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[inline]
diff --git a/library/proc_macro/src/escape.rs b/library/proc_macro/src/escape.rs
new file mode 100644
index 00000000000..87a4d1d50fd
--- /dev/null
+++ b/library/proc_macro/src/escape.rs
@@ -0,0 +1,57 @@
+#[derive(Copy, Clone)]
+pub(crate) struct EscapeOptions {
+    /// Produce \'.
+    pub escape_single_quote: bool,
+    /// Produce \".
+    pub escape_double_quote: bool,
+    /// Produce \x escapes for non-ASCII, and use \x rather than \u for ASCII
+    /// control characters.
+    pub escape_nonascii: bool,
+}
+
+pub(crate) fn escape_bytes(bytes: &[u8], opt: EscapeOptions) -> String {
+    let mut repr = String::new();
+
+    if opt.escape_nonascii {
+        for &byte in bytes {
+            escape_single_byte(byte, opt, &mut repr);
+        }
+    } else {
+        let mut chunks = bytes.utf8_chunks();
+        while let Some(chunk) = chunks.next() {
+            for ch in chunk.valid().chars() {
+                escape_single_char(ch, opt, &mut repr);
+            }
+            for &byte in chunk.invalid() {
+                escape_single_byte(byte, opt, &mut repr);
+            }
+        }
+    }
+
+    repr
+}
+
+fn escape_single_byte(byte: u8, opt: EscapeOptions, repr: &mut String) {
+    if byte == b'\0' {
+        repr.push_str("\\0");
+    } else if (byte == b'\'' && !opt.escape_single_quote)
+        || (byte == b'"' && !opt.escape_double_quote)
+    {
+        repr.push(byte as char);
+    } else {
+        // Escapes \t, \r, \n, \\, \', \", and uses \x## for non-ASCII and
+        // for ASCII control characters.
+        repr.extend(byte.escape_ascii().map(char::from));
+    }
+}
+
+fn escape_single_char(ch: char, opt: EscapeOptions, repr: &mut String) {
+    if (ch == '\'' && !opt.escape_single_quote) || (ch == '"' && !opt.escape_double_quote) {
+        repr.push(ch);
+    } else {
+        // Escapes \0, \t, \r, \n, \\, \', \", and uses \u{...} for
+        // non-printable characters and for Grapheme_Extend characters, which
+        // includes things like U+0300 "Combining Grave Accent".
+        repr.extend(ch.escape_debug());
+    }
+}
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 3d7d36b27e5..581d7e3efe3 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -43,10 +43,12 @@
 pub mod bridge;
 
 mod diagnostic;
+mod escape;
 
 #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
 pub use diagnostic::{Diagnostic, Level, MultiSpan};
 
+use crate::escape::{escape_bytes, EscapeOptions};
 use std::ffi::CStr;
 use std::ops::{Range, RangeBounds};
 use std::path::PathBuf;
@@ -1356,40 +1358,61 @@ impl Literal {
     /// String literal.
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
     pub fn string(string: &str) -> Literal {
-        let quoted = format!("{:?}", string);
-        assert!(quoted.starts_with('"') && quoted.ends_with('"'));
-        let symbol = &quoted[1..quoted.len() - 1];
-        Literal::new(bridge::LitKind::Str, symbol, None)
+        let escape = EscapeOptions {
+            escape_single_quote: false,
+            escape_double_quote: true,
+            escape_nonascii: false,
+        };
+        let repr = escape_bytes(string.as_bytes(), escape);
+        Literal::new(bridge::LitKind::Str, &repr, None)
     }
 
     /// Character literal.
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
     pub fn character(ch: char) -> Literal {
-        let quoted = format!("{:?}", ch);
-        assert!(quoted.starts_with('\'') && quoted.ends_with('\''));
-        let symbol = &quoted[1..quoted.len() - 1];
-        Literal::new(bridge::LitKind::Char, symbol, None)
+        let escape = EscapeOptions {
+            escape_single_quote: true,
+            escape_double_quote: false,
+            escape_nonascii: false,
+        };
+        let repr = escape_bytes(ch.encode_utf8(&mut [0u8; 4]).as_bytes(), escape);
+        Literal::new(bridge::LitKind::Char, &repr, None)
     }
 
     /// Byte character literal.
     #[stable(feature = "proc_macro_byte_character", since = "1.79.0")]
     pub fn byte_character(byte: u8) -> Literal {
-        let string = [byte].escape_ascii().to_string();
-        Literal::new(bridge::LitKind::Byte, &string, None)
+        let escape = EscapeOptions {
+            escape_single_quote: true,
+            escape_double_quote: false,
+            escape_nonascii: true,
+        };
+        let repr = escape_bytes(&[byte], escape);
+        Literal::new(bridge::LitKind::Byte, &repr, None)
     }
 
     /// Byte string literal.
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
     pub fn byte_string(bytes: &[u8]) -> Literal {
-        let string = bytes.escape_ascii().to_string();
-        Literal::new(bridge::LitKind::ByteStr, &string, None)
+        let escape = EscapeOptions {
+            escape_single_quote: false,
+            escape_double_quote: true,
+            escape_nonascii: true,
+        };
+        let repr = escape_bytes(bytes, escape);
+        Literal::new(bridge::LitKind::ByteStr, &repr, None)
     }
 
     /// C string literal.
     #[stable(feature = "proc_macro_c_str_literals", since = "1.79.0")]
     pub fn c_string(string: &CStr) -> Literal {
-        let string = string.to_bytes().escape_ascii().to_string();
-        Literal::new(bridge::LitKind::CStr, &string, None)
+        let escape = EscapeOptions {
+            escape_single_quote: false,
+            escape_double_quote: true,
+            escape_nonascii: false,
+        };
+        let repr = escape_bytes(string.to_bytes(), escape);
+        Literal::new(bridge::LitKind::CStr, &repr, None)
     }
 
     /// Returns the span encompassing this literal.
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 68bba5c2be1..32479cd2836 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -50,7 +50,7 @@ dlmalloc = { version = "0.2.4", features = ['rustc-dep-of-std'] }
 fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'], public = true }
 
 [target.'cfg(target_os = "hermit")'.dependencies]
-hermit-abi = { version = "0.3.9", features = ['rustc-dep-of-std'], public = true }
+hermit-abi = { version = "0.4.0", features = ['rustc-dep-of-std'], public = true }
 
 [target.'cfg(target_os = "wasi")'.dependencies]
 wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index b98fbbf762f..dc4924cdf58 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -73,7 +73,9 @@ pub use alloc_crate::alloc::*;
 /// work, such as to serve alignment requests greater than the alignment
 /// provided directly by the backing system allocator.
 ///
-/// This type implements the `GlobalAlloc` trait and Rust programs by default
+/// This type implements the [`GlobalAlloc`] trait. Currently the default
+/// global allocator is unspecified. Libraries, however, like `cdylib`s and
+/// `staticlib`s are guaranteed to use the [`System`] by default and as such
 /// work as if they had this definition:
 ///
 /// ```rust
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 295e782639b..2f35e721610 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -363,20 +363,12 @@ impl Error for VarError {
 /// }
 /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
 /// ```
-#[cfg(not(bootstrap))]
 #[rustc_deprecated_safe_2024]
 #[stable(feature = "env", since = "1.0.0")]
 pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
     _set_var(key.as_ref(), value.as_ref())
 }
 
-#[cfg(bootstrap)]
-#[allow(missing_docs)]
-#[stable(feature = "env", since = "1.0.0")]
-pub fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
-    unsafe { _set_var(key.as_ref(), value.as_ref()) }
-}
-
 unsafe fn _set_var(key: &OsStr, value: &OsStr) {
     os_imp::setenv(key, value).unwrap_or_else(|e| {
         panic!("failed to set environment variable `{key:?}` to `{value:?}`: {e}")
@@ -438,20 +430,12 @@ unsafe fn _set_var(key: &OsStr, value: &OsStr) {
 /// }
 /// assert!(env::var(key).is_err());
 /// ```
-#[cfg(not(bootstrap))]
 #[rustc_deprecated_safe_2024]
 #[stable(feature = "env", since = "1.0.0")]
 pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) {
     _remove_var(key.as_ref())
 }
 
-#[cfg(bootstrap)]
-#[allow(missing_docs)]
-#[stable(feature = "env", since = "1.0.0")]
-pub fn remove_var<K: AsRef<OsStr>>(key: K) {
-    unsafe { _remove_var(key.as_ref()) }
-}
-
 unsafe fn _remove_var(key: &OsStr) {
     os_imp::unsetenv(key)
         .unwrap_or_else(|e| panic!("failed to remove environment variable `{key:?}`: {e}"))
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 0dcf554770c..2132097fde4 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -2302,7 +2302,7 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
 ///
 /// This function currently corresponds to the `realpath` function on Unix
 /// and the `CreateFile` and `GetFinalPathNameByHandle` functions on Windows.
-/// Note that, this [may change in the future][changes].
+/// Note that this [may change in the future][changes].
 ///
 /// On Windows, this converts the path to use [extended length path][path]
 /// syntax, which allows your program to use longer path names, but means you
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index f55ec1588f9..97b72f9664b 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -2058,7 +2058,7 @@ pub trait Seek {
     /// ```
     ///
     /// [`BufReader`]: crate::io::BufReader
-    #[stable(feature = "seek_seek_relative", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "seek_seek_relative", since = "1.80.0")]
     fn seek_relative(&mut self, offset: i64) -> Result<()> {
         self.seek(SeekFrom::Current(offset))?;
         Ok(())
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index adbcdcd2e67..7b8caaa2684 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -3345,14 +3345,33 @@ impl Error for StripPrefixError {
 /// Makes the path absolute without accessing the filesystem.
 ///
 /// If the path is relative, the current directory is used as the base directory.
-/// All intermediate components will be resolved according to platforms-specific
-/// rules but unlike [`canonicalize`][crate::fs::canonicalize] this does not
+/// All intermediate components will be resolved according to platform-specific
+/// rules, but unlike [`canonicalize`][crate::fs::canonicalize], this does not
 /// resolve symlinks and may succeed even if the path does not exist.
 ///
 /// If the `path` is empty or getting the
-/// [current directory][crate::env::current_dir] fails then an error will be
+/// [current directory][crate::env::current_dir] fails, then an error will be
 /// returned.
 ///
+/// # Platform-specific behavior
+///
+/// On POSIX platforms, the path is resolved using [POSIX semantics][posix-semantics],
+/// except that it stops short of resolving symlinks. This means it will keep `..`
+/// components and trailing slashes.
+///
+/// On Windows, for verbatim paths, this will simply return the path as given. For other
+/// paths, this is currently equivalent to calling
+/// [`GetFullPathNameW`][windows-path].
+///
+/// Note that these [may change in the future][changes].
+///
+/// # Errors
+///
+/// This function may return an error in the following situations:
+///
+/// * If `path` is syntactically invalid; in particular, if it is empty.
+/// * If getting the [current directory][crate::env::current_dir] fails.
+///
 /// # Examples
 ///
 /// ## POSIX paths
@@ -3360,50 +3379,42 @@ impl Error for StripPrefixError {
 /// ```
 /// # #[cfg(unix)]
 /// fn main() -> std::io::Result<()> {
-///   use std::path::{self, Path};
+///     use std::path::{self, Path};
 ///
-///   // Relative to absolute
-///   let absolute = path::absolute("foo/./bar")?;
-///   assert!(absolute.ends_with("foo/bar"));
+///     // Relative to absolute
+///     let absolute = path::absolute("foo/./bar")?;
+///     assert!(absolute.ends_with("foo/bar"));
 ///
-///   // Absolute to absolute
-///   let absolute = path::absolute("/foo//test/.././bar.rs")?;
-///   assert_eq!(absolute, Path::new("/foo/test/../bar.rs"));
-///   Ok(())
+///     // Absolute to absolute
+///     let absolute = path::absolute("/foo//test/.././bar.rs")?;
+///     assert_eq!(absolute, Path::new("/foo/test/../bar.rs"));
+///     Ok(())
 /// }
 /// # #[cfg(not(unix))]
 /// # fn main() {}
 /// ```
 ///
-/// The path is resolved using [POSIX semantics][posix-semantics] except that
-/// it stops short of resolving symlinks. This means it will keep `..`
-/// components and trailing slashes.
-///
 /// ## Windows paths
 ///
 /// ```
 /// # #[cfg(windows)]
 /// fn main() -> std::io::Result<()> {
-///   use std::path::{self, Path};
+///     use std::path::{self, Path};
 ///
-///   // Relative to absolute
-///   let absolute = path::absolute("foo/./bar")?;
-///   assert!(absolute.ends_with(r"foo\bar"));
+///     // Relative to absolute
+///     let absolute = path::absolute("foo/./bar")?;
+///     assert!(absolute.ends_with(r"foo\bar"));
 ///
-///   // Absolute to absolute
-///   let absolute = path::absolute(r"C:\foo//test\..\./bar.rs")?;
+///     // Absolute to absolute
+///     let absolute = path::absolute(r"C:\foo//test\..\./bar.rs")?;
 ///
-///   assert_eq!(absolute, Path::new(r"C:\foo\bar.rs"));
-///   Ok(())
+///     assert_eq!(absolute, Path::new(r"C:\foo\bar.rs"));
+///     Ok(())
 /// }
 /// # #[cfg(not(windows))]
 /// # fn main() {}
 /// ```
 ///
-/// For verbatim paths this will simply return the path as given. For other
-/// paths this is currently equivalent to calling
-/// [`GetFullPathNameW`][windows-path].
-///
 /// Note that this [may change in the future][changes].
 ///
 /// [changes]: io#platform-specific-behavior
diff --git a/library/std/src/prelude/common.rs b/library/std/src/prelude/common.rs
index ceee3e33c3e..055ab7eb6d9 100644
--- a/library/std/src/prelude/common.rs
+++ b/library/std/src/prelude/common.rs
@@ -14,7 +14,7 @@ pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::mem::drop;
-#[stable(feature = "size_of_prelude", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "size_of_prelude", since = "1.80.0")]
 #[doc(no_inline)]
 pub use crate::mem::{align_of, align_of_val, size_of, size_of_val};
 
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index c926c89f7a9..f351dab78dc 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -629,6 +629,25 @@ impl Command {
     ///     .spawn()
     ///     .expect("sh command failed to start");
     /// ```
+    ///
+    /// # Caveats
+    ///
+    /// [`Command::new`] is only intended to accept the path of the program. If you pass a program
+    /// path along with arguments like `Command::new("ls -l").spawn()`, it will try to search for
+    /// `ls -l` literally. The arguments need to be passed separately, such as via [`arg`] or
+    /// [`args`].
+    ///
+    /// ```no_run
+    /// use std::process::Command;
+    ///
+    /// Command::new("ls")
+    ///     .arg("-l") // arg passed separately
+    ///     .spawn()
+    ///     .expect("ls command failed to start");
+    /// ```
+    ///
+    /// [`arg`]: Self::arg
+    /// [`args`]: Self::args
     #[stable(feature = "process", since = "1.0.0")]
     pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
         Command { inner: imp::Command::new(program.as_ref()) }
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 7a2eed93dd4..b70c041fa42 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -64,7 +64,7 @@ union Data<T, F> {
 ///     println!("{}", *data.number);
 /// }
 /// ```
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 pub struct LazyLock<T, F = fn() -> T> {
     once: Once,
     data: UnsafeCell<Data<T, F>>,
@@ -85,8 +85,8 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
     /// assert_eq!(&*lazy, "HELLO, WORLD!");
     /// ```
     #[inline]
-    #[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "lazy_cell", since = "1.80.0")]
+    #[rustc_const_stable(feature = "lazy_cell", since = "1.80.0")]
     pub const fn new(f: F) -> LazyLock<T, F> {
         LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) }
     }
@@ -152,7 +152,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
     /// assert_eq!(&*lazy, &92);
     /// ```
     #[inline]
-    #[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "lazy_cell", since = "1.80.0")]
     pub fn force(this: &LazyLock<T, F>) -> &T {
         this.once.call_once(|| {
             // SAFETY: `call_once` only runs this closure once, ever.
@@ -188,7 +188,7 @@ impl<T, F> LazyLock<T, F> {
     }
 }
 
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 impl<T, F> Drop for LazyLock<T, F> {
     fn drop(&mut self) {
         match self.once.state() {
@@ -201,7 +201,7 @@ impl<T, F> Drop for LazyLock<T, F> {
     }
 }
 
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
     type Target = T;
 
@@ -216,7 +216,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
     }
 }
 
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 impl<T: Default> Default for LazyLock<T> {
     /// Creates a new lazy value using `Default` as the initializing function.
     #[inline]
@@ -225,7 +225,7 @@ impl<T: Default> Default for LazyLock<T> {
     }
 }
 
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut d = f.debug_tuple("LazyLock");
@@ -239,13 +239,13 @@ impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
 
 // We never create a `&F` from a `&LazyLock<T, F>` so it is fine
 // to not impl `Sync` for `F`.
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {}
 // auto-derived `Send` impl is OK.
 
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {}
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {}
 
 #[cfg(test)]
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index 70e8f5f90c6..9a38c42f43a 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -133,7 +133,8 @@
 //! - [`Mutex`]: Mutual Exclusion mechanism, which ensures that at
 //!   most one thread at a time is able to access some data.
 //!
-//! - [`Once`]: Used for a thread-safe, one-time global initialization routine
+//! - [`Once`]: Used for a thread-safe, one-time global initialization routine.
+//!   Mostly useful for implementing other types like `OnceLock`.
 //!
 //! - [`OnceLock`]: Used for thread-safe, one-time initialization of a
 //!   variable, with potentially different initializers based on the caller.
@@ -182,7 +183,7 @@ pub use self::rwlock::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
 
-#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "lazy_cell", since = "1.80.0")]
 pub use self::lazy_lock::LazyLock;
 #[stable(feature = "once_cell", since = "1.70.0")]
 pub use self::once_lock::OnceLock;
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index 608229fd674..9d969af8c6d 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -10,9 +10,15 @@ use crate::fmt;
 use crate::panic::{RefUnwindSafe, UnwindSafe};
 use crate::sys::sync as sys;
 
-/// A synchronization primitive which can be used to run a one-time global
-/// initialization. Useful for one-time initialization for FFI or related
-/// functionality. This type can only be constructed with [`Once::new()`].
+/// A low-level synchronization primitive for one-time global execution.
+///
+/// Previously this was the only "execute once" synchronization in `std`.
+/// Other libraries implemented novel synchronizing types with `Once`, like
+/// [`OnceLock<T>`] or [`LazyLock<T, F>`], before those were added to `std`.
+/// `OnceLock<T>` in particular supersedes `Once` in functionality and should
+/// be preferred for the common case where the `Once` is associated with data.
+///
+/// This type can only be constructed with [`Once::new()`].
 ///
 /// # Examples
 ///
@@ -25,6 +31,9 @@ use crate::sys::sync as sys;
 ///     // run initialization here
 /// });
 /// ```
+///
+/// [`OnceLock<T>`]: crate::sync::OnceLock
+/// [`LazyLock<T, F>`]: crate::sync::LazyLock
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Once {
     inner: sys::Once,
diff --git a/library/std/src/sys/pal/hermit/fd.rs b/library/std/src/sys/pal/hermit/fd.rs
index d7dab08cfbd..3c52b85de23 100644
--- a/library/std/src/sys/pal/hermit/fd.rs
+++ b/library/std/src/sys/pal/hermit/fd.rs
@@ -1,7 +1,8 @@
 #![unstable(reason = "not public", issue = "none", feature = "fd")]
 
 use super::hermit_abi;
-use crate::io::{self, Read};
+use crate::cmp;
+use crate::io::{self, IoSlice, IoSliceMut, Read};
 use crate::os::hermit::io::{FromRawFd, OwnedFd, RawFd};
 use crate::sys::cvt;
 use crate::sys::unsupported;
@@ -9,6 +10,10 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 
 use crate::os::hermit::io::*;
 
+const fn max_iov() -> usize {
+    hermit_abi::IOV_MAX
+}
+
 #[derive(Debug)]
 pub struct FileDesc {
     fd: OwnedFd,
@@ -21,6 +26,22 @@ impl FileDesc {
         Ok(result as usize)
     }
 
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        let ret = cvt(unsafe {
+            hermit_abi::readv(
+                self.as_raw_fd(),
+                bufs.as_mut_ptr() as *mut hermit_abi::iovec as *const hermit_abi::iovec,
+                cmp::min(bufs.len(), max_iov()),
+            )
+        })?;
+        Ok(ret as usize)
+    }
+
+    #[inline]
+    pub fn is_read_vectored(&self) -> bool {
+        true
+    }
+
     pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
         let mut me = self;
         (&mut me).read_to_end(buf)
@@ -32,6 +53,22 @@ impl FileDesc {
         Ok(result as usize)
     }
 
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        let ret = cvt(unsafe {
+            hermit_abi::writev(
+                self.as_raw_fd(),
+                bufs.as_ptr() as *const hermit_abi::iovec,
+                cmp::min(bufs.len(), max_iov()),
+            )
+        })?;
+        Ok(ret as usize)
+    }
+
+    #[inline]
+    pub fn is_write_vectored(&self) -> bool {
+        true
+    }
+
     pub fn duplicate(&self) -> io::Result<FileDesc> {
         self.duplicate_path(&[])
     }
diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs
index a4a16e6e86b..a98a1006ef4 100644
--- a/library/std/src/sys/pal/hermit/fs.rs
+++ b/library/std/src/sys/pal/hermit/fs.rs
@@ -1,7 +1,7 @@
 use super::fd::FileDesc;
 use super::hermit_abi::{
     self, dirent64, stat as stat_struct, DT_DIR, DT_LNK, DT_REG, DT_UNKNOWN, O_APPEND, O_CREAT,
-    O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG,
+    O_DIRECTORY, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG,
 };
 use crate::ffi::{CStr, OsStr, OsString};
 use crate::fmt;
@@ -62,7 +62,7 @@ pub struct DirEntry {
     /// 64-bit inode number
     ino: u64,
     /// File type
-    type_: u32,
+    type_: u8,
     /// name of the entry
     name: OsString,
 }
@@ -90,7 +90,7 @@ pub struct FilePermissions {
 
 #[derive(Copy, Clone, Eq, Debug)]
 pub struct FileType {
-    mode: u32,
+    mode: u8,
 }
 
 impl PartialEq for FileType {
@@ -112,31 +112,23 @@ pub struct DirBuilder {
 
 impl FileAttr {
     pub fn modified(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::new(
-            self.stat_val.st_mtime.try_into().unwrap(),
-            self.stat_val.st_mtime_nsec.try_into().unwrap(),
-        ))
+        Ok(SystemTime::new(self.stat_val.st_mtim.tv_sec, self.stat_val.st_mtim.tv_nsec))
     }
 
     pub fn accessed(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::new(
-            self.stat_val.st_atime.try_into().unwrap(),
-            self.stat_val.st_atime_nsec.try_into().unwrap(),
-        ))
+        Ok(SystemTime::new(self.stat_val.st_atim.tv_sec, self.stat_val.st_atim.tv_nsec))
     }
 
     pub fn created(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::new(
-            self.stat_val.st_ctime.try_into().unwrap(),
-            self.stat_val.st_ctime_nsec.try_into().unwrap(),
-        ))
+        Ok(SystemTime::new(self.stat_val.st_ctim.tv_sec, self.stat_val.st_ctim.tv_nsec))
     }
 
     pub fn size(&self) -> u64 {
         self.stat_val.st_size as u64
     }
+
     pub fn perm(&self) -> FilePermissions {
-        FilePermissions { mode: (self.stat_val.st_mode) }
+        FilePermissions { mode: self.stat_val.st_mode }
     }
 
     pub fn file_type(&self) -> FileType {
@@ -220,7 +212,7 @@ impl Iterator for ReadDir {
                 let entry = DirEntry {
                     root: self.inner.root.clone(),
                     ino: dir.d_ino,
-                    type_: dir.d_type as u32,
+                    type_: dir.d_type,
                     name: OsString::from_vec(name_bytes.to_vec()),
                 };
 
@@ -251,7 +243,7 @@ impl DirEntry {
     }
 
     pub fn file_type(&self) -> io::Result<FileType> {
-        Ok(FileType { mode: self.type_ as u32 })
+        Ok(FileType { mode: self.type_ })
     }
 
     #[allow(dead_code)]
@@ -385,12 +377,12 @@ impl File {
     }
 
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        crate::io::default_read_vectored(|buf| self.read(buf), bufs)
+        self.0.read_vectored(bufs)
     }
 
     #[inline]
     pub fn is_read_vectored(&self) -> bool {
-        false
+        self.0.is_read_vectored()
     }
 
     pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
@@ -402,12 +394,12 @@ impl File {
     }
 
     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        crate::io::default_write_vectored(|buf| self.write(buf), bufs)
+        self.0.write_vectored(bufs)
     }
 
     #[inline]
     pub fn is_write_vectored(&self) -> bool {
-        false
+        self.0.is_write_vectored()
     }
 
     #[inline]
@@ -439,13 +431,13 @@ impl DirBuilder {
 
     pub fn mkdir(&self, path: &Path) -> io::Result<()> {
         run_path_with_cstr(path, &|path| {
-            cvt(unsafe { hermit_abi::mkdir(path.as_ptr(), self.mode) }).map(|_| ())
+            cvt(unsafe { hermit_abi::mkdir(path.as_ptr(), self.mode.into()) }).map(|_| ())
         })
     }
 
     #[allow(dead_code)]
     pub fn set_mode(&mut self, mode: u32) {
-        self.mode = mode as u32;
+        self.mode = mode;
     }
 }
 
@@ -501,8 +493,9 @@ impl FromRawFd for File {
 }
 
 pub fn readdir(path: &Path) -> io::Result<ReadDir> {
-    let fd_raw =
-        run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::opendir(path.as_ptr()) }))?;
+    let fd_raw = run_path_with_cstr(path, &|path| {
+        cvt(unsafe { hermit_abi::open(path.as_ptr(), O_RDONLY | O_DIRECTORY, 0) })
+    })?;
     let fd = unsafe { FileDesc::from_raw_fd(fd_raw as i32) };
     let root = path.to_path_buf();
 
diff --git a/library/std/src/sys/pal/hermit/futex.rs b/library/std/src/sys/pal/hermit/futex.rs
index 571b2885658..b2d74d1311b 100644
--- a/library/std/src/sys/pal/hermit/futex.rs
+++ b/library/std/src/sys/pal/hermit/futex.rs
@@ -10,7 +10,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
     let timespec = timeout.and_then(|dur| {
         Some(hermit_abi::timespec {
             tv_sec: dur.as_secs().try_into().ok()?,
-            tv_nsec: dur.subsec_nanos().into(),
+            tv_nsec: dur.subsec_nanos().try_into().ok()?,
         })
     });
 
diff --git a/library/std/src/sys/pal/hermit/io.rs b/library/std/src/sys/pal/hermit/io.rs
new file mode 100644
index 00000000000..9de7b53e53c
--- /dev/null
+++ b/library/std/src/sys/pal/hermit/io.rs
@@ -0,0 +1,82 @@
+use crate::marker::PhantomData;
+use crate::os::hermit::io::{AsFd, AsRawFd};
+use crate::slice;
+
+use hermit_abi::{c_void, iovec};
+
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+pub struct IoSlice<'a> {
+    vec: iovec,
+    _p: PhantomData<&'a [u8]>,
+}
+
+impl<'a> IoSlice<'a> {
+    #[inline]
+    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        IoSlice {
+            vec: iovec { iov_base: buf.as_ptr() as *mut u8 as *mut c_void, iov_len: buf.len() },
+            _p: PhantomData,
+        }
+    }
+
+    #[inline]
+    pub fn advance(&mut self, n: usize) {
+        if self.vec.iov_len < n {
+            panic!("advancing IoSlice beyond its length");
+        }
+
+        unsafe {
+            self.vec.iov_len -= n;
+            self.vec.iov_base = self.vec.iov_base.add(n);
+        }
+    }
+
+    #[inline]
+    pub fn as_slice(&self) -> &[u8] {
+        unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
+    }
+}
+
+#[repr(transparent)]
+pub struct IoSliceMut<'a> {
+    vec: iovec,
+    _p: PhantomData<&'a mut [u8]>,
+}
+
+impl<'a> IoSliceMut<'a> {
+    #[inline]
+    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        IoSliceMut {
+            vec: iovec { iov_base: buf.as_mut_ptr() as *mut c_void, iov_len: buf.len() },
+            _p: PhantomData,
+        }
+    }
+
+    #[inline]
+    pub fn advance(&mut self, n: usize) {
+        if self.vec.iov_len < n {
+            panic!("advancing IoSliceMut beyond its length");
+        }
+
+        unsafe {
+            self.vec.iov_len -= n;
+            self.vec.iov_base = self.vec.iov_base.add(n);
+        }
+    }
+
+    #[inline]
+    pub fn as_slice(&self) -> &[u8] {
+        unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
+    }
+
+    #[inline]
+    pub fn as_mut_slice(&mut self) -> &mut [u8] {
+        unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
+    }
+}
+
+pub fn is_terminal(fd: &impl AsFd) -> bool {
+    let fd = fd.as_fd();
+    hermit_abi::isatty(fd.as_raw_fd())
+}
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index a64323a3a29..eca7351d54c 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -23,7 +23,6 @@ pub mod env;
 pub mod fd;
 pub mod fs;
 pub mod futex;
-#[path = "../unsupported/io.rs"]
 pub mod io;
 pub mod net;
 pub mod os;
diff --git a/library/std/src/sys/pal/hermit/net.rs b/library/std/src/sys/pal/hermit/net.rs
index 00dbca86a4b..6016d50eba0 100644
--- a/library/std/src/sys/pal/hermit/net.rs
+++ b/library/std/src/sys/pal/hermit/net.rs
@@ -175,12 +175,12 @@ impl Socket {
     }
 
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        crate::io::default_read_vectored(|b| self.read(b), bufs)
+        self.0.read_vectored(bufs)
     }
 
     #[inline]
     pub fn is_read_vectored(&self) -> bool {
-        false
+        self.0.is_read_vectored()
     }
 
     fn recv_from_with_flags(&self, buf: &mut [u8], flags: i32) -> io::Result<(usize, SocketAddr)> {
@@ -209,16 +209,15 @@ impl Socket {
     }
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
-        let sz = cvt(unsafe { netc::write(self.0.as_raw_fd(), buf.as_ptr(), buf.len()) })?;
-        Ok(sz.try_into().unwrap())
+        self.0.write(buf)
     }
 
     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        crate::io::default_write_vectored(|b| self.write(b), bufs)
+        self.0.write_vectored(bufs)
     }
 
     pub fn is_write_vectored(&self) -> bool {
-        false
+        self.0.is_write_vectored()
     }
 
     pub fn set_timeout(&self, dur: Option<Duration>, kind: i32) -> io::Result<()> {
@@ -265,7 +264,7 @@ impl Socket {
             Shutdown::Read => netc::SHUT_RD,
             Shutdown::Both => netc::SHUT_RDWR,
         };
-        cvt(unsafe { netc::shutdown_socket(self.as_raw_fd(), how) })?;
+        cvt(unsafe { netc::shutdown(self.as_raw_fd(), how) })?;
         Ok(())
     }
 
diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs
index 91247d30462..a7a73c756f2 100644
--- a/library/std/src/sys/pal/hermit/os.rs
+++ b/library/std/src/sys/pal/hermit/os.rs
@@ -198,5 +198,5 @@ pub fn exit(code: i32) -> ! {
 }
 
 pub fn getpid() -> u32 {
-    unsafe { hermit_abi::getpid() }
+    unsafe { hermit_abi::getpid() as u32 }
 }
diff --git a/library/std/src/sys/pal/hermit/stdio.rs b/library/std/src/sys/pal/hermit/stdio.rs
index 777c57b391c..3ea00f5cc5e 100644
--- a/library/std/src/sys/pal/hermit/stdio.rs
+++ b/library/std/src/sys/pal/hermit/stdio.rs
@@ -1,6 +1,9 @@
 use super::hermit_abi;
 use crate::io;
 use crate::io::{IoSlice, IoSliceMut};
+use crate::mem::ManuallyDrop;
+use crate::os::hermit::io::FromRawFd;
+use crate::sys::fd::FileDesc;
 
 pub struct Stdin;
 pub struct Stdout;
@@ -13,12 +16,14 @@ impl Stdin {
 }
 
 impl io::Read for Stdin {
-    fn read(&mut self, data: &mut [u8]) -> io::Result<usize> {
-        self.read_vectored(&mut [IoSliceMut::new(data)])
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(hermit_abi::STDIN_FILENO)).read(buf) }
     }
 
-    fn read_vectored(&mut self, _data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        Ok(0)
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        unsafe {
+            ManuallyDrop::new(FileDesc::from_raw_fd(hermit_abi::STDIN_FILENO)).read_vectored(bufs)
+        }
     }
 
     #[inline]
@@ -34,27 +39,13 @@ impl Stdout {
 }
 
 impl io::Write for Stdout {
-    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
-        let len;
-
-        unsafe { len = hermit_abi::write(1, data.as_ptr() as *const u8, data.len()) }
-
-        if len < 0 {
-            Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stdout is not able to print"))
-        } else {
-            Ok(len as usize)
-        }
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(hermit_abi::STDOUT_FILENO)).write(buf) }
     }
 
-    fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
-        let len;
-
-        unsafe { len = hermit_abi::write(1, data.as_ptr() as *const u8, data.len()) }
-
-        if len < 0 {
-            Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stdout is not able to print"))
-        } else {
-            Ok(len as usize)
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        unsafe {
+            ManuallyDrop::new(FileDesc::from_raw_fd(hermit_abi::STDOUT_FILENO)).write_vectored(bufs)
         }
     }
 
@@ -75,27 +66,13 @@ impl Stderr {
 }
 
 impl io::Write for Stderr {
-    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
-        let len;
-
-        unsafe { len = hermit_abi::write(2, data.as_ptr() as *const u8, data.len()) }
-
-        if len < 0 {
-            Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stderr is not able to print"))
-        } else {
-            Ok(len as usize)
-        }
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(hermit_abi::STDERR_FILENO)).write(buf) }
     }
 
-    fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
-        let len;
-
-        unsafe { len = hermit_abi::write(2, data.as_ptr() as *const u8, data.len()) }
-
-        if len < 0 {
-            Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stderr is not able to print"))
-        } else {
-            Ok(len as usize)
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        unsafe {
+            ManuallyDrop::new(FileDesc::from_raw_fd(hermit_abi::STDERR_FILENO)).write_vectored(bufs)
         }
     }
 
@@ -109,10 +86,10 @@ impl io::Write for Stderr {
     }
 }
 
-pub const STDIN_BUF_SIZE: usize = 0;
+pub const STDIN_BUF_SIZE: usize = 128;
 
-pub fn is_ebadf(_err: &io::Error) -> bool {
-    true
+pub fn is_ebadf(err: &io::Error) -> bool {
+    err.raw_os_error() == Some(hermit_abi::EBADF)
 }
 
 pub fn panic_output() -> Option<impl io::Write> {
diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs
index b336dcd6860..07a843a597e 100644
--- a/library/std/src/sys/pal/hermit/thread.rs
+++ b/library/std/src/sys/pal/hermit/thread.rs
@@ -98,5 +98,5 @@ impl Thread {
 }
 
 pub fn available_parallelism() -> io::Result<NonZero<usize>> {
-    unsafe { Ok(NonZero::new_unchecked(hermit_abi::get_processor_count())) }
+    unsafe { Ok(NonZero::new_unchecked(hermit_abi::available_parallelism())) }
 }
diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs
index 2bf24462fa8..e0cb7c2aa98 100644
--- a/library/std/src/sys/pal/hermit/time.rs
+++ b/library/std/src/sys/pal/hermit/time.rs
@@ -1,11 +1,13 @@
 #![allow(dead_code)]
 
-use super::hermit_abi::{self, timespec, CLOCK_MONOTONIC, CLOCK_REALTIME, NSEC_PER_SEC};
+use super::hermit_abi::{self, timespec, CLOCK_MONOTONIC, CLOCK_REALTIME};
 use crate::cmp::Ordering;
 use crate::ops::{Add, AddAssign, Sub, SubAssign};
 use crate::time::Duration;
 use core::hash::{Hash, Hasher};
 
+const NSEC_PER_SEC: i32 = 1_000_000_000;
+
 #[derive(Copy, Clone, Debug)]
 struct Timespec {
     t: timespec,
@@ -16,8 +18,8 @@ impl Timespec {
         Timespec { t: timespec { tv_sec: 0, tv_nsec: 0 } }
     }
 
-    const fn new(tv_sec: i64, tv_nsec: i64) -> Timespec {
-        assert!(tv_nsec >= 0 && tv_nsec < NSEC_PER_SEC as i64);
+    const fn new(tv_sec: i64, tv_nsec: i32) -> Timespec {
+        assert!(tv_nsec >= 0 && tv_nsec < NSEC_PER_SEC);
         // SAFETY: The assert above checks tv_nsec is within the valid range
         Timespec { t: timespec { tv_sec: tv_sec, tv_nsec: tv_nsec } }
     }
@@ -32,7 +34,7 @@ impl Timespec {
             } else {
                 Duration::new(
                     (self.t.tv_sec - 1 - other.t.tv_sec) as u64,
-                    self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - other.t.tv_nsec as u32,
+                    (self.t.tv_nsec + NSEC_PER_SEC - other.t.tv_nsec) as u32,
                 )
             })
         } else {
@@ -48,9 +50,9 @@ impl Timespec {
 
         // Nano calculations can't overflow because nanos are <1B which fit
         // in a u32.
-        let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
-        if nsec >= NSEC_PER_SEC as u32 {
-            nsec -= NSEC_PER_SEC as u32;
+        let mut nsec = other.subsec_nanos() + u32::try_from(self.t.tv_nsec).unwrap();
+        if nsec >= NSEC_PER_SEC.try_into().unwrap() {
+            nsec -= u32::try_from(NSEC_PER_SEC).unwrap();
             secs = secs.checked_add(1)?;
         }
         Some(Timespec { t: timespec { tv_sec: secs, tv_nsec: nsec as _ } })
@@ -200,7 +202,7 @@ pub struct SystemTime(Timespec);
 pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero());
 
 impl SystemTime {
-    pub fn new(tv_sec: i64, tv_nsec: i64) -> SystemTime {
+    pub fn new(tv_sec: i64, tv_nsec: i32) -> SystemTime {
         SystemTime(Timespec::new(tv_sec, tv_nsec))
     }
 
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index 56a0f8e39c4..035c92bc84b 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -22,16 +22,12 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 
 #[cfg(any(all(target_os = "linux", target_env = "gnu"), target_vendor = "apple"))]
 use crate::sys::weak::syscall;
-#[cfg(any(target_os = "android", target_os = "macos", target_os = "solaris"))]
+#[cfg(target_os = "android")]
 use crate::sys::weak::weak;
 
 use libc::{c_int, mode_t};
 
-#[cfg(any(
-    target_os = "solaris",
-    all(target_os = "linux", target_env = "gnu"),
-    target_vendor = "apple",
-))]
+#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_vendor = "apple"))]
 use libc::c_char;
 #[cfg(any(
     all(target_os = "linux", not(target_env = "musl")),
@@ -1753,19 +1749,6 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> {
                     // Android has `linkat` on newer versions, but we happen to know `link`
                     // always has the correct behavior, so it's here as well.
                     cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
-                } else if #[cfg(any(target_os = "macos", target_os = "solaris"))] {
-                    // MacOS (<=10.9) and Solaris 10 lack support for linkat while newer
-                    // versions have it. We want to use linkat if it is available, so we use weak!
-                    // to check. `linkat` is preferable to `link` because it gives us a flag to
-                    // specify how symlinks should be handled. We pass 0 as the flags argument,
-                    // meaning it shouldn't follow symlinks.
-                    weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int);
-
-                    if let Some(f) = linkat.get() {
-                        cvt(unsafe { f(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
-                    } else {
-                        cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
-                    };
                 } else {
                     // Where we can, use `linkat` instead of `link`; see the comment above
                     // this one for details on why.
diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs
index 1da8871ae44..19f013d3347 100644
--- a/library/std/src/sys/pal/windows/c/windows_sys.rs
+++ b/library/std/src/sys/pal/windows/c/windows_sys.rs
@@ -1,4 +1,4 @@
-// Bindings generated by `windows-bindgen` 0.56.0
+// Bindings generated by `windows-bindgen` 0.57.0
 
 #![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]
 #[link(name = "advapi32")]
@@ -841,6 +841,7 @@ extern "system" {
 pub const ABOVE_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 32768u32;
 pub type ADDRESS_FAMILY = u16;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct ADDRINFOA {
     pub ai_flags: i32,
     pub ai_family: i32,
@@ -851,18 +852,13 @@ pub struct ADDRINFOA {
     pub ai_addr: *mut SOCKADDR,
     pub ai_next: *mut ADDRINFOA,
 }
-impl Copy for ADDRINFOA {}
-impl Clone for ADDRINFOA {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const AF_INET: ADDRESS_FAMILY = 2u16;
 pub const AF_INET6: ADDRESS_FAMILY = 23u16;
 pub const AF_UNIX: u16 = 1u16;
 pub const AF_UNSPEC: ADDRESS_FAMILY = 0u16;
 pub const ALL_PROCESSOR_GROUPS: u16 = 65535u16;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub union ARM64_NT_NEON128 {
     pub Anonymous: ARM64_NT_NEON128_0,
     pub D: [f64; 2],
@@ -870,27 +866,17 @@ pub union ARM64_NT_NEON128 {
     pub H: [u16; 8],
     pub B: [u8; 16],
 }
-impl Copy for ARM64_NT_NEON128 {}
-impl Clone for ARM64_NT_NEON128 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct ARM64_NT_NEON128_0 {
     pub Low: u64,
     pub High: i64,
 }
-impl Copy for ARM64_NT_NEON128_0 {}
-impl Clone for ARM64_NT_NEON128_0 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const BELOW_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 16384u32;
 pub type BOOL = i32;
 pub type BOOLEAN = u8;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct BY_HANDLE_FILE_INFORMATION {
     pub dwFileAttributes: u32,
     pub ftCreationTime: FILETIME,
@@ -903,41 +889,26 @@ pub struct BY_HANDLE_FILE_INFORMATION {
     pub nFileIndexHigh: u32,
     pub nFileIndexLow: u32,
 }
-impl Copy for BY_HANDLE_FILE_INFORMATION {}
-impl Clone for BY_HANDLE_FILE_INFORMATION {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const CALLBACK_CHUNK_FINISHED: LPPROGRESS_ROUTINE_CALLBACK_REASON = 0u32;
 pub const CALLBACK_STREAM_SWITCH: LPPROGRESS_ROUTINE_CALLBACK_REASON = 1u32;
 pub type COMPARESTRING_RESULT = i32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct CONDITION_VARIABLE {
     pub Ptr: *mut core::ffi::c_void,
 }
-impl Copy for CONDITION_VARIABLE {}
-impl Clone for CONDITION_VARIABLE {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub type CONSOLE_MODE = u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct CONSOLE_READCONSOLE_CONTROL {
     pub nLength: u32,
     pub nInitialChars: u32,
     pub dwCtrlWakeupMask: u32,
     pub dwControlKeyState: u32,
 }
-impl Copy for CONSOLE_READCONSOLE_CONTROL {}
-impl Clone for CONSOLE_READCONSOLE_CONTROL {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
 #[cfg(target_arch = "aarch64")]
+#[derive(Clone, Copy)]
 pub struct CONTEXT {
     pub ContextFlags: CONTEXT_FLAGS,
     pub Cpsr: u32,
@@ -952,30 +923,16 @@ pub struct CONTEXT {
     pub Wcr: [u32; 2],
     pub Wvr: [u64; 2],
 }
-#[cfg(target_arch = "aarch64")]
-impl Copy for CONTEXT {}
-#[cfg(target_arch = "aarch64")]
-impl Clone for CONTEXT {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
 #[cfg(target_arch = "aarch64")]
+#[derive(Clone, Copy)]
 pub union CONTEXT_0 {
     pub Anonymous: CONTEXT_0_0,
     pub X: [u64; 31],
 }
-#[cfg(target_arch = "aarch64")]
-impl Copy for CONTEXT_0 {}
-#[cfg(target_arch = "aarch64")]
-impl Clone for CONTEXT_0 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
 #[cfg(target_arch = "aarch64")]
+#[derive(Clone, Copy)]
 pub struct CONTEXT_0_0 {
     pub X0: u64,
     pub X1: u64,
@@ -1009,16 +966,9 @@ pub struct CONTEXT_0_0 {
     pub Fp: u64,
     pub Lr: u64,
 }
-#[cfg(target_arch = "aarch64")]
-impl Copy for CONTEXT_0_0 {}
-#[cfg(target_arch = "aarch64")]
-impl Clone for CONTEXT_0_0 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
 #[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
+#[derive(Clone, Copy)]
 pub struct CONTEXT {
     pub P1Home: u64,
     pub P2Home: u64,
@@ -1067,30 +1017,16 @@ pub struct CONTEXT {
     pub LastExceptionToRip: u64,
     pub LastExceptionFromRip: u64,
 }
-#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
-impl Copy for CONTEXT {}
-#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
-impl Clone for CONTEXT {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
 #[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
+#[derive(Clone, Copy)]
 pub union CONTEXT_0 {
     pub FltSave: XSAVE_FORMAT,
     pub Anonymous: CONTEXT_0_0,
 }
-#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
-impl Copy for CONTEXT_0 {}
-#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
-impl Clone for CONTEXT_0 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
 #[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
+#[derive(Clone, Copy)]
 pub struct CONTEXT_0_0 {
     pub Header: [M128A; 2],
     pub Legacy: [M128A; 8],
@@ -1111,16 +1047,9 @@ pub struct CONTEXT_0_0 {
     pub Xmm14: M128A,
     pub Xmm15: M128A,
 }
-#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
-impl Copy for CONTEXT_0_0 {}
-#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
-impl Clone for CONTEXT_0_0 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
 #[cfg(target_arch = "x86")]
+#[derive(Clone, Copy)]
 pub struct CONTEXT {
     pub ContextFlags: CONTEXT_FLAGS,
     pub Dr0: u32,
@@ -1148,14 +1077,6 @@ pub struct CONTEXT {
     pub SegSs: u32,
     pub ExtendedRegisters: [u8; 512],
 }
-#[cfg(target_arch = "x86")]
-impl Copy for CONTEXT {}
-#[cfg(target_arch = "x86")]
-impl Clone for CONTEXT {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub type CONTEXT_FLAGS = u32;
 pub const CP_UTF8: u32 = 65001u32;
 pub const CREATE_ALWAYS: FILE_CREATION_DISPOSITION = 2u32;
@@ -3068,6 +2989,7 @@ pub const ERROR_XML_PARSE_ERROR: WIN32_ERROR = 1465u32;
 pub type EXCEPTION_DISPOSITION = i32;
 pub const EXCEPTION_MAXIMUM_PARAMETERS: u32 = 15u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct EXCEPTION_RECORD {
     pub ExceptionCode: NTSTATUS,
     pub ExceptionFlags: u32,
@@ -3076,12 +2998,6 @@ pub struct EXCEPTION_RECORD {
     pub NumberParameters: u32,
     pub ExceptionInformation: [usize; 15],
 }
-impl Copy for EXCEPTION_RECORD {}
-impl Clone for EXCEPTION_RECORD {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _;
 pub const EXTENDED_STARTUPINFO_PRESENT: PROCESS_CREATION_FLAGS = 524288u32;
 pub const E_NOTIMPL: HRESULT = 0x80004001_u32 as _;
@@ -3095,40 +3011,25 @@ pub const FALSE: BOOL = 0i32;
 pub type FARPROC = Option<unsafe extern "system" fn() -> isize>;
 pub const FAST_FAIL_FATAL_APP_EXIT: u32 = 7u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct FD_SET {
     pub fd_count: u32,
     pub fd_array: [SOCKET; 64],
 }
-impl Copy for FD_SET {}
-impl Clone for FD_SET {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct FILETIME {
     pub dwLowDateTime: u32,
     pub dwHighDateTime: u32,
 }
-impl Copy for FILETIME {}
-impl Clone for FILETIME {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub type FILE_ACCESS_RIGHTS = u32;
 pub const FILE_ADD_FILE: FILE_ACCESS_RIGHTS = 2u32;
 pub const FILE_ADD_SUBDIRECTORY: FILE_ACCESS_RIGHTS = 4u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct FILE_ALLOCATION_INFO {
     pub AllocationSize: i64,
 }
-impl Copy for FILE_ALLOCATION_INFO {}
-impl Clone for FILE_ALLOCATION_INFO {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const FILE_ALL_ACCESS: FILE_ACCESS_RIGHTS = 2032127u32;
 pub const FILE_APPEND_DATA: FILE_ACCESS_RIGHTS = 4u32;
 pub const FILE_ATTRIBUTE_ARCHIVE: FILE_FLAGS_AND_ATTRIBUTES = 32u32;
@@ -3151,20 +3052,16 @@ pub const FILE_ATTRIBUTE_REPARSE_POINT: FILE_FLAGS_AND_ATTRIBUTES = 1024u32;
 pub const FILE_ATTRIBUTE_SPARSE_FILE: FILE_FLAGS_AND_ATTRIBUTES = 512u32;
 pub const FILE_ATTRIBUTE_SYSTEM: FILE_FLAGS_AND_ATTRIBUTES = 4u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct FILE_ATTRIBUTE_TAG_INFO {
     pub FileAttributes: u32,
     pub ReparseTag: u32,
 }
-impl Copy for FILE_ATTRIBUTE_TAG_INFO {}
-impl Clone for FILE_ATTRIBUTE_TAG_INFO {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const FILE_ATTRIBUTE_TEMPORARY: FILE_FLAGS_AND_ATTRIBUTES = 256u32;
 pub const FILE_ATTRIBUTE_UNPINNED: FILE_FLAGS_AND_ATTRIBUTES = 1048576u32;
 pub const FILE_ATTRIBUTE_VIRTUAL: FILE_FLAGS_AND_ATTRIBUTES = 65536u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct FILE_BASIC_INFO {
     pub CreationTime: i64,
     pub LastAccessTime: i64,
@@ -3172,12 +3069,6 @@ pub struct FILE_BASIC_INFO {
     pub ChangeTime: i64,
     pub FileAttributes: u32,
 }
-impl Copy for FILE_BASIC_INFO {}
-impl Clone for FILE_BASIC_INFO {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const FILE_BEGIN: SET_FILE_POINTER_MOVE_METHOD = 0u32;
 pub const FILE_COMPLETE_IF_OPLOCKED: NTCREATEFILE_CREATE_OPTIONS = 256u32;
 pub const FILE_CONTAINS_EXTENDED_CREATE_INFORMATION: NTCREATEFILE_CREATE_OPTIONS = 268435456u32;
@@ -3197,37 +3088,22 @@ pub const FILE_DISPOSITION_FLAG_IGNORE_READONLY_ATTRIBUTE: FILE_DISPOSITION_INFO
 pub const FILE_DISPOSITION_FLAG_ON_CLOSE: FILE_DISPOSITION_INFO_EX_FLAGS = 8u32;
 pub const FILE_DISPOSITION_FLAG_POSIX_SEMANTICS: FILE_DISPOSITION_INFO_EX_FLAGS = 2u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct FILE_DISPOSITION_INFO {
     pub DeleteFile: BOOLEAN,
 }
-impl Copy for FILE_DISPOSITION_INFO {}
-impl Clone for FILE_DISPOSITION_INFO {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct FILE_DISPOSITION_INFO_EX {
     pub Flags: FILE_DISPOSITION_INFO_EX_FLAGS,
 }
-impl Copy for FILE_DISPOSITION_INFO_EX {}
-impl Clone for FILE_DISPOSITION_INFO_EX {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub type FILE_DISPOSITION_INFO_EX_FLAGS = u32;
 pub const FILE_END: SET_FILE_POINTER_MOVE_METHOD = 2u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct FILE_END_OF_FILE_INFO {
     pub EndOfFile: i64,
 }
-impl Copy for FILE_END_OF_FILE_INFO {}
-impl Clone for FILE_END_OF_FILE_INFO {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const FILE_EXECUTE: FILE_ACCESS_RIGHTS = 32u32;
 pub type FILE_FLAGS_AND_ATTRIBUTES = u32;
 pub const FILE_FLAG_BACKUP_SEMANTICS: FILE_FLAGS_AND_ATTRIBUTES = 33554432u32;
@@ -3246,6 +3122,7 @@ pub const FILE_GENERIC_EXECUTE: FILE_ACCESS_RIGHTS = 1179808u32;
 pub const FILE_GENERIC_READ: FILE_ACCESS_RIGHTS = 1179785u32;
 pub const FILE_GENERIC_WRITE: FILE_ACCESS_RIGHTS = 1179926u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct FILE_ID_BOTH_DIR_INFO {
     pub NextEntryOffset: u32,
     pub FileIndex: u32,
@@ -3263,23 +3140,12 @@ pub struct FILE_ID_BOTH_DIR_INFO {
     pub FileId: i64,
     pub FileName: [u16; 1],
 }
-impl Copy for FILE_ID_BOTH_DIR_INFO {}
-impl Clone for FILE_ID_BOTH_DIR_INFO {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub type FILE_INFO_BY_HANDLE_CLASS = i32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct FILE_IO_PRIORITY_HINT_INFO {
     pub PriorityHint: PRIORITY_HINT,
 }
-impl Copy for FILE_IO_PRIORITY_HINT_INFO {}
-impl Clone for FILE_IO_PRIORITY_HINT_INFO {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const FILE_LIST_DIRECTORY: FILE_ACCESS_RIGHTS = 1u32;
 pub const FILE_NAME_NORMALIZED: GETFINALPATHNAMEBYHANDLE_FLAGS = 0u32;
 pub const FILE_NAME_OPENED: GETFINALPATHNAMEBYHANDLE_FLAGS = 8u32;
@@ -3310,6 +3176,7 @@ pub const FILE_SHARE_NONE: FILE_SHARE_MODE = 0u32;
 pub const FILE_SHARE_READ: FILE_SHARE_MODE = 1u32;
 pub const FILE_SHARE_WRITE: FILE_SHARE_MODE = 2u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct FILE_STANDARD_INFO {
     pub AllocationSize: i64,
     pub EndOfFile: i64,
@@ -3317,12 +3184,6 @@ pub struct FILE_STANDARD_INFO {
     pub DeletePending: BOOLEAN,
     pub Directory: BOOLEAN,
 }
-impl Copy for FILE_STANDARD_INFO {}
-impl Clone for FILE_STANDARD_INFO {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const FILE_SUPERSEDE: NTCREATEFILE_CREATE_DISPOSITION = 0u32;
 pub const FILE_SYNCHRONOUS_IO_ALERT: NTCREATEFILE_CREATE_OPTIONS = 16u32;
 pub const FILE_SYNCHRONOUS_IO_NONALERT: NTCREATEFILE_CREATE_OPTIONS = 32u32;
@@ -3340,6 +3201,7 @@ pub const FILE_WRITE_THROUGH: NTCREATEFILE_CREATE_OPTIONS = 2u32;
 pub const FIONBIO: i32 = -2147195266i32;
 #[repr(C)]
 #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
+#[derive(Clone, Copy)]
 pub struct FLOATING_SAVE_AREA {
     pub ControlWord: u32,
     pub StatusWord: u32,
@@ -3351,16 +3213,9 @@ pub struct FLOATING_SAVE_AREA {
     pub RegisterArea: [u8; 80],
     pub Cr0NpxState: u32,
 }
-#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
-impl Copy for FLOATING_SAVE_AREA {}
-#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
-impl Clone for FLOATING_SAVE_AREA {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
 #[cfg(target_arch = "x86")]
+#[derive(Clone, Copy)]
 pub struct FLOATING_SAVE_AREA {
     pub ControlWord: u32,
     pub StatusWord: u32,
@@ -3372,14 +3227,6 @@ pub struct FLOATING_SAVE_AREA {
     pub RegisterArea: [u8; 80],
     pub Spare0: u32,
 }
-#[cfg(target_arch = "x86")]
-impl Copy for FLOATING_SAVE_AREA {}
-#[cfg(target_arch = "x86")]
-impl Clone for FLOATING_SAVE_AREA {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const FORMAT_MESSAGE_ALLOCATE_BUFFER: FORMAT_MESSAGE_OPTIONS = 256u32;
 pub const FORMAT_MESSAGE_ARGUMENT_ARRAY: FORMAT_MESSAGE_OPTIONS = 8192u32;
 pub const FORMAT_MESSAGE_FROM_HMODULE: FORMAT_MESSAGE_OPTIONS = 2048u32;
@@ -3422,18 +3269,13 @@ pub const GENERIC_READ: GENERIC_ACCESS_RIGHTS = 2147483648u32;
 pub const GENERIC_WRITE: GENERIC_ACCESS_RIGHTS = 1073741824u32;
 pub type GETFINALPATHNAMEBYHANDLE_FLAGS = u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct GUID {
     pub data1: u32,
     pub data2: u16,
     pub data3: u16,
     pub data4: [u8; 8],
 }
-impl Copy for GUID {}
-impl Clone for GUID {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 impl GUID {
     pub const fn from_u128(uuid: u128) -> Self {
         Self {
@@ -3454,112 +3296,67 @@ pub type HMODULE = *mut core::ffi::c_void;
 pub type HRESULT = i32;
 pub const IDLE_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 64u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct IN6_ADDR {
     pub u: IN6_ADDR_0,
 }
-impl Copy for IN6_ADDR {}
-impl Clone for IN6_ADDR {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub union IN6_ADDR_0 {
     pub Byte: [u8; 16],
     pub Word: [u16; 8],
 }
-impl Copy for IN6_ADDR_0 {}
-impl Clone for IN6_ADDR_0 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const INFINITE: u32 = 4294967295u32;
 pub const INHERIT_CALLER_PRIORITY: PROCESS_CREATION_FLAGS = 131072u32;
 pub const INHERIT_PARENT_AFFINITY: PROCESS_CREATION_FLAGS = 65536u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub union INIT_ONCE {
     pub Ptr: *mut core::ffi::c_void,
 }
-impl Copy for INIT_ONCE {}
-impl Clone for INIT_ONCE {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const INIT_ONCE_INIT_FAILED: u32 = 4u32;
 pub const INVALID_FILE_ATTRIBUTES: u32 = 4294967295u32;
 pub const INVALID_SOCKET: SOCKET = -1i32 as _;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct IN_ADDR {
     pub S_un: IN_ADDR_0,
 }
-impl Copy for IN_ADDR {}
-impl Clone for IN_ADDR {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub union IN_ADDR_0 {
     pub S_un_b: IN_ADDR_0_0,
     pub S_un_w: IN_ADDR_0_1,
     pub S_addr: u32,
 }
-impl Copy for IN_ADDR_0 {}
-impl Clone for IN_ADDR_0 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct IN_ADDR_0_0 {
     pub s_b1: u8,
     pub s_b2: u8,
     pub s_b3: u8,
     pub s_b4: u8,
 }
-impl Copy for IN_ADDR_0_0 {}
-impl Clone for IN_ADDR_0_0 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct IN_ADDR_0_1 {
     pub s_w1: u16,
     pub s_w2: u16,
 }
-impl Copy for IN_ADDR_0_1 {}
-impl Clone for IN_ADDR_0_1 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const IO_REPARSE_TAG_MOUNT_POINT: u32 = 2684354563u32;
 pub const IO_REPARSE_TAG_SYMLINK: u32 = 2684354572u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct IO_STATUS_BLOCK {
     pub Anonymous: IO_STATUS_BLOCK_0,
     pub Information: usize,
 }
-impl Copy for IO_STATUS_BLOCK {}
-impl Clone for IO_STATUS_BLOCK {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub union IO_STATUS_BLOCK_0 {
     pub Status: NTSTATUS,
     pub Pointer: *mut core::ffi::c_void,
 }
-impl Copy for IO_STATUS_BLOCK_0 {}
-impl Clone for IO_STATUS_BLOCK_0 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub type IPPROTO = i32;
 pub const IPPROTO_AH: IPPROTO = 51i32;
 pub const IPPROTO_CBT: IPPROTO = 7i32;
@@ -3601,45 +3398,30 @@ pub const IPPROTO_UDP: IPPROTO = 17i32;
 pub const IPV6_ADD_MEMBERSHIP: i32 = 12i32;
 pub const IPV6_DROP_MEMBERSHIP: i32 = 13i32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct IPV6_MREQ {
     pub ipv6mr_multiaddr: IN6_ADDR,
     pub ipv6mr_interface: u32,
 }
-impl Copy for IPV6_MREQ {}
-impl Clone for IPV6_MREQ {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const IPV6_MULTICAST_LOOP: i32 = 11i32;
 pub const IPV6_V6ONLY: i32 = 27i32;
 pub const IP_ADD_MEMBERSHIP: i32 = 12i32;
 pub const IP_DROP_MEMBERSHIP: i32 = 13i32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct IP_MREQ {
     pub imr_multiaddr: IN_ADDR,
     pub imr_interface: IN_ADDR,
 }
-impl Copy for IP_MREQ {}
-impl Clone for IP_MREQ {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const IP_MULTICAST_LOOP: i32 = 11i32;
 pub const IP_MULTICAST_TTL: i32 = 10i32;
 pub const IP_TTL: i32 = 4i32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct LINGER {
     pub l_onoff: u16,
     pub l_linger: u16,
 }
-impl Copy for LINGER {}
-impl Clone for LINGER {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub type LPOVERLAPPED_COMPLETION_ROUTINE = Option<
     unsafe extern "system" fn(
         dwerrorcode: u32,
@@ -3673,16 +3455,11 @@ pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = Option<
     ),
 >;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct M128A {
     pub Low: u64,
     pub High: i64,
 }
-impl Copy for M128A {}
-impl Clone for M128A {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: u32 = 16384u32;
 pub const MAX_PATH: u32 = 260u32;
 pub const MB_COMPOSITE: MULTI_BYTE_TO_WIDE_CHAR_FLAGS = 2u32;
@@ -3710,6 +3487,7 @@ pub type NTCREATEFILE_CREATE_DISPOSITION = u32;
 pub type NTCREATEFILE_CREATE_OPTIONS = u32;
 pub type NTSTATUS = i32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct OBJECT_ATTRIBUTES {
     pub Length: u32,
     pub RootDirectory: HANDLE,
@@ -3718,50 +3496,29 @@ pub struct OBJECT_ATTRIBUTES {
     pub SecurityDescriptor: *const core::ffi::c_void,
     pub SecurityQualityOfService: *const core::ffi::c_void,
 }
-impl Copy for OBJECT_ATTRIBUTES {}
-impl Clone for OBJECT_ATTRIBUTES {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const OBJ_DONT_REPARSE: i32 = 4096i32;
 pub const OPEN_ALWAYS: FILE_CREATION_DISPOSITION = 4u32;
 pub const OPEN_EXISTING: FILE_CREATION_DISPOSITION = 3u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct OVERLAPPED {
     pub Internal: usize,
     pub InternalHigh: usize,
     pub Anonymous: OVERLAPPED_0,
     pub hEvent: HANDLE,
 }
-impl Copy for OVERLAPPED {}
-impl Clone for OVERLAPPED {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub union OVERLAPPED_0 {
     pub Anonymous: OVERLAPPED_0_0,
     pub Pointer: *mut core::ffi::c_void,
 }
-impl Copy for OVERLAPPED_0 {}
-impl Clone for OVERLAPPED_0 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct OVERLAPPED_0_0 {
     pub Offset: u32,
     pub OffsetHigh: u32,
 }
-impl Copy for OVERLAPPED_0_0 {}
-impl Clone for OVERLAPPED_0_0 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub type PCSTR = *const u8;
 pub type PCWSTR = *const u16;
 pub type PIO_APC_ROUTINE = Option<
@@ -3788,18 +3545,13 @@ pub type PRIORITY_HINT = i32;
 pub type PROCESSOR_ARCHITECTURE = u16;
 pub type PROCESS_CREATION_FLAGS = u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct PROCESS_INFORMATION {
     pub hProcess: HANDLE,
     pub hThread: HANDLE,
     pub dwProcessId: u32,
     pub dwThreadId: u32,
 }
-impl Copy for PROCESS_INFORMATION {}
-impl Clone for PROCESS_INFORMATION {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const PROCESS_MODE_BACKGROUND_BEGIN: PROCESS_CREATION_FLAGS = 1048576u32;
 pub const PROCESS_MODE_BACKGROUND_END: PROCESS_CREATION_FLAGS = 2097152u32;
 pub const PROFILE_KERNEL: PROCESS_CREATION_FLAGS = 536870912u32;
@@ -3822,17 +3574,12 @@ pub const SD_RECEIVE: WINSOCK_SHUTDOWN_HOW = 0i32;
 pub const SD_SEND: WINSOCK_SHUTDOWN_HOW = 1i32;
 pub const SECURITY_ANONYMOUS: FILE_FLAGS_AND_ATTRIBUTES = 0u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct SECURITY_ATTRIBUTES {
     pub nLength: u32,
     pub lpSecurityDescriptor: *mut core::ffi::c_void,
     pub bInheritHandle: BOOL,
 }
-impl Copy for SECURITY_ATTRIBUTES {}
-impl Clone for SECURITY_ATTRIBUTES {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const SECURITY_CONTEXT_TRACKING: FILE_FLAGS_AND_ATTRIBUTES = 262144u32;
 pub const SECURITY_DELEGATION: FILE_FLAGS_AND_ATTRIBUTES = 196608u32;
 pub const SECURITY_EFFECTIVE_ONLY: FILE_FLAGS_AND_ATTRIBUTES = 524288u32;
@@ -3843,27 +3590,17 @@ pub const SECURITY_VALID_SQOS_FLAGS: FILE_FLAGS_AND_ATTRIBUTES = 2031616u32;
 pub type SEND_RECV_FLAGS = i32;
 pub type SET_FILE_POINTER_MOVE_METHOD = u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct SOCKADDR {
     pub sa_family: ADDRESS_FAMILY,
     pub sa_data: [i8; 14],
 }
-impl Copy for SOCKADDR {}
-impl Clone for SOCKADDR {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct SOCKADDR_UN {
     pub sun_family: ADDRESS_FAMILY,
     pub sun_path: [i8; 108],
 }
-impl Copy for SOCKADDR_UN {}
-impl Clone for SOCKADDR_UN {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub type SOCKET = usize;
 pub const SOCKET_ERROR: i32 = -1i32;
 pub const SOCK_DGRAM: WINSOCK_SOCKET_TYPE = 2i32;
@@ -3879,15 +3616,10 @@ pub const SO_RCVTIMEO: i32 = 4102i32;
 pub const SO_SNDTIMEO: i32 = 4101i32;
 pub const SPECIFIC_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 65535u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct SRWLOCK {
     pub Ptr: *mut core::ffi::c_void,
 }
-impl Copy for SRWLOCK {}
-impl Clone for SRWLOCK {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const STACK_SIZE_PARAM_IS_A_RESERVATION: THREAD_CREATION_FLAGS = 65536u32;
 pub const STANDARD_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 2031616u32;
 pub const STANDARD_RIGHTS_EXECUTE: FILE_ACCESS_RIGHTS = 131072u32;
@@ -3909,17 +3641,13 @@ pub const STARTF_USESHOWWINDOW: STARTUPINFOW_FLAGS = 1u32;
 pub const STARTF_USESIZE: STARTUPINFOW_FLAGS = 2u32;
 pub const STARTF_USESTDHANDLES: STARTUPINFOW_FLAGS = 256u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct STARTUPINFOEXW {
     pub StartupInfo: STARTUPINFOW,
     pub lpAttributeList: LPPROC_THREAD_ATTRIBUTE_LIST,
 }
-impl Copy for STARTUPINFOEXW {}
-impl Clone for STARTUPINFOEXW {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct STARTUPINFOW {
     pub cb: u32,
     pub lpReserved: PWSTR,
@@ -3940,12 +3668,6 @@ pub struct STARTUPINFOW {
     pub hStdOutput: HANDLE,
     pub hStdError: HANDLE,
 }
-impl Copy for STARTUPINFOW {}
-impl Clone for STARTUPINFOW {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub type STARTUPINFOW_FLAGS = u32;
 pub const STATUS_DELETE_PENDING: NTSTATUS = 0xC0000056_u32 as _;
 pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011_u32 as _;
@@ -3964,6 +3686,7 @@ pub const SYMLINK_FLAG_RELATIVE: u32 = 1u32;
 pub type SYNCHRONIZATION_ACCESS_RIGHTS = u32;
 pub const SYNCHRONIZE: FILE_ACCESS_RIGHTS = 1048576u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct SYSTEM_INFO {
     pub Anonymous: SYSTEM_INFO_0,
     pub dwPageSize: u32,
@@ -3976,34 +3699,18 @@ pub struct SYSTEM_INFO {
     pub wProcessorLevel: u16,
     pub wProcessorRevision: u16,
 }
-impl Copy for SYSTEM_INFO {}
-impl Clone for SYSTEM_INFO {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub union SYSTEM_INFO_0 {
     pub dwOemId: u32,
     pub Anonymous: SYSTEM_INFO_0_0,
 }
-impl Copy for SYSTEM_INFO_0 {}
-impl Clone for SYSTEM_INFO_0 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct SYSTEM_INFO_0_0 {
     pub wProcessorArchitecture: PROCESSOR_ARCHITECTURE,
     pub wReserved: u16,
 }
-impl Copy for SYSTEM_INFO_0_0 {}
-impl Clone for SYSTEM_INFO_0_0 {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const TCP_NODELAY: i32 = 1i32;
 pub const THREAD_CREATE_RUN_IMMEDIATELY: THREAD_CREATION_FLAGS = 0u32;
 pub const THREAD_CREATE_SUSPENDED: THREAD_CREATION_FLAGS = 4u32;
@@ -4011,16 +3718,11 @@ pub type THREAD_CREATION_FLAGS = u32;
 pub const TIMER_ALL_ACCESS: SYNCHRONIZATION_ACCESS_RIGHTS = 2031619u32;
 pub const TIMER_MODIFY_STATE: SYNCHRONIZATION_ACCESS_RIGHTS = 2u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct TIMEVAL {
     pub tv_sec: i32,
     pub tv_usec: i32,
 }
-impl Copy for TIMEVAL {}
-impl Clone for TIMEVAL {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const TLS_OUT_OF_INDEXES: u32 = 4294967295u32;
 pub type TOKEN_ACCESS_MASK = u32;
 pub const TOKEN_ACCESS_PSEUDO_HANDLE: TOKEN_ACCESS_MASK = 24u32;
@@ -4047,17 +3749,12 @@ pub const TOKEN_WRITE_OWNER: TOKEN_ACCESS_MASK = 524288u32;
 pub const TRUE: BOOL = 1i32;
 pub const TRUNCATE_EXISTING: FILE_CREATION_DISPOSITION = 5u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct UNICODE_STRING {
     pub Length: u16,
     pub MaximumLength: u16,
     pub Buffer: PWSTR,
 }
-impl Copy for UNICODE_STRING {}
-impl Clone for UNICODE_STRING {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const VOLUME_NAME_DOS: GETFINALPATHNAMEBYHANDLE_FLAGS = 0u32;
 pub const VOLUME_NAME_GUID: GETFINALPATHNAMEBYHANDLE_FLAGS = 1u32;
 pub const VOLUME_NAME_NONE: GETFINALPATHNAMEBYHANDLE_FLAGS = 4u32;
@@ -4071,6 +3768,7 @@ pub const WAIT_TIMEOUT: WAIT_EVENT = 258u32;
 pub const WC_ERR_INVALID_CHARS: u32 = 128u32;
 pub type WIN32_ERROR = u32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct WIN32_FIND_DATAW {
     pub dwFileAttributes: u32,
     pub ftCreationTime: FILETIME,
@@ -4083,30 +3781,20 @@ pub struct WIN32_FIND_DATAW {
     pub cFileName: [u16; 260],
     pub cAlternateFileName: [u16; 14],
 }
-impl Copy for WIN32_FIND_DATAW {}
-impl Clone for WIN32_FIND_DATAW {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub type WINSOCK_SHUTDOWN_HOW = i32;
 pub type WINSOCK_SOCKET_TYPE = i32;
 pub const WRITE_DAC: FILE_ACCESS_RIGHTS = 262144u32;
 pub const WRITE_OWNER: FILE_ACCESS_RIGHTS = 524288u32;
 pub const WSABASEERR: WSA_ERROR = 10000i32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct WSABUF {
     pub len: u32,
     pub buf: PSTR,
 }
-impl Copy for WSABUF {}
-impl Clone for WSABUF {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
 #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
+#[derive(Clone, Copy)]
 pub struct WSADATA {
     pub wVersion: u16,
     pub wHighVersion: u16,
@@ -4116,16 +3804,9 @@ pub struct WSADATA {
     pub szDescription: [i8; 257],
     pub szSystemStatus: [i8; 129],
 }
-#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
-impl Copy for WSADATA {}
-#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
-impl Clone for WSADATA {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
 #[cfg(target_arch = "x86")]
+#[derive(Clone, Copy)]
 pub struct WSADATA {
     pub wVersion: u16,
     pub wHighVersion: u16,
@@ -4135,14 +3816,6 @@ pub struct WSADATA {
     pub iMaxUdpDg: u16,
     pub lpVendorInfo: PSTR,
 }
-#[cfg(target_arch = "x86")]
-impl Copy for WSADATA {}
-#[cfg(target_arch = "x86")]
-impl Clone for WSADATA {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const WSAEACCES: WSA_ERROR = 10013i32;
 pub const WSAEADDRINUSE: WSA_ERROR = 10048i32;
 pub const WSAEADDRNOTAVAIL: WSA_ERROR = 10049i32;
@@ -4198,17 +3871,13 @@ pub const WSANOTINITIALISED: WSA_ERROR = 10093i32;
 pub const WSANO_DATA: WSA_ERROR = 11004i32;
 pub const WSANO_RECOVERY: WSA_ERROR = 11003i32;
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct WSAPROTOCOLCHAIN {
     pub ChainLen: i32,
     pub ChainEntries: [u32; 7],
 }
-impl Copy for WSAPROTOCOLCHAIN {}
-impl Clone for WSAPROTOCOLCHAIN {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
+#[derive(Clone, Copy)]
 pub struct WSAPROTOCOL_INFOW {
     pub dwServiceFlags1: u32,
     pub dwServiceFlags2: u32,
@@ -4231,12 +3900,6 @@ pub struct WSAPROTOCOL_INFOW {
     pub dwProviderReserved: u32,
     pub szProtocol: [u16; 256],
 }
-impl Copy for WSAPROTOCOL_INFOW {}
-impl Clone for WSAPROTOCOL_INFOW {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 pub const WSASERVICE_NOT_FOUND: WSA_ERROR = 10108i32;
 pub const WSASYSCALLFAILURE: WSA_ERROR = 10107i32;
 pub const WSASYSNOTREADY: WSA_ERROR = 10091i32;
@@ -4287,6 +3950,7 @@ pub const WSA_WAIT_EVENT_0: WSA_ERROR = 0i32;
 pub const WSA_WAIT_IO_COMPLETION: WSA_ERROR = 192i32;
 #[repr(C)]
 #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
+#[derive(Clone, Copy)]
 pub struct XSAVE_FORMAT {
     pub ControlWord: u16,
     pub StatusWord: u16,
@@ -4305,16 +3969,9 @@ pub struct XSAVE_FORMAT {
     pub XmmRegisters: [M128A; 16],
     pub Reserved4: [u8; 96],
 }
-#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
-impl Copy for XSAVE_FORMAT {}
-#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
-impl Clone for XSAVE_FORMAT {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 #[repr(C)]
 #[cfg(target_arch = "x86")]
+#[derive(Clone, Copy)]
 pub struct XSAVE_FORMAT {
     pub ControlWord: u16,
     pub StatusWord: u16,
@@ -4333,12 +3990,4 @@ pub struct XSAVE_FORMAT {
     pub XmmRegisters: [M128A; 8],
     pub Reserved4: [u8; 224],
 }
-#[cfg(target_arch = "x86")]
-impl Copy for XSAVE_FORMAT {}
-#[cfg(target_arch = "x86")]
-impl Clone for XSAVE_FORMAT {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
 // ignore-tidy-filelength
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 66692a2a2cb..cc5b0073213 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1008,10 +1008,7 @@ pub fn rustc_cargo(
 
     // If the rustc output is piped to e.g. `head -n1` we want the process to be
     // killed, rather than having an error bubble up and cause a panic.
-    // FIXME: Synthetic #[cfg(bootstrap)]. Remove when the bootstrap compiler supports it.
-    if compiler.stage != 0 {
-        cargo.rustflag("-Zon-broken-pipe=kill");
-    }
+    cargo.rustflag("-Zon-broken-pipe=kill");
 
     // We currently don't support cross-crate LTO in stage0. This also isn't hugely necessary
     // and may just be a time sink.
@@ -1137,7 +1134,9 @@ pub fn rustc_cargo_env(
     }
 
     // Enable rustc's env var for `rust-lld` when requested.
-    if builder.config.lld_enabled {
+    if builder.config.lld_enabled
+        && (builder.config.channel == "dev" || builder.config.channel == "nightly")
+    {
         cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
     }
 
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 60b1ff3e441..f651f751441 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -78,7 +78,7 @@ impl Step for Docs {
 
         let mut tarball = Tarball::new(builder, "rust-docs", &host.triple);
         tarball.set_product_name("Rust Documentation");
-        tarball.add_bulk_dir(&builder.doc_out(host), dest);
+        tarball.add_bulk_dir(builder.doc_out(host), dest);
         tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, 0o644);
         Some(tarball.generate())
     }
@@ -117,7 +117,7 @@ impl Step for JsonDocs {
         let mut tarball = Tarball::new(builder, "rust-docs-json", &host.triple);
         tarball.set_product_name("Rust Documentation In JSON Format");
         tarball.is_preview(true);
-        tarball.add_bulk_dir(&builder.json_doc_out(host), dest);
+        tarball.add_bulk_dir(builder.json_doc_out(host), dest);
         Some(tarball.generate())
     }
 }
@@ -148,7 +148,7 @@ impl Step for RustcDocs {
 
         let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple);
         tarball.set_product_name("Rustc Documentation");
-        tarball.add_bulk_dir(&builder.compiler_doc_out(host), "share/doc/rust/html/rustc");
+        tarball.add_bulk_dir(builder.compiler_doc_out(host), "share/doc/rust/html/rustc");
         Some(tarball.generate())
     }
 }
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index b37b2b5bcef..6748625f132 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -378,7 +378,7 @@ impl Step for Standalone {
                 .arg(&favicon)
                 .arg("--markdown-no-toc")
                 .arg("--index-page")
-                .arg(&builder.src.join("src/doc/index.md"))
+                .arg(builder.src.join("src/doc/index.md"))
                 .arg("--markdown-playground-url")
                 .arg("https://play.rust-lang.org/")
                 .arg("-o")
@@ -482,7 +482,7 @@ impl Step for Releases {
                 .arg("--markdown-css")
                 .arg("rust.css")
                 .arg("--index-page")
-                .arg(&builder.src.join("src/doc/index.md"))
+                .arg(builder.src.join("src/doc/index.md"))
                 .arg("--markdown-playground-url")
                 .arg("https://play.rust-lang.org/")
                 .arg("-o")
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index 0caa39d78ac..b96e26dbb3a 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -15,7 +15,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F
     let mut cmd = Command::new(rustfmt);
     // Avoid the submodule config paths from coming into play. We only allow a single global config
     // for the workspace for now.
-    cmd.arg("--config-path").arg(&src.canonicalize().unwrap());
+    cmd.arg("--config-path").arg(src.canonicalize().unwrap());
     cmd.arg("--edition").arg("2021");
     cmd.arg("--unstable-features");
     cmd.arg("--skip-children");
@@ -93,7 +93,7 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, Str
         return Ok(None);
     }
 
-    get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &vec!["rs"])
+    get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &["rs"])
 }
 
 #[derive(serde_derive::Deserialize)]
diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs
index 354eb2b6003..9268b335db7 100644
--- a/src/bootstrap/src/core/build_steps/run.rs
+++ b/src/bootstrap/src/core/build_steps/run.rs
@@ -149,12 +149,14 @@ impl Step for Miri {
             &[],
         );
         miri.add_rustc_lib_path(builder);
-        // Forward arguments.
         miri.arg("--").arg("--target").arg(target.rustc_target_arg());
-        miri.args(builder.config.args());
 
         // miri tests need to know about the stage sysroot
-        miri.env("MIRI_SYSROOT", &miri_sysroot);
+        miri.arg("--sysroot").arg(miri_sysroot);
+
+        // Forward arguments. This may contain further arguments to the program
+        // after another --, so this must be at the end.
+        miri.args(builder.config.args());
 
         let mut miri = Command::from(miri);
         builder.run(&mut miri);
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 29cd90222b2..7556a19c90c 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -308,7 +308,7 @@ impl Step for Cargo {
         // Forcibly disable tests using nightly features since any changes to
         // those features won't be able to land.
         cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
-        cargo.env("PATH", &path_for_cargo(builder, compiler));
+        cargo.env("PATH", path_for_cargo(builder, compiler));
 
         #[cfg(feature = "build-metrics")]
         builder.metrics.begin_test_suite(
@@ -2559,7 +2559,7 @@ fn prepare_cargo_test(
         cargo.arg("-p").arg(krate);
     }
 
-    cargo.arg("--").args(&builder.config.test_args()).args(libtest_args);
+    cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
     if !builder.config.verbose_tests {
         cargo.arg("--quiet");
     }
@@ -3108,7 +3108,7 @@ impl Step for TierCheck {
             &[],
         );
         cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
-        cargo.arg(&builder.rustc(self.compiler));
+        cargo.arg(builder.rustc(self.compiler));
         if builder.is_verbose() {
             cargo.arg("--verbose");
         }
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 9df4698f21f..e0a9674ae5a 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -199,7 +199,7 @@ pub fn prepare_tool_cargo(
         cargo.env("CFG_COMMIT_DATE", date);
     }
     if !features.is_empty() {
-        cargo.arg("--features").arg(&features.join(", "));
+        cargo.arg("--features").arg(features.join(", "));
     }
 
     // Enable internal lints for clippy and rustdoc
@@ -521,10 +521,7 @@ impl Step for Rustdoc {
         // If the rustdoc output is piped to e.g. `head -n1` we want the process
         // to be killed, rather than having an error bubble up and cause a
         // panic.
-        // FIXME: Synthetic #[cfg(bootstrap)]. Remove when the bootstrap compiler supports it.
-        if build_compiler.stage > 0 {
-            cargo.rustflag("-Zon-broken-pipe=kill");
-        }
+        cargo.rustflag("-Zon-broken-pipe=kill");
 
         let _guard = builder.msg_tool(
             Kind::Build,
@@ -826,19 +823,29 @@ impl Step for LibcxxVersionTool {
 
     fn run(self, builder: &Builder<'_>) -> LibcxxVersion {
         let out_dir = builder.out.join(self.target.to_string()).join("libcxx-version");
-        let _ = fs::remove_dir_all(&out_dir);
-        t!(fs::create_dir_all(&out_dir));
+        let executable = out_dir.join(exe("libcxx-version", self.target));
+
+        // This is a sanity-check specific step, which means it is frequently called (when using
+        // CI LLVM), and compiling `src/tools/libcxx-version/main.cpp` at the beginning of the bootstrap
+        // invocation adds a fair amount of overhead to the process (see https://github.com/rust-lang/rust/issues/126423).
+        // Therefore, we want to avoid recompiling this file unnecessarily.
+        if !executable.exists() {
+            if !out_dir.exists() {
+                t!(fs::create_dir_all(&out_dir));
+            }
 
-        let compiler = builder.cxx(self.target).unwrap();
-        let mut cmd = Command::new(compiler);
+            let compiler = builder.cxx(self.target).unwrap();
+            let mut cmd = Command::new(compiler);
 
-        let executable = out_dir.join(exe("libcxx-version", self.target));
-        cmd.arg("-o").arg(&executable).arg(builder.src.join("src/tools/libcxx-version/main.cpp"));
+            cmd.arg("-o")
+                .arg(&executable)
+                .arg(builder.src.join("src/tools/libcxx-version/main.cpp"));
 
-        builder.run_cmd(&mut cmd);
+            builder.run_cmd(&mut cmd);
 
-        if !executable.exists() {
-            panic!("Something went wrong. {} is not present", executable.display());
+            if !executable.exists() {
+                panic!("Something went wrong. {} is not present", executable.display());
+            }
         }
 
         let version_output = output(&mut Command::new(executable));
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 12d2bb18ab7..d9e4cbae17d 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -1566,7 +1566,6 @@ impl<'a> Builder<'a> {
         // features but cargo isn't involved in the #[path] process and so cannot pass the
         // complete list of features, so for that reason we don't enable checking of
         // features for std crates.
-        cargo.arg("-Zcheck-cfg");
         if mode == Mode::Std {
             rustflags.arg("--check-cfg=cfg(feature,values(any()))");
         }
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 36b44d0169c..6024896b065 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -10,7 +10,7 @@ use std::env;
 use std::fmt::{self, Display};
 use std::fs;
 use std::io::IsTerminal;
-use std::path::{Path, PathBuf};
+use std::path::{absolute, Path, PathBuf};
 use std::process::Command;
 use std::str::FromStr;
 use std::sync::OnceLock;
@@ -1437,7 +1437,7 @@ impl Config {
         // To avoid writing to random places on the file system, `config.out` needs to be an absolute path.
         if !config.out.is_absolute() {
             // `canonicalize` requires the path to already exist. Use our vendored copy of `absolute` instead.
-            config.out = crate::utils::helpers::absolute(&config.out);
+            config.out = absolute(&config.out).expect("can't make empty path absolute");
         }
 
         config.initial_rustc = if let Some(rustc) = rustc {
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index b5f17b9f54e..5a0be2948a1 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -128,6 +128,9 @@ pub fn check(build: &mut Build) {
                     eprintln!(
                         "Consider upgrading libstdc++ or disabling the `llvm.download-ci-llvm` option."
                     );
+                    eprintln!(
+                        "If you choose to upgrade libstdc++, run `x clean` or delete `build/host/libcxx-version` manually after the upgrade."
+                    );
                 }
             }
             tool::LibcxxVersion::Llvm(_) => {
@@ -137,19 +140,20 @@ pub fn check(build: &mut Build) {
     }
 
     // We need cmake, but only if we're actually building LLVM or sanitizers.
-    let building_llvm = build
-        .hosts
-        .iter()
-        .map(|host| {
-            build.config.llvm_enabled(*host)
-                && build
-                    .config
-                    .target_config
-                    .get(host)
-                    .map(|config| config.llvm_config.is_none())
-                    .unwrap_or(true)
-        })
-        .any(|build_llvm_ourselves| build_llvm_ourselves);
+    let building_llvm = !build.config.llvm_from_ci
+        && build
+            .hosts
+            .iter()
+            .map(|host| {
+                build.config.llvm_enabled(*host)
+                    && build
+                        .config
+                        .target_config
+                        .get(host)
+                        .map(|config| config.llvm_config.is_none())
+                        .unwrap_or(true)
+            })
+            .any(|build_llvm_ourselves| build_llvm_ourselves);
 
     let need_cmake = building_llvm || build.config.any_sanitizers_to_build();
     if need_cmake && cmd_finder.maybe_have("cmake").is_none() {
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index cde090637e0..1cab02e8c31 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -624,7 +624,7 @@ impl Build {
             self.config
                 .git()
                 .args(["config", "--file"])
-                .arg(&self.config.src.join(".gitmodules"))
+                .arg(self.config.src.join(".gitmodules"))
                 .args(["--get-regexp", "path"]),
         );
         for line in output.lines() {
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 278359cb08e..1df34323535 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -331,115 +331,6 @@ fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
     })
 }
 
-/// Copied from `std::path::absolute` until it stabilizes.
-///
-/// FIXME: this shouldn't exist.
-pub(crate) fn absolute(path: &Path) -> PathBuf {
-    if path.as_os_str().is_empty() {
-        panic!("can't make empty path absolute");
-    }
-    #[cfg(unix)]
-    {
-        t!(absolute_unix(path), format!("could not make path absolute: {}", path.display()))
-    }
-    #[cfg(windows)]
-    {
-        t!(absolute_windows(path), format!("could not make path absolute: {}", path.display()))
-    }
-    #[cfg(not(any(unix, windows)))]
-    {
-        println!("WARNING: bootstrap is not supported on non-unix platforms");
-        t!(std::fs::canonicalize(t!(std::env::current_dir()))).join(path)
-    }
-}
-
-#[cfg(unix)]
-/// Make a POSIX path absolute without changing its semantics.
-fn absolute_unix(path: &Path) -> io::Result<PathBuf> {
-    // This is mostly a wrapper around collecting `Path::components`, with
-    // exceptions made where this conflicts with the POSIX specification.
-    // See 4.13 Pathname Resolution, IEEE Std 1003.1-2017
-    // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
-
-    use std::os::unix::prelude::OsStrExt;
-    let mut components = path.components();
-    let path_os = path.as_os_str().as_bytes();
-
-    let mut normalized = if path.is_absolute() {
-        // "If a pathname begins with two successive <slash> characters, the
-        // first component following the leading <slash> characters may be
-        // interpreted in an implementation-defined manner, although more than
-        // two leading <slash> characters shall be treated as a single <slash>
-        // character."
-        if path_os.starts_with(b"//") && !path_os.starts_with(b"///") {
-            components.next();
-            PathBuf::from("//")
-        } else {
-            PathBuf::new()
-        }
-    } else {
-        env::current_dir()?
-    };
-    normalized.extend(components);
-
-    // "Interfaces using pathname resolution may specify additional constraints
-    // when a pathname that does not name an existing directory contains at
-    // least one non- <slash> character and contains one or more trailing
-    // <slash> characters".
-    // A trailing <slash> is also meaningful if "a symbolic link is
-    // encountered during pathname resolution".
-
-    if path_os.ends_with(b"/") {
-        normalized.push("");
-    }
-
-    Ok(normalized)
-}
-
-#[cfg(windows)]
-fn absolute_windows(path: &std::path::Path) -> std::io::Result<std::path::PathBuf> {
-    use std::ffi::OsString;
-    use std::io::Error;
-    use std::os::windows::ffi::{OsStrExt, OsStringExt};
-    use std::ptr::null_mut;
-    #[link(name = "kernel32")]
-    extern "system" {
-        fn GetFullPathNameW(
-            lpFileName: *const u16,
-            nBufferLength: u32,
-            lpBuffer: *mut u16,
-            lpFilePart: *mut *const u16,
-        ) -> u32;
-    }
-
-    unsafe {
-        // encode the path as UTF-16
-        let path: Vec<u16> = path.as_os_str().encode_wide().chain([0]).collect();
-        let mut buffer = Vec::new();
-        // Loop until either success or failure.
-        loop {
-            // Try to get the absolute path
-            let len = GetFullPathNameW(
-                path.as_ptr(),
-                buffer.len().try_into().unwrap(),
-                buffer.as_mut_ptr(),
-                null_mut(),
-            );
-            match len as usize {
-                // Failure
-                0 => return Err(Error::last_os_error()),
-                // Buffer is too small, resize.
-                len if len > buffer.len() => buffer.resize(len, 0),
-                // Success!
-                len => {
-                    buffer.truncate(len);
-                    return Ok(OsString::from_wide(&buffer).into());
-                }
-            }
-        }
-    }
-}
-
 /// Adapted from <https://github.com/llvm/llvm-project/blob/782e91224601e461c019e0a4573bbccc6094fbcd/llvm/cmake/modules/HandleLLVMOptions.cmake#L1058-L1079>
 ///
 /// When `clang-cl` is used with instrumentation, we need to add clang's runtime library resource
diff --git a/src/bootstrap/src/utils/helpers/tests.rs b/src/bootstrap/src/utils/helpers/tests.rs
index 9cfaa3eb67b..2ab3952ae5a 100644
--- a/src/bootstrap/src/utils/helpers/tests.rs
+++ b/src/bootstrap/src/utils/helpers/tests.rs
@@ -25,27 +25,6 @@ fn test_make() {
     }
 }
 
-#[cfg(unix)]
-#[test]
-fn test_absolute_unix() {
-    use crate::utils::helpers::absolute_unix;
-
-    // Test an absolute path
-    let path = PathBuf::from("/home/user/file.txt");
-    assert_eq!(absolute_unix(&path).unwrap(), PathBuf::from("/home/user/file.txt"));
-
-    // Test an absolute path with double leading slashes
-    let path = PathBuf::from("//root//file.txt");
-    assert_eq!(absolute_unix(&path).unwrap(), PathBuf::from("//root/file.txt"));
-
-    // Test a relative path
-    let path = PathBuf::from("relative/path");
-    assert_eq!(
-        absolute_unix(&path).unwrap(),
-        std::env::current_dir().unwrap().join("relative/path")
-    );
-}
-
 #[test]
 fn test_beta_rev_parsing() {
     // single digit revision
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile
index d228dfc87eb..a944f370c6b 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-integration/Dockerfile
@@ -26,27 +26,27 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 # Duplicated in dist-various-2 Dockerfile.
 # FIXME: Move to canonical triple
 ENV \
-    AR_x86_64_fuchsia=x86_64-unknown-fuchsia-ar \
-    CC_x86_64_fuchsia=x86_64-unknown-fuchsia-clang \
-    CFLAGS_x86_64_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
-    CXX_x86_64_fuchsia=x86_64-unknown-fuchsia-clang++ \
-    CXXFLAGS_x86_64_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
-    LDFLAGS_x86_64_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -L/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/lib"
+    AR_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-ar \
+    CC_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang \
+    CFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
+    CXX_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang++ \
+    CXXFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -I/usr/local/core-linux-amd64-fuchsia-sdk/pkg/fdio/include" \
+    LDFLAGS_x86_64_unknown_fuchsia="--target=x86_64-unknown-fuchsia --sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot -L/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/lib"
 
 WORKDIR /tmp
 COPY scripts/shared.sh /tmp/
 COPY scripts/build-fuchsia-toolchain.sh /tmp/
 RUN /tmp/build-fuchsia-toolchain.sh
 
-ENV CARGO_TARGET_X86_64_FUCHSIA_AR /usr/local/bin/llvm-ar
-ENV CARGO_TARGET_X86_64_FUCHSIA_RUSTFLAGS \
+ENV CARGO_TARGET_X86_64_UNKNOWN_FUCHSIA_AR /usr/local/bin/llvm-ar
+ENV CARGO_TARGET_X86_64_UNKNOWN_FUCHSIA_RUSTFLAGS \
   -C panic=abort \
   -C force-unwind-tables=yes \
   -C link-arg=--sysroot=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot \
   -Lnative=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/sysroot/lib \
   -Lnative=/usr/local/core-linux-amd64-fuchsia-sdk/arch/x64/lib
 
-ENV TARGETS=x86_64-fuchsia
+ENV TARGETS=x86_64-unknown-fuchsia
 ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnu
 ENV TARGETS=$TARGETS,wasm32-unknown-unknown
 
@@ -69,11 +69,11 @@ ENV RUST_CONFIGURE_ARGS \
   --llvm-libunwind=in-tree \
   --enable-extended \
   --disable-docs \
-  --set target.x86_64-fuchsia.cc=/usr/local/bin/clang \
-  --set target.x86_64-fuchsia.cxx=/usr/local/bin/clang++ \
-  --set target.x86_64-fuchsia.ar=/usr/local/bin/llvm-ar \
-  --set target.x86_64-fuchsia.ranlib=/usr/local/bin/llvm-ranlib \
-  --set target.x86_64-fuchsia.linker=/usr/local/bin/ld.lld
+  --set target.x86_64-unknown-fuchsia.cc=/usr/local/bin/clang \
+  --set target.x86_64-unknown-fuchsia.cxx=/usr/local/bin/clang++ \
+  --set target.x86_64-unknown-fuchsia.ar=/usr/local/bin/llvm-ar \
+  --set target.x86_64-unknown-fuchsia.ranlib=/usr/local/bin/llvm-ranlib \
+  --set target.x86_64-unknown-fuchsia.linker=/usr/local/bin/ld.lld
 ENV SCRIPT \
     python3 ../x.py install --target $TARGETS compiler/rustc library/std clippy && \
     bash ../src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh b/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
index 913a0b0c09c..2bb1d0a6338 100755
--- a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh
@@ -35,7 +35,7 @@ PICK_REFS=()
 # commit hash of fuchsia.git and some other repos in the "monorepo" checkout, in
 # addition to versions of prebuilts. It should be bumped regularly by the
 # Fuchsia team – we aim for every 1-2 months.
-INTEGRATION_SHA=1011e3298775ee7cdf6f6dc73e808d6a86e33bd6
+INTEGRATION_SHA=737ebdd83afa47b742ca8325fad0176952fcefbd
 
 checkout=fuchsia
 jiri=.jiri_root/bin/jiri
diff --git a/src/ci/docker/scripts/build-fuchsia-toolchain.sh b/src/ci/docker/scripts/build-fuchsia-toolchain.sh
index 7a0d4fcffc1..027d412d250 100755
--- a/src/ci/docker/scripts/build-fuchsia-toolchain.sh
+++ b/src/ci/docker/scripts/build-fuchsia-toolchain.sh
@@ -4,13 +4,13 @@ set -ex
 source shared.sh
 
 FUCHSIA_SDK_URL=https://chrome-infra-packages.appspot.com/dl/fuchsia/sdk/core/linux-amd64
-FUCHSIA_SDK_ID=version:20.20240412.3.1
-FUCHSIA_SDK_SHA256=cc52f3497487dd813c89d9316e6967efcea89c7759edccf3e40fcf3662e53f19
+FUCHSIA_SDK_ID=version:21.20240610.2.1
+FUCHSIA_SDK_SHA256=2d2d057fc3f0404197cced2200f88cbcdaaf5fbf6475955045091f8676791ce7
 FUCHSIA_SDK_USR_DIR=/usr/local/core-linux-amd64-fuchsia-sdk
 CLANG_DOWNLOAD_URL=\
 https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/linux-amd64
-CLANG_DOWNLOAD_ID=git_revision:c777c011a709dffd4fa5e79cad7947b7c3405d02
-CLANG_DOWNLOAD_SHA256=779167422ad73c292f049dcea5569f84577af9292189ed2749518b966a4d0844
+CLANG_DOWNLOAD_ID=git_revision:3809e20afc68d7d03821f0ec59b928dcf9befbf4
+CLANG_DOWNLOAD_SHA256=3c2c442b61cd9e8f1b567738f6d53cffe11b3fc820e7dae87a82a0859be8f204
 
 install_clang() {
   mkdir -p clang_download
diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py
index 4f504341d52..d791550a8db 100755
--- a/src/ci/docker/scripts/fuchsia-test-runner.py
+++ b/src/ci/docker/scripts/fuchsia-test-runner.py
@@ -286,7 +286,7 @@ class TestEnvironment:
         # Look up the product bundle transfer manifest.
         self.log_info("Looking up the product bundle transfer manifest...")
         product_name = "minimal." + self.triple_to_arch(self.target)
-        fuchsia_version = "20.20240412.3.1"
+        fuchsia_version = "21.20240610.2.1"
 
         out = self.check_output(
             [
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 010e1b8fd51..4366a92fbcd 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -390,9 +390,7 @@ auto:
   - image: x86_64-mingw
     env:
       SCRIPT: make ci-mingw
-      RUST_CONFIGURE_ARGS: >-
-        --build=x86_64-pc-windows-gnu
-        --enable-profiler
+      RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
       # We are intentionally allowing an old toolchain on this builder (and that's
       # incompatible with LLVM downloads today).
       NO_DOWNLOAD_CI_LLVM: 1
@@ -440,7 +438,6 @@ auto:
       RUST_CONFIGURE_ARGS: >-
         --build=i686-pc-windows-gnu
         --enable-full-tools
-        --enable-profiler
       # We are intentionally allowing an old toolchain on this builder (and that's
       # incompatible with LLVM downloads today).
       NO_DOWNLOAD_CI_LLVM: 1
@@ -454,7 +451,6 @@ auto:
       RUST_CONFIGURE_ARGS: >-
         --build=x86_64-pc-windows-gnu
         --enable-full-tools
-        --enable-profiler
       # We are intentionally allowing an old toolchain on this builder (and that's
       # incompatible with LLVM downloads today).
       NO_DOWNLOAD_CI_LLVM: 1
diff --git a/src/doc/rustc/src/check-cfg.md b/src/doc/rustc/src/check-cfg.md
index 8e39adaa438..dfc4871b924 100644
--- a/src/doc/rustc/src/check-cfg.md
+++ b/src/doc/rustc/src/check-cfg.md
@@ -11,8 +11,8 @@ development process.
 In order to accomplish that goal, `rustc` accepts the `--check-cfg` flag, which specifies
 whether to check conditions and how to check them.
 
-> **Note:** No implicit expectation is added when using `--cfg`. Users are expected to
-pass all expected names and values using the _check cfg specification_.
+> **Note:** For interacting with this through Cargo,
+see [Cargo Specifics](check-cfg/cargo-specifics.md) page.
 
 [^reachable]: `rustc` promises to at least check reachable `#[cfg]`, and while non-reachable
 `#[cfg]` are not currently checked, they may well be checked in the future without it being a
@@ -23,6 +23,9 @@ breaking change.
 To specify expected names and values, the _check cfg specification_ provides the `cfg(...)`
 option which enables specifying for an expected config name and it's expected values.
 
+> **Note:** No implicit expectation is added when using `--cfg`. Users are expected to
+pass all expected names and values using the _check cfg specification_.
+
 It has this basic form:
 
 ```bash
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index c672cff7452..e55bb3bd155 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -259,7 +259,7 @@ target | std | host | notes
 [`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD
 [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD
 `aarch64-unknown-redox` | ? |  | ARM64 Redox OS
-`aarch64-uwp-windows-msvc` | ? |  |
+`aarch64-uwp-windows-msvc` | ✓ |  |
 `aarch64-wrs-vxworks` | ? |  |
 `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI)
 `aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian)
@@ -300,8 +300,8 @@ target | std | host | notes
 [`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-uwp-windows-gnu` | ✓ |  | [^x86_32-floats-return-ABI]
+`i686-uwp-windows-msvc` | ✓ |  | [^x86_32-floats-return-ABI]
 [`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ |   | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
 `i686-wrs-vxworks` | ? |  | [^x86_32-floats-return-ABI]
 [`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | ? |  | LoongArch64 Linux (LP64D ABI) with musl 1.2.3
@@ -362,7 +362,7 @@ target | std | host | notes
 [`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64
 [`thumbv4t-none-eabi`](platform-support/armv4t-none-eabi.md) | * |  | Thumb-mode Bare Armv4T
 [`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * |  | Thumb-mode Bare Armv5TE
-`thumbv7a-pc-windows-msvc` | ? |  |
+`thumbv7a-pc-windows-msvc` | ✓ |  |
 `thumbv7a-uwp-windows-msvc` | ✓ |  |
 `thumbv7neon-unknown-linux-musleabihf` | ? |  | Thumb2-mode Armv7-A Linux with NEON, musl 1.2.3
 [`wasm32-wasip2`](platform-support/wasm32-wasip2.md) | ✓ |  | WebAssembly
diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md
index 519e9cc7cc4..2b3d15e93c8 100644
--- a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md
+++ b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md
@@ -150,3 +150,15 @@ or another engine that supports `wasi-threads` is installed and can be found in
 5. Apply such [a change](https://github.com/g0djan/rust/compare/godjan/wasi-threads...g0djan:rust:godjan/wasi-run-ui-tests?expand=1) with an engine from the step 1.
 6. Run `./x.py test --target wasm32-wasip1-threads tests/ui` and save the list of failed tests.
 7. For both lists of failed tests run `cat list | sort > sorted_list` and compare it with `diff sorted_list1 sorted_list2`.
+
+## Conditionally compiling code
+
+It's recommended to conditionally compile code for this target with:
+
+```text
+#[cfg(all(target_os = "wasi", target_env = "p1", target_feature = "atomics"))]
+```
+
+Prior to Rust 1.80 the `target_env = "p1"` key was not set. Currently the
+`target_feature = "atomics"` is Nightly-only. Note that the precise `#[cfg]`
+necessary to detect this target may change as the target becomes more stable.
diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md
index 4faa1988735..fb70bbdc2b4 100644
--- a/src/doc/rustc/src/platform-support/wasm32-wasip1.md
+++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md
@@ -121,3 +121,14 @@ can be tested locally, for example, with:
 ```text
 ./x.py test --target wasm32-wasip1 tests/ui
 ```
+
+## Conditionally compiling code
+
+It's recommended to conditionally compile code for this target with:
+
+```text
+#[cfg(all(target_os = "wasi", target_env = "p1"))]
+```
+
+Note that the `target_env = "p1"` condition first appeared in Rust 1.80. Prior
+to Rust 1.80 the `target_env` condition was not set.
diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip2.md b/src/doc/rustc/src/platform-support/wasm32-wasip2.md
index a385600cc22..1e53fbc178e 100644
--- a/src/doc/rustc/src/platform-support/wasm32-wasip2.md
+++ b/src/doc/rustc/src/platform-support/wasm32-wasip2.md
@@ -53,3 +53,11 @@ This target is not tested in CI at this time. Locally it can be tested with a
 ```text
 ./x.py test --target wasm32-wasip2 tests/ui
 ```
+
+## Conditionally compiling code
+
+It's recommended to conditionally compile code for this target with:
+
+```text
+#[cfg(all(target_os = "wasi", target_env = "p2"))]
+```
diff --git a/src/stage0 b/src/stage0
index ed88549e698..f36010fa4b4 100644
--- a/src/stage0
+++ b/src/stage0
@@ -14,434 +14,434 @@ nightly_branch=master
 # All changes below this comment will be overridden the next time the
 # tool is executed.
             
-compiler_date=2024-05-26
+compiler_date=2024-06-11
 compiler_version=beta
-rustfmt_date=2024-05-29
+rustfmt_date=2024-06-11
 rustfmt_version=nightly
 
-dist/2024-05-26/rustc-beta-aarch64-apple-darwin.tar.gz=b899079e4c3541762db909b2ec2fd73ca10c26874308831346770c35be29d6e4
-dist/2024-05-26/rustc-beta-aarch64-apple-darwin.tar.xz=2370613f7b60baee5dfccb0adf1586ec960d8590863e2be1571e5efe10f7eaf2
-dist/2024-05-26/rustc-beta-i686-pc-windows-msvc.tar.gz=d8976f398b8fdc3a43894cdd783c83bf0d7db33d6d059dd5387dd7a2840c70b6
-dist/2024-05-26/rustc-beta-i686-pc-windows-msvc.tar.xz=1eeb53dfc82b902e5f9e11bb631b0c2812c7f81a84c1023c69903debb6fff4da
-dist/2024-05-26/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=512c74d27fc57bddaf8ec8865afc1ec3dc37106e07a9ef60921b2f852c16ef88
-dist/2024-05-26/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=48b01607a0316817505d4286ce075dacdb38fc170aae7e8b4daa7b75272916f9
-dist/2024-05-26/rustc-beta-aarch64-pc-windows-msvc.tar.gz=f9c8260ce005ffb02213b23530abc8bda5f74104ede11202a6b379e1cead640c
-dist/2024-05-26/rustc-beta-aarch64-pc-windows-msvc.tar.xz=567989038185ddbf00d5ef5f7bde9934cce7c8d932db81c3c635283512d8983c
-dist/2024-05-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=9fe58cd58e0f758d338d1ee427186f2ac0b644ef9decf457d4b6c0f67df475e4
-dist/2024-05-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=c589495fc21e7bfe3ff19736ba79ff78bc8899bc95f714e93ae4d410a704b0c8
-dist/2024-05-26/rustc-beta-x86_64-unknown-freebsd.tar.gz=4d9206a4361ed0d400decc68b2d908447de0390801bb5ef49885b42e31fc8b07
-dist/2024-05-26/rustc-beta-x86_64-unknown-freebsd.tar.xz=215b0f6ce7885bc2fa8c5d8352e4c5b9bfddb6d92f398ece00ede1bb693c92bc
-dist/2024-05-26/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=a7f32c585c191b194a271c3baec3e81d8daac6a107ab5fada0b94e6c31dc295a
-dist/2024-05-26/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=ea7a5b798e251fea669265bb66d8e20889e1fa0dd71c5cbb7caf9eb187462fa4
-dist/2024-05-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=44cb994404abeb3b9f873cacae90a208b3243a98d6c7366a7f211a81180eb3af
-dist/2024-05-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=49cdde9184c78d03a3fc1af955c0cb37ab290f6d4f0f3a71ce37903df389f804
-dist/2024-05-26/rustc-beta-x86_64-pc-windows-gnu.tar.gz=fe9aebf5129393a8525c9be7fb3120b61a346028d23a19727dac37bb282d4731
-dist/2024-05-26/rustc-beta-x86_64-pc-windows-gnu.tar.xz=760ea53130788d624e3cbee11ade75b38abeaa10701e8205ae5cd8781f54d5f4
-dist/2024-05-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=0a7412f1c722cf74736120b9fce90e4f432da4a51f2d7a53320362e7e829f661
-dist/2024-05-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=e82df323b5544ca55a23db09fd23dff72cacc575dd25e7e056033ff2ca5ba3e3
-dist/2024-05-26/rustc-beta-aarch64-unknown-linux-musl.tar.gz=9b9e7fe38a6e1fe44e629a8523d6b3acdf199b2bb94e7cb2bc9dc4858faf2022
-dist/2024-05-26/rustc-beta-aarch64-unknown-linux-musl.tar.xz=cf1c8a2e68d22d078b69fcffa64dafa9d3b54ad4983b485368dc297c4109645e
-dist/2024-05-26/rustc-beta-x86_64-pc-windows-msvc.tar.gz=9069c6b50e3842e03ed13cdd39513a17ae4251fb47893c02c58b5f4704b4c9ff
-dist/2024-05-26/rustc-beta-x86_64-pc-windows-msvc.tar.xz=6a315e496629f9b57fa9b82e6cb705cc7aacde690b3619c81dfa57382bdb64ac
-dist/2024-05-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=c31a1bf28a4d2c4470032e893b043c25c349ff07facda18587a2eb76cff648e4
-dist/2024-05-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=36da69f87daec24b9810ece65d51abc41128ee1874be14bbc46f74c09a3b20f2
-dist/2024-05-26/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=6b9aab90326c804aeb88bcfbc8055438bae0fb721b9d8b1a64b062836ba9efa4
-dist/2024-05-26/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=d0aeed09775c58a17649c42e0b641f20c44479056db43116ad452e771a88ddfc
-dist/2024-05-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=4b1293f35b04a2f9e01e9752b3e8a5b61aa2375930fa72a8c3d04f52f4fbcad3
-dist/2024-05-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=06a653d79b84399798df9f3e636160f56c774a1593e7ad9a57f6e35a3d54fa77
-dist/2024-05-26/rustc-beta-x86_64-unknown-illumos.tar.gz=827865d233d702017b592d6c46954b54f18ffb758f79bfedf59fb535168b9b18
-dist/2024-05-26/rustc-beta-x86_64-unknown-illumos.tar.xz=4258e58b103e5a579e57059bdb1f61fa8e54854c80340888a11a2e81040bfc32
-dist/2024-05-26/rustc-beta-x86_64-unknown-linux-musl.tar.gz=be7f3f7485cfb378e105f8ea09b4a1fb6b78cd68e2a5b7e1cc354c6abfa55953
-dist/2024-05-26/rustc-beta-x86_64-unknown-linux-musl.tar.xz=ee6c02cdf6baa8cbadf8dc53a075582db428a0b149dec7c0f70bb182f49df79a
-dist/2024-05-26/rustc-beta-s390x-unknown-linux-gnu.tar.gz=cbf5cc045498ade9d1051de75b127e78d7986f5dee9ca39586e9e9e3bfe066d2
-dist/2024-05-26/rustc-beta-s390x-unknown-linux-gnu.tar.xz=8803daf2ffadd1c76f7591dd765bccb8630336c00a9419f4e9e9a2fc882cd1c7
-dist/2024-05-26/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=9546048a0d5022d19770398f27e8c51cee4fd5879ec012709b8683a5ea9acd62
-dist/2024-05-26/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=5da5076d933127e616a289f6ba9bdea41f0f8f2604436c440a12f7007e5bee79
-dist/2024-05-26/rustc-beta-i686-unknown-linux-gnu.tar.gz=2f20e8666a768b32913a61e49f1774ad0fd616af874eab37b8fcff5344479806
-dist/2024-05-26/rustc-beta-i686-unknown-linux-gnu.tar.xz=1ac7c922764f406db986050f526f5b4490d789978cafad00db668cb4128d64da
-dist/2024-05-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=d685e5d7efd8f312f22c0d1c132618f6112e528a51e451fa3279e71d66b46a4d
-dist/2024-05-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=bb378be1b0bd6187cca16f5142f6d516790b8acc330f64af4371dd15751aff4f
-dist/2024-05-26/rustc-beta-i686-pc-windows-gnu.tar.gz=5a628010b3fd859aae9b75086ad299fdee3159c6f7b8c5b93b24f56f392af0c6
-dist/2024-05-26/rustc-beta-i686-pc-windows-gnu.tar.xz=7546c4cbbc9c33dbed8895608116393855d73b99987e5e1fb2e6a8e88b0ed3cf
-dist/2024-05-26/rustc-beta-x86_64-unknown-netbsd.tar.gz=5c10adf9a0d2b917d05e285b8754925d324a43335639d6caeae6bc815f70a852
-dist/2024-05-26/rustc-beta-x86_64-unknown-netbsd.tar.xz=49015adf19be4847dc5de824718a07f741b921a6c4f5565ae9d57b2ff24977c3
-dist/2024-05-26/rustc-beta-x86_64-apple-darwin.tar.gz=399a4751cf0f1015cd67b312f89a3b57f1a2e0b2b7052aa943dd87ff88e10e2c
-dist/2024-05-26/rustc-beta-x86_64-apple-darwin.tar.xz=214178058be3e0d305838e1cc0c4de7d7a6aaeb3df1c8de451aa598bab46bc13
-dist/2024-05-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=fc8ba79857b1f1d8d27049e3322db0e9dd8e8f55e9899a7651826d29d18ccbd8
-dist/2024-05-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=d83f291dd371fec862e71e382db853d3547c1f8fc5cf475765e91054ffe4b40d
-dist/2024-05-26/rust-std-beta-i686-pc-windows-msvc.tar.gz=4e831a551c6903d6995162c7e4ca35dcb421e50659a52e33b5d82a071ffc9c6d
-dist/2024-05-26/rust-std-beta-i686-pc-windows-msvc.tar.xz=4944a6c8bd5716811eaa34d932899cb7a7b1ef16def784663867921357b98b89
-dist/2024-05-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=25cf208ccd2bfd922d43f7d5e6000daf523fdea3c436795a641af43ca5af3c3e
-dist/2024-05-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=846bcd9b52a0c267bc0f5870dde2b672f002df8397d31ec4d55ef407ac9f7097
-dist/2024-05-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=2043dc32a5df5da4c289119d70896b88ec527ca72509eafbe39592bf18451c2d
-dist/2024-05-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=20bffebf6414d6c5eb357280a301a7d7b6e2fe778423403aaa9106ce16ead498
-dist/2024-05-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=a67464ceea45dd3bfd20156091e1ac070ad1f921f70cb8c11c0a5945e857cc40
-dist/2024-05-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=b8518464ed51eb07fe9874dd38eb81004a58a994e95f1062ec5ab01db0d7cbd1
-dist/2024-05-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=398e2a8c2c1ff8e19f810513f1d4105c57b509290393d346ff56a78c58419c54
-dist/2024-05-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=3cb98ea534755f69a050df188c4b0b4282e5778609a8df6bd7dc9a467966344b
-dist/2024-05-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=aaf44990f5ea7055c911d414e7ba74ec6457d347648b13eba087ef87030fef34
-dist/2024-05-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=32aa99692fe79711fa637b4f222fc5bcce3673845fee99692ef2cdc94acd033a
-dist/2024-05-26/rust-std-beta-wasm32-wasip1.tar.gz=7711323738d70039ac2dcc39812610464b5d06f4a24db127143964424f07692c
-dist/2024-05-26/rust-std-beta-wasm32-wasip1.tar.xz=413fc4b5480274ede6fc389d2563655cea0d438baee6b4f6c0d8757a4179d8e3
-dist/2024-05-26/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=b46cc9fab639276eb86be72746f3e484020014041cadff276da79f2c62b16376
-dist/2024-05-26/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=f4241afe5137e9a28fefd20115154dedfdd0db6d62e70e8b447a9999d238bf98
-dist/2024-05-26/rust-std-beta-x86_64-unknown-illumos.tar.gz=7b963148cf41ec6c918448d71929190474ac18b4770581e8ca41c9aa06d0d548
-dist/2024-05-26/rust-std-beta-x86_64-unknown-illumos.tar.xz=11d363e7e1325daa6161206f659b2da1cb64e1a6a49bedea2afd0993692e0110
-dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=2846fb587bc1e04ebcc15c4401eca652ec4a9a3ee07c4c8901ba8f0dec8bd307
-dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=c9aba9b367861d861b7c21969c64ed7c56db27b295b79498f817d28afe6258d6
-dist/2024-05-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=dccd96c4f24fd935c04f29b1ac10f936ee92b9c8ecc71ca494d60555a3541a80
-dist/2024-05-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=6b22b9c8526b4c5e25e7b6583df7c626388d3ff177e1f7b22c57ffec07bdcde2
-dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=d85b7dc13e34927030b76f0578dfa8da22025b914e8f024e611a05f55f2ff60c
-dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=327beab489c253a802259760afc82ac337fe2addd2f26877610e1a2ca8a20c47
-dist/2024-05-26/rust-std-beta-thumbv7m-none-eabi.tar.gz=3b78f640fbc54016515b15fe5eba6c3d3f679582f33fbbd7656a9514bf04de25
-dist/2024-05-26/rust-std-beta-thumbv7m-none-eabi.tar.xz=f8fa181333351d8673b938b0395be2632110cdc6ad40f2b2bbc254643f5047df
-dist/2024-05-26/rust-std-beta-wasm32-wasi.tar.gz=fa1f7cbf6784e9d1487a88f1942a223056315d45968d1f23ac262d81e6a3a1ca
-dist/2024-05-26/rust-std-beta-wasm32-wasi.tar.xz=e13ce9734bebabf39839b27310c4a97c1553a34988bb2de69c9f4ad38592da48
-dist/2024-05-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=93c06f87883dd3b8abc504ee10c0d46ad702ec7266f13996a8e8dbbdcc6adfb8
-dist/2024-05-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=f785f3f53f47cd70cb3b1e04f46ae56f937814a895d132db470e21d9eb3f0eba
-dist/2024-05-26/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=7bdb39efb763f3272550f229d97145515e73c9510b54c53246436c068fa4b98e
-dist/2024-05-26/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=33960973887d3e4dc5f72550dd636c28bf6d5a9319c23c2ea1a14bb4c33eccf3
-dist/2024-05-26/rust-std-beta-x86_64-unknown-redox.tar.gz=16194e687a77d25e67d575f4e8a202d070771b6e51fb261d3a4673978b4c2a76
-dist/2024-05-26/rust-std-beta-x86_64-unknown-redox.tar.xz=0ce66624b0d2c1e476c730fc96718e8ff52780f8d5d6968e39a30cb9bd906b22
-dist/2024-05-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=01555fb03930106ae6be0c4bbc185a5f8cbec27375aedf4201529ed6856ac02d
-dist/2024-05-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=3fa3ec9e478370a2874e7a47dcd84f714612b0eb05a8cbb6ff9379250e750278
-dist/2024-05-26/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=b84dc461e790fdcbf8084d2adb42398e51f162416522f2901f1d82d07915ee70
-dist/2024-05-26/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=8792ac895cd373b3fa8f4913e5a1b098d97ca1ca8f71beb15ca614111ea9bbbc
-dist/2024-05-26/rust-std-beta-i686-unknown-linux-musl.tar.gz=5133f49db7ba73e900d8431838cbc12a5a276ff0f95fcd10a5791d5b4ef9b714
-dist/2024-05-26/rust-std-beta-i686-unknown-linux-musl.tar.xz=607131ca6ed1feab6289035445be404060281d3b1f720f40eb985b0341d2f2cd
-dist/2024-05-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=aa8ba338e80abadf4383c34a686b1fa331e31a4cf0bb067576288f265a86aac3
-dist/2024-05-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=46fdbdffd351933cc1bebeaee3e2b26bee28c2356a9b337a4472346ee6cac9c9
-dist/2024-05-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=dbbd9d0f3b4ecd1cac5d9c6ee62e5e099fd5f05dd8703c9035d5280b38e3a601
-dist/2024-05-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=60edbb54ab8f1b982057a79063e6cf0fe5e4041c6306251e54cfca7014de84c9
-dist/2024-05-26/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=7ab82e3ae01242203d9d72b7d3c01c3bd70ef4d9ddcc86feaf025ae120558dad
-dist/2024-05-26/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=148500507545bc8addedd8fe2f1df836c9aba894afb06bcb6f8a1258d9590999
-dist/2024-05-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=5b9d7ca3c0b76a23ac412aae8421750b144c9e9fdacdb34a637a6f5f353d9bc9
-dist/2024-05-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=7c856cc68e7d0b972258cc8f37731e72b9dd7eb88fc143fdea5220f4f60f6db0
-dist/2024-05-26/rust-std-beta-x86_64-unknown-uefi.tar.gz=5ddf07fcfd6e2cf17104f26fdfbaed3fa9055708b0ca63b1b0e675df8690b04f
-dist/2024-05-26/rust-std-beta-x86_64-unknown-uefi.tar.xz=bbe32665b93efc6cf2fc5c28af448f85efa3810734a121033a92eac06b8414b1
-dist/2024-05-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=cde6a9cfb0aeced8be963fd7faa0456d506b6d693e84afd6a5423ac37a69d944
-dist/2024-05-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=026bdb53279ebb5f6a50f581b12ca2aa2c4de9655e786a3a17a606b2db4ff49d
-dist/2024-05-26/rust-std-beta-i686-linux-android.tar.gz=8a21fb5147985941fc9eb8581e9970997240d8af19d6348e8b1b4296ecbea47c
-dist/2024-05-26/rust-std-beta-i686-linux-android.tar.xz=ac5fd73f5a6ddc8c0644b32626c0bc53c885788e3e9fe331e2b598b86f0daebd
-dist/2024-05-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=1f791a99dbed0179a1ea7b36fd13128c5c05d08489c8baa0ce660b6bbaf42a05
-dist/2024-05-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=92f8573bb786beb5cc74f3842a57d2725409ca7c2b12ed64f7ee543bb3ee477a
-dist/2024-05-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=faf08553004fda1e2215116221cf35c7ea4a9f9c51b5bbe4bf16c99235d571de
-dist/2024-05-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=81a5f8c273f7403091781bd7ad110fe7103392bef4350bba0e029385bc0ce0a7
-dist/2024-05-26/rust-std-beta-x86_64-apple-darwin.tar.gz=2a2bf00ca629cd0c7bdcc7333456f5766db2a805cba1c88a1a89cfe76a0f5d09
-dist/2024-05-26/rust-std-beta-x86_64-apple-darwin.tar.xz=b3ac3042484e972962a3e67b4f9251380135d6cf07b9589c5e3e94b0dbdb70fb
-dist/2024-05-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=c1953526bed228077dd42be2e570d1276fcf04868e4c8d426d23e00037178617
-dist/2024-05-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=71310bef84016c25c949826121b8bf78eabac6d7c34b3397961ad39493df49c2
-dist/2024-05-26/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=d8fa9332e29f19b8b06dbafa2b6b13eb3479b9b28601372dabcee0cbb2a4d0ab
-dist/2024-05-26/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=84daea4b14a3eb2712120652ebb2c342e6a37f984f1512dfa3cbd3531fb5cf53
-dist/2024-05-26/rust-std-beta-armebv7r-none-eabihf.tar.gz=348822ddf1f918cf56e6b76cdcfd3c4d4f50fb8e45c8b8c803e639910150b044
-dist/2024-05-26/rust-std-beta-armebv7r-none-eabihf.tar.xz=0f26d6888811e8ce6f0324bc5b4cbd667fbd8771e3e42192410d15e1d45033d5
-dist/2024-05-26/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=42b49ef649da71c425b9de48812c23470638ac876f489f4c1c35ac116ba0d078
-dist/2024-05-26/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=1111d46b2f5ef019cfb894b1a330721ee6fa1cf19b6f3c1abd8f866f8a208b3c
-dist/2024-05-26/rust-std-beta-thumbv7em-none-eabi.tar.gz=4a41109968645be22ef1540037ac0a73789583eb250381d8431dfa6c8dd3a652
-dist/2024-05-26/rust-std-beta-thumbv7em-none-eabi.tar.xz=10007bd59e6cd60e924e472c19df1bda10bf6c60887ed91fb9874a7e596f9e72
-dist/2024-05-26/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=09d74fb8bd049910c60f585193af33fa51eab82dd2211030d71f3dcfba128a96
-dist/2024-05-26/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=2cdabc7be85304a7675fcebd53b8dd0e4183007fe0f81db3811df0d8bc712120
-dist/2024-05-26/rust-std-beta-x86_64-apple-ios.tar.gz=2061188c2361ce7b3a62a5bf45012aed708a8a86c2e5d1035a8c82b2ce868aa9
-dist/2024-05-26/rust-std-beta-x86_64-apple-ios.tar.xz=b6fd849acd590c2b853783b12b7b559395cc6698c6ab60d3b58a8475c809b9c6
-dist/2024-05-26/rust-std-beta-armv7r-none-eabihf.tar.gz=1915d8b728f8e37d7ede0da8cf2281676b970281c486d683f58d9bccfac2868e
-dist/2024-05-26/rust-std-beta-armv7r-none-eabihf.tar.xz=21323f2a4eb7d46924438d0cc341b5d4e35b1ddb5abb02604980b5b055449e40
-dist/2024-05-26/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=2f6ff815e3f4ed2913a27bb30c51c3992e60fa4d7d00a6ea8c648f19c9fd56bd
-dist/2024-05-26/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=ae6d85a4ee1a98084f3b95befb923ccb57eb42a05ef1fc9f4e5d6736a63edc09
-dist/2024-05-26/rust-std-beta-x86_64-linux-android.tar.gz=580b1f05fc5530fe0078e958b8740ac538ba1b2589e2c893a6b25f12fa4609f5
-dist/2024-05-26/rust-std-beta-x86_64-linux-android.tar.xz=8eccdb906d4f28404172d6e09dbe8a33a89cdf4dea168c446a3f38d719b63ec7
-dist/2024-05-26/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=91c10648eaa115ebb2436cf78031d86704a917c2641090c2fc30d3234f2ed316
-dist/2024-05-26/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=376e28b76c9b0fb590b7a7b3700debb4bd5878d861c144aa69502a0aaba2c9ba
-dist/2024-05-26/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=9a02c999175b39b1ae4a99a5556f42c89ce02b9c6e25688cfe573833256f9a0b
-dist/2024-05-26/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=5dbcb9a42313fcbec57d26877175320bde265a1c1c1f8a3415bb742b86810153
-dist/2024-05-26/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=df780a07a1322e981da7083938d755dbefe0a2fa00c6acbe5658469400b79d32
-dist/2024-05-26/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=611fe18a51c4d84b231d3cf9a2dc47913071698634b7b3c4c066b1e92ef5adee
-dist/2024-05-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=0f30d5e28ed599888e8125b3614070ef3da7d9b52442fd11e15993a84b678432
-dist/2024-05-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=7118728e4dfb3283f4f6ffdf0cb92e4f1dbee7a8d9ee79c2cb4cad99e90507f5
-dist/2024-05-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=f1f1a976de6ad212370887bc8079a0ce6b491ca9bad3e4e8d2ba06e4eafae2d3
-dist/2024-05-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=034a5cebd66cf8f6d9379a26744e14d7d7e681b9203589a090a0fa205296d58d
-dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=900ac2af2799139ea704e192f6709f364b736e31ce682e12ce2ba0471b01afa1
-dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=5883309a473fb227ed5c71b7f341fc6f5ff22657d089ba790fc80ac9afeb065b
-dist/2024-05-26/rust-std-beta-i586-unknown-linux-musl.tar.gz=da1637ebab43f0a7b6e64ba42d8e2d06f04c7c8eda4e8f80a6fa520832288dde
-dist/2024-05-26/rust-std-beta-i586-unknown-linux-musl.tar.xz=c80f46b0b5b4cd2e3ea67f4ab3df1ad4124fa6b425d598ca0b6656451a74ba44
-dist/2024-05-26/rust-std-beta-aarch64-unknown-uefi.tar.gz=f7d0413c0882917fd041704c692cf5cc5030660aa9f04ada91e5c3c3fe007c6c
-dist/2024-05-26/rust-std-beta-aarch64-unknown-uefi.tar.xz=ad84c695a7eb2dccee3d3560e2140fe19c6aee116fc5fc953ac944d630d3fd64
-dist/2024-05-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=d42f482f7c262cc9cd6f9bb5bc64019cc348c0ec552ac5b518bd92548018411a
-dist/2024-05-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=7589cab1072cecc50a9481e025e2f62f42975e60ba3e50fa6074e57e80c97257
-dist/2024-05-26/rust-std-beta-i686-unknown-uefi.tar.gz=85392042843c9653f1f6f643c0ba1af98ab0fd5a81cf1ddb7736415238cd5fa1
-dist/2024-05-26/rust-std-beta-i686-unknown-uefi.tar.xz=9cac1dafe8fc420c163fdb0ec089443dd4632077eaef73c459f3e8a9648fc6e5
-dist/2024-05-26/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=a2c33177e3a1d48542bd376eac44d4fc6320e58ed5b5ee1c5f58980301d7df49
-dist/2024-05-26/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=7183769937af0c9501b8fb71ce84a41562d9d773f4647d0d76d692fc0a623994
-dist/2024-05-26/rust-std-beta-armv7a-none-eabi.tar.gz=48e17ac14232f015425b46e1cfea19eea664cd224e0ec3e5b2ff58b82174b67a
-dist/2024-05-26/rust-std-beta-armv7a-none-eabi.tar.xz=e04323b38171e9c63a4cd1673a5d69a9faf6e415d69ba11e7da7f30bd77077ac
-dist/2024-05-26/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=2bc38de25271bd34c74a97b2f09133b4d3518911bd2d32deceab3e91f7554aed
-dist/2024-05-26/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=2aad6d3b0b86847dfb1e57394de95dcbfe799630b388933d09939d1e309df911
-dist/2024-05-26/rust-std-beta-x86_64-unknown-none.tar.gz=9de88c179553ec42bdf5e036a44318a442778396380c44387cac94658ae7a294
-dist/2024-05-26/rust-std-beta-x86_64-unknown-none.tar.xz=f526dabd3d11858320129ccabfb3e5d14249ea6db30ac882ab26ae628d91f81e
-dist/2024-05-26/rust-std-beta-armv7r-none-eabi.tar.gz=fa439d79673ad7a467dda9aa40524299880378d2a44a3338d038a6c6e6ec164c
-dist/2024-05-26/rust-std-beta-armv7r-none-eabi.tar.xz=e07e26bcb5bd8dc93a877d122568aa78d09f77e81a3c85538872ddea47f3b319
-dist/2024-05-26/rust-std-beta-i586-pc-windows-msvc.tar.gz=f703880c171e14a6748beadb64477e85716e1cf45f98c5342600ee850518ba60
-dist/2024-05-26/rust-std-beta-i586-pc-windows-msvc.tar.xz=17dbd60169c3f47aa031d58dcd4898032d1e4991df86ff64e684e833c717d453
-dist/2024-05-26/rust-std-beta-armebv7r-none-eabi.tar.gz=5e53e25483594947af7a2aa5f14b06d44e0eaa16a464a004cfe7b079da9d7847
-dist/2024-05-26/rust-std-beta-armebv7r-none-eabi.tar.xz=81da84696b4250ad653b29aa73e8dd70fb0db6b469d8895a1f6c587ef38b47eb
-dist/2024-05-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=d93918290043ba801c78f1d662ab847cd19002560fa6832176bb549cc51b0e8b
-dist/2024-05-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=46b81807b463ef523a2e522199b4cdff70b817ab45bac56d17b7cf40c2bdb908
-dist/2024-05-26/rust-std-beta-i686-unknown-linux-gnu.tar.gz=adc0fa2c9a8cc8b4204fbd0455ccb2f914ae5335d8f8f96dc3df2791cf85e625
-dist/2024-05-26/rust-std-beta-i686-unknown-linux-gnu.tar.xz=8d5531693ba346d36f89fa969826434a1583c60dd1bf61b055aff026cadcb82d
-dist/2024-05-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=01bd0ccbae4a301cd39eb92afda2f3a4d81276c17f8a3f48f9226a36fe4b6d31
-dist/2024-05-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=a07afdb285f1744ea75082d0a92f07333d5fd26ab84818a1bbb91ffab047998f
-dist/2024-05-26/rust-std-beta-aarch64-apple-darwin.tar.gz=333fb310bf7749b0fb81a4f0930d0db738e24098fd3b4b38d037686c713f7243
-dist/2024-05-26/rust-std-beta-aarch64-apple-darwin.tar.xz=aa720a70e396e872045fe5934444b0e1b1e4633f371dc781397192c42a970c22
-dist/2024-05-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=4949dc875777c799d1fa74db866d6492b25bf15a9383867f8272c3751b1bfd99
-dist/2024-05-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=40eb3bffd0ca0db7dcd330e01f28ba777807f0e2e514f65e3c2aedf19b72d61c
-dist/2024-05-26/rust-std-beta-loongarch64-unknown-none.tar.gz=0b719a0748343cea4f6e3fcd0dffc567de0e45eef6b8067259c5d8b61c7b8040
-dist/2024-05-26/rust-std-beta-loongarch64-unknown-none.tar.xz=e7cb82769b71b100a8453df764a231d1967e5ae41a39a0b974a31ecd6c348568
-dist/2024-05-26/rust-std-beta-aarch64-linux-android.tar.gz=9b85abd7488b16f323396e5158059104281319971933a0702055b1e508418395
-dist/2024-05-26/rust-std-beta-aarch64-linux-android.tar.xz=2164c9dd13043e16b5144670a3032adfe0e439b18a193ca22c4c6b6bab678577
-dist/2024-05-26/rust-std-beta-sparcv9-sun-solaris.tar.gz=ab9d4db4abb8057fa0e9d8cfe0d01921da5499d082402f6277e1f8ed75c32f23
-dist/2024-05-26/rust-std-beta-sparcv9-sun-solaris.tar.xz=43254c65450dde6de4ce2538b80100db01ca15632989a6ba7173b01f4acc89bc
-dist/2024-05-26/rust-std-beta-x86_64-unknown-netbsd.tar.gz=07c76a68e44cb9d6ba527d17dafdc0b51c9e2b51ab1c5dbbe8784d137609a4b5
-dist/2024-05-26/rust-std-beta-x86_64-unknown-netbsd.tar.xz=caf5dc8356c9fd34f13983f338e0d44fbec83358309a60b1d7520aaaddc4ff57
-dist/2024-05-26/rust-std-beta-i686-pc-windows-gnu.tar.gz=ca3561531a6054f2236a820c77b5ce109118f720a0e1ef850cb5dc8abfd1c8ce
-dist/2024-05-26/rust-std-beta-i686-pc-windows-gnu.tar.xz=955681b4b4f5b3bebee11c381b8c12a73ca7fedf4f4d80213be9035cfad722f1
-dist/2024-05-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=035483e893dc4e28689c8ddba80b0e12d4b6ff8c8075c8fbb72612edfb830d1a
-dist/2024-05-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=e6d4f6d00972fdf6f9c9faf4e8608d7f6eca23094623ddd9c6a08237f0721825
-dist/2024-05-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=02f9bb16b62f6b1a02787ad30877fe5b1676524ec868789044b82cb762cd96d3
-dist/2024-05-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=c54719d0e78d063c1aabc9253a3cb0bb5bc9a9b88bdd02829f004c183ef225ae
-dist/2024-05-26/rust-std-beta-arm-linux-androideabi.tar.gz=ab579d41fa31499c9ae0574194961d64065bbded4595c9809504826151d7ffb9
-dist/2024-05-26/rust-std-beta-arm-linux-androideabi.tar.xz=41f0ac3317212f46df64b0907487ced9b5c8e390f2d8a49f284ddf95a89c04b1
-dist/2024-05-26/rust-std-beta-i686-unknown-freebsd.tar.gz=cad37ef490a691de7b1649b94aea62af61a79d93e3f859fffaf5ccf63ca238f5
-dist/2024-05-26/rust-std-beta-i686-unknown-freebsd.tar.xz=f20be5c8c379fe9d2445eaf83fdb9b1df77117a93fa6ec0b97fbd0e5449f75bc
-dist/2024-05-26/rust-std-beta-armv7-linux-androideabi.tar.gz=58eb5e6155e8f4e598f7201ad46633afda0fbc3221fdf07c57ab7c644eed4140
-dist/2024-05-26/rust-std-beta-armv7-linux-androideabi.tar.xz=c2ee165302f135710ea2158d9592731cfdbb1c2d7f529ac1557b190826aae24d
-dist/2024-05-26/rust-std-beta-wasm32-unknown-emscripten.tar.gz=6268910518871d87012f8e77e31c3b525cb573f6697787b03c516e2a43846e45
-dist/2024-05-26/rust-std-beta-wasm32-unknown-emscripten.tar.xz=01cf5cd68bcd9a7f706ff1b266bc5bfb61b8b1230488b3352359ce1c604c5d36
-dist/2024-05-26/rust-std-beta-x86_64-unknown-freebsd.tar.gz=c3baafd66056b93943bde313b84b00f719fbb006045a7af869d1c0b77927ffc4
-dist/2024-05-26/rust-std-beta-x86_64-unknown-freebsd.tar.xz=7d846e6840553986ebe3f2a8dd526af5daeaad566f3b241e94c2d18dedabed85
-dist/2024-05-26/rust-std-beta-wasm32-wasip1-threads.tar.gz=b4de80001c585b3644116c7a4cc7ee6a00476058f84637c3ff49e8dfc5edcf1d
-dist/2024-05-26/rust-std-beta-wasm32-wasip1-threads.tar.xz=8facfbeb32902b094512c89dac44b94f437163a8b630adc485383045ec4bfd0d
-dist/2024-05-26/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=0b8a82fa80653cbd2c27237b7b696f4ddd37e0a2575fca29655fd36883193659
-dist/2024-05-26/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=ea9b3e6984605bd2606aa0456e5a9ecc4addd2880104cf5ddbb7fdb81673818f
-dist/2024-05-26/rust-std-beta-x86_64-pc-solaris.tar.gz=b4234ad1e817f65a7a2ecdfabfb1437ce98fd580c0bff61037ec917fd6e3c88b
-dist/2024-05-26/rust-std-beta-x86_64-pc-solaris.tar.xz=b7ee8e567aa1341d76be78eccd2c5857f4757b295b32a14d4054766c41cd126c
-dist/2024-05-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=145a8427c01b038b9bc79aed2e0ff46af87789555bd486885b3592c4bb62fe9b
-dist/2024-05-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=d84f020657dd466ba4f45d50fe1a8c316d03291c8845c443e2c68c4b40e590c4
-dist/2024-05-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=96b2278c15a6f83cb37ad6af34d9c5f364198a19cedac937d5cbaafbaca63fa7
-dist/2024-05-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=edbe125808cfcc69189c59f7b7614e056d34b23d121f9f165a93498eb775f92f
-dist/2024-05-26/rust-std-beta-thumbv7em-none-eabihf.tar.gz=dbbc72ede43591cfddb55ceb4aeb38d641a7ea7d7c0f5f4415a3c2e3a07e916a
-dist/2024-05-26/rust-std-beta-thumbv7em-none-eabihf.tar.xz=6b80df5802d08d6653fea474366bf1d4c892a87738a7a9f7156ae7ef916b5de6
-dist/2024-05-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=2e9c56810053a067bf91df0bf3d2c5c08c823e25fbe7267a6633ad33876ab0bb
-dist/2024-05-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=494963c721fb8d1e0d44ab9ad4212aa086af2363289d7b0d8b08c1e82f71efc7
-dist/2024-05-26/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=9901fb8f28e2334b31cb594afb1a91f22fa019b13808b650d940bd2d89a1315d
-dist/2024-05-26/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=583b0336f3f501eda441cdb5fbae87c4457a0bdcf896cca808111a181549b786
-dist/2024-05-26/rust-std-beta-i586-unknown-linux-gnu.tar.gz=e4fd222c2ed08e0fc1da161a23183ee222fa8755e70f4a352ae854b2cb798663
-dist/2024-05-26/rust-std-beta-i586-unknown-linux-gnu.tar.xz=81bf3475805e8af9a6297868ce9c1893c22d901fc7d16f0482c28a4655608de6
-dist/2024-05-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=c1d015599bc48664b01507da30bf152d730eaf0bd61cd907caa353b223d7adb9
-dist/2024-05-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=fdea1b1280e2fa5b14ef8998408557ecad0954b2502fe073e65e3ec3cacd1d22
-dist/2024-05-26/rust-std-beta-aarch64-apple-ios.tar.gz=be8fc41bb262be74ad73d375db76cc8ba277e8313a911aaabf17b02c52909b2f
-dist/2024-05-26/rust-std-beta-aarch64-apple-ios.tar.xz=7ae7187a9e85b58b740cf778df6d4442e388236501d6eeee76bcef0f9f378533
-dist/2024-05-26/rust-std-beta-wasm32-unknown-unknown.tar.gz=f5d863504c8b6b3fd42123dc09ad5e2cef978d8887a8ed62a125c125a7022b32
-dist/2024-05-26/rust-std-beta-wasm32-unknown-unknown.tar.xz=a36d65ab13f0da73e38f5e034d041dbdb1dc6577508734af332b2cbda5122ad6
-dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=f9c9684b948b09d658689ca70b84515b3533c41edab0e25bcd8aef5e40c621f5
-dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=e595f26a2b49d2f5b36e5a7333ac6bd0b54fd1c05122d160e5c1a4708ed6d488
-dist/2024-05-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=2c140b89014321f7827ce3e0b2d6cfdc84e871f05b3a0908716174719689498a
-dist/2024-05-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=bfed676e39a67671f3256edb6b9e20e8ed4421d4b777627c1484afd8c0d68d85
-dist/2024-05-26/rust-std-beta-aarch64-apple-ios-sim.tar.gz=8297677d667a637cb298e9e7453ba68190a9ad314a52015bc4124817e6586ece
-dist/2024-05-26/rust-std-beta-aarch64-apple-ios-sim.tar.xz=f2763a0f3a59b6c87ad1dc390cd7715587cf2b41fb58f58849243c69524905ac
-dist/2024-05-26/rust-std-beta-thumbv6m-none-eabi.tar.gz=447a1c4e502b0deef96183af40f32ef3f0d011f833621d7b0a6d972c8859e986
-dist/2024-05-26/rust-std-beta-thumbv6m-none-eabi.tar.xz=5d21d53fdcbdcae5dedf1e8cf2742d05b95198c984cf42322b72e98636214364
-dist/2024-05-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=f1ea6387ea140cce37c4708bbd5135d74f2861309b907b58458f2a4bb34dff13
-dist/2024-05-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=464f09ab8fe2fb8cda1d194d1178e025f092c13984680fcfc55f60f0f3b7f757
-dist/2024-05-26/rust-std-beta-aarch64-unknown-none.tar.gz=17b2d567838919513d8b998819f0367cee1b030882bff2be1116fcc4d3b95b1e
-dist/2024-05-26/rust-std-beta-aarch64-unknown-none.tar.xz=a0571520b61b28a64055b6420ce5cbd49ebb8aaaefc73ab40df73b0ebeb142e8
-dist/2024-05-26/cargo-beta-aarch64-unknown-linux-musl.tar.gz=61a51a1409249cb99d168d88805d678f042b0cebae06f0f2be3ec3ffe507e59a
-dist/2024-05-26/cargo-beta-aarch64-unknown-linux-musl.tar.xz=ea1e0fa7859596502b1b270e58599ca0d71c17060dc504a8cc801dc63a60de30
-dist/2024-05-26/cargo-beta-x86_64-pc-windows-gnu.tar.gz=ed791a607b85ed30666cf25de886892bcdab38bb2194bb5969637c4bf5700dcf
-dist/2024-05-26/cargo-beta-x86_64-pc-windows-gnu.tar.xz=3cd4887501f35f9d608c25e5306b3e20473820d194e014902f1ba7e2baf365d7
-dist/2024-05-26/cargo-beta-i686-pc-windows-msvc.tar.gz=c531faa0b9af65f9987897dab8ef32d32c53d14437a76541fb7e477d73a778ca
-dist/2024-05-26/cargo-beta-i686-pc-windows-msvc.tar.xz=f624fd704ee17023fe568a5f7165fd310170610b62fcfe0be374fbd53ba5e5fa
-dist/2024-05-26/cargo-beta-s390x-unknown-linux-gnu.tar.gz=e4de592c9e6e58556ee56ca395838259cd239cd88be27fe27141181981ebac4f
-dist/2024-05-26/cargo-beta-s390x-unknown-linux-gnu.tar.xz=b34dedc4c0312d40c7923f7fda9491ec6969002d641cff31889b96ba9becec08
-dist/2024-05-26/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=3c60bd3a7623e4a6f8691256ebdbd5b7441a13cc291803cd7e1e3a9af600def6
-dist/2024-05-26/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=07c4043b8da23bc161e8df2924c96f21c3d613e07b6d78c57c57908eeff50feb
-dist/2024-05-26/cargo-beta-x86_64-unknown-freebsd.tar.gz=9e8e5e7e2725c680eef7ac4c9b962f04f31d2f59a33a4ff2025aa035f0ef9f80
-dist/2024-05-26/cargo-beta-x86_64-unknown-freebsd.tar.xz=c5e194b6bd6494101ac163902943437b3b0b1e78cfe50900fa80eda96bf37a4a
-dist/2024-05-26/cargo-beta-i686-unknown-linux-gnu.tar.gz=20931f1b365f6f39fa473393ffade8bca346d00483673253a75f5718728e934f
-dist/2024-05-26/cargo-beta-i686-unknown-linux-gnu.tar.xz=7ce7c900c333f79170d28fcc85603822c39b14b687db22618ae11bfd3d6d274e
-dist/2024-05-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=152b2d0c9d1b79ef75cf5d86b880aff2e675e74d1f3456d156f782692df9062a
-dist/2024-05-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=29852ddbc3e91ef2524a267f4037a901a5dcef4182138dc85f946b13f2defe2d
-dist/2024-05-26/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=084be6c65205744138bb4b32c8c64acfcd62eec48de06dce24904d7dc92d5d08
-dist/2024-05-26/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=40139b0b78e8bf8b6ced7bd45675be174b51e99b0e09d5029aa2810f4ecd1850
-dist/2024-05-26/cargo-beta-x86_64-unknown-illumos.tar.gz=92448a4b52d02cc7e33c4304542f3514c1dfdd48a10a15c085caf24eae1ac955
-dist/2024-05-26/cargo-beta-x86_64-unknown-illumos.tar.xz=54757ba4bfc4ee87161dab91d3406570eae3f95f9022742b7096359e532a46bf
-dist/2024-05-26/cargo-beta-aarch64-pc-windows-msvc.tar.gz=c8d3cd13d4a2f3932b3804bfd18a11f847b5c2bb5ae32f4eb04c75f882c23471
-dist/2024-05-26/cargo-beta-aarch64-pc-windows-msvc.tar.xz=ff5b389e3645d58fd7cad66881554537d36319d84add1d897382b6ca3ca406f2
-dist/2024-05-26/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=31ea12902d3179266af423f4534881a9b2ea0131c0ee292a46e4db35efed6063
-dist/2024-05-26/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=1b467f77feaadd5d37d6faeca1f4001e7d5d1b29c4d40465c78f4d556ae23b1a
-dist/2024-05-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=a32d5142d32f64f3adc18d9949c63e4582caac446daf8809626f3edc04dcc2ee
-dist/2024-05-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=facf0eb79d61967126c5c49698aea3603790c13f467e40475ba4ba80d2937ee8
-dist/2024-05-26/cargo-beta-x86_64-pc-windows-msvc.tar.gz=bbc183a2ffa90e9771c1db7ae1bb260d6c5ecc86933e9d60026d5ff4975c76ac
-dist/2024-05-26/cargo-beta-x86_64-pc-windows-msvc.tar.xz=154e72625aa847777464b1aa8d885f8de0f16138362ec3725f96b434d6ec3a1d
-dist/2024-05-26/cargo-beta-x86_64-unknown-linux-musl.tar.gz=b45ea7d288797a7da04b71b665dca721899df248887e35b1d6903077a7f3a363
-dist/2024-05-26/cargo-beta-x86_64-unknown-linux-musl.tar.xz=cf654640589ad3326d5072be882270c8e16694400668a2b1be1feea6cd623636
-dist/2024-05-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=0c57f4972f64d8a418d4821492d2f069b7dd8f7b1e9626bdf59c4763ee85e06c
-dist/2024-05-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=2ddb32aec0863593472f47c90fe9e8f008fdf69f3e33679d808383e56e5acaae
-dist/2024-05-26/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=f304394966cea648c66faadc1f04d46a39e7532b913ae6f170b67eca1c03cfbf
-dist/2024-05-26/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=0625fe16550bd1a1aac9699560e168836d6a31f24c2bd5f49007029684991c05
-dist/2024-05-26/cargo-beta-aarch64-apple-darwin.tar.gz=8159a07acc11cd1c1b7d0c0dcf8be269325033922c21a85ec38a9a1b11166cbf
-dist/2024-05-26/cargo-beta-aarch64-apple-darwin.tar.xz=e4e935be5e89a405c06dcc77a76929a7c5fda2e576bde183a6854254720e053e
-dist/2024-05-26/cargo-beta-i686-pc-windows-gnu.tar.gz=6a5c34fd6a762df06c7b25d3a25f93f8dcd9071789528365350b20ac4a0cf08b
-dist/2024-05-26/cargo-beta-i686-pc-windows-gnu.tar.xz=3b0784e1ada13f88c1b3d130135406ab1b12ace88e2f296b292071ec35d15b50
-dist/2024-05-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=8dee7954f81238d7be66538f70cce670b724e919fcd7f2eeeef8ee492a808a8d
-dist/2024-05-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=dd2445c26ea2c151b93bff68c164ed69a313f87fbf1f90e8024317b4a66a6185
-dist/2024-05-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=bdcc649bb6f425ab32caa2cc385fa3b99cbe86cc3ea7a5780788c35c029fb099
-dist/2024-05-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=8fb0a771f69f3d6849129a1ebf5026e256010775e8bb9befd52325243b8f188e
-dist/2024-05-26/cargo-beta-x86_64-apple-darwin.tar.gz=2f4cefcb58f0ff51eef25680c926313e9b5e4a2c3beb710e7bb8eadde50c9313
-dist/2024-05-26/cargo-beta-x86_64-apple-darwin.tar.xz=5d53afb9ca5fe65a56e1d64e4746b13f9c586f81603553c0556eb02ad95df4c2
-dist/2024-05-26/cargo-beta-x86_64-unknown-netbsd.tar.gz=35c5b04d84d85c43f0c5a3bdc2aa8b8fb848961e3c4daf276704f85e47ae3fb2
-dist/2024-05-26/cargo-beta-x86_64-unknown-netbsd.tar.xz=3b0296264bd63a2d40c9d5e3a663756a5bdf442635ee8b6f54438a2767a2d04d
-dist/2024-05-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=a8c3a909f50a5de7f78672942d87aed939ee60ed6d5e50f308460a942a632545
-dist/2024-05-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=2ca4cb39879eba33da970197d45de82df898cf5a5bd4f4614b083fe999fac575
-dist/2024-05-26/clippy-beta-aarch64-apple-darwin.tar.gz=04c563beabcaefe80eda700ab26e975b30b5264c6202e04c9577f6c2b41bd6a9
-dist/2024-05-26/clippy-beta-aarch64-apple-darwin.tar.xz=19846f743872fd899ad66ce4820eef3f7ac056834856fe1d86c963f2e8acf2e5
-dist/2024-05-26/clippy-beta-s390x-unknown-linux-gnu.tar.gz=911554e8139df5c5b61fc85aaee2119cf36f3ec0f0e8741a7c8d92b1205bcff6
-dist/2024-05-26/clippy-beta-s390x-unknown-linux-gnu.tar.xz=1b108110da176b81daaadbc8c0a65950761fca243eb6cbf5ae0991d2bc3c89ec
-dist/2024-05-26/clippy-beta-x86_64-unknown-illumos.tar.gz=264150fbe3d369f18b61f2d607b694519c2b4b50f93c8c03f7109064bea79ad7
-dist/2024-05-26/clippy-beta-x86_64-unknown-illumos.tar.xz=89a044938cf7734caaf39c98c6e2a036e544bc474a0af3a3d92e47f39534e6cc
-dist/2024-05-26/clippy-beta-x86_64-unknown-linux-musl.tar.gz=f3a99c3a05280706cc042d67cec7162088cd2f62f2174bce8f074eda3d43cb8c
-dist/2024-05-26/clippy-beta-x86_64-unknown-linux-musl.tar.xz=0da48481695a90c1857bc0f8ff39223b3791b8b7102143e44bcca7bcea6fcb42
-dist/2024-05-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=5ba8b0e2162c574dc73121a69e43fd6629df9c656d96d95e9d269c3bc6e62add
-dist/2024-05-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=778eaf706993f617d40c22084f06d4ec8fa7455a22bcb699bd7b376d1194bd58
-dist/2024-05-26/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=cdf9711390230edab20cf0552d55ebbef87263b3353fd51bf232c12d1dd131d4
-dist/2024-05-26/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=5aa9b052cd0c7452ad08a1523c6fcad7df0a69f62a0a222b6a57d003d1881a6a
-dist/2024-05-26/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=3d7276560656e51826e3033dcc45fd2c78c2d872951c7e3434fd5f693a37fb45
-dist/2024-05-26/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=9aa885565bf7691ed028b8838a4108313cb2e7eda4b2f96381e8d80655ff4ce8
-dist/2024-05-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=29bcb622529f9e13b6aff7597e4c9d474f8127259f9efa96fa928eb3ba49b157
-dist/2024-05-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=14c7a9664a635479391eb33b90d8af80188cd38069799bb5b851b935e1848473
-dist/2024-05-26/clippy-beta-x86_64-pc-windows-msvc.tar.gz=3491ca3ce04812559abe45455e468625791aa6fc648ddc229d429159ce2b639f
-dist/2024-05-26/clippy-beta-x86_64-pc-windows-msvc.tar.xz=85eca1d8659dd6c171295b0aea160eff1410bc60e15889952998460b30df03ab
-dist/2024-05-26/clippy-beta-aarch64-unknown-linux-musl.tar.gz=aed3c4e45f47fd0bd6ca299f5883132e6d8b3c3f06d6bede71bb664bb0b04c10
-dist/2024-05-26/clippy-beta-aarch64-unknown-linux-musl.tar.xz=b8c475ac163435bad15fada68c29733d96f23f87cd92f5aa13ca99df21b93323
-dist/2024-05-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=3b42f9ffedd1b4074e7831fbf0809987866021b095eaa5f2d9481ca2765a7f85
-dist/2024-05-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=d71a3e5ae13c46f68f95f8fca7a3c6f8795faebf7602f8d1206e355c6d9bec08
-dist/2024-05-26/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=ce12948ba13e8f0556255a65657e9b92b996c2f96966cfefb895a6ffb8b08d47
-dist/2024-05-26/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=d1d23de591053c469fccc8ae6edeae3a2a8502ea5feb95272ab90f6651c52dc1
-dist/2024-05-26/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=31ae7b2c3af5ca9b47a9eb6ff53d1717df49e3a834584659a7108a72739799bc
-dist/2024-05-26/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=576332e47d5cd862581be587f03aa3a3e6abfc982fda6d26c7dcef0e2742b537
-dist/2024-05-26/clippy-beta-aarch64-pc-windows-msvc.tar.gz=8bd2c213b1dd6eea58a7896203962e9928ba9a39b0cbed5c5737b2d35c707a44
-dist/2024-05-26/clippy-beta-aarch64-pc-windows-msvc.tar.xz=dd530cb08114f28323c740e453f25b553376f0f4df977ebc79a87d09ac8e2b25
-dist/2024-05-26/clippy-beta-i686-unknown-linux-gnu.tar.gz=d8aa70bb4711bb985592632f88b2499b1fceedc294adcdb6e37f234dff0081f9
-dist/2024-05-26/clippy-beta-i686-unknown-linux-gnu.tar.xz=26349efee4513b0c37b9a963f3f6fcdeabc6857554bf3f28efa7c76c5c5b54b3
-dist/2024-05-26/clippy-beta-x86_64-apple-darwin.tar.gz=e6283756c66ff219a879799b6237df25755ac6a590e2015750bc3ac79eee322b
-dist/2024-05-26/clippy-beta-x86_64-apple-darwin.tar.xz=474a5bacc986404ebdca454c28254e6af3a7865db1daf26da56497e6dd8db248
-dist/2024-05-26/clippy-beta-x86_64-pc-windows-gnu.tar.gz=2fab393b9f0fae2c087067dc42758f914d74eff81c6e87da134520b1e4bcfb97
-dist/2024-05-26/clippy-beta-x86_64-pc-windows-gnu.tar.xz=23f46cea5a99191908e79f6f145b6577ce328aa4a435c8fb84a3c5afba8b9476
-dist/2024-05-26/clippy-beta-i686-pc-windows-gnu.tar.gz=5d0b5a07967828f9d2180ecda420433962532721fcd6b5b1dcf7fd273c8ee1bb
-dist/2024-05-26/clippy-beta-i686-pc-windows-gnu.tar.xz=34e36c25a1f385161d352f4d0fd03c332b9ad70c8bd96cd7928010f367d9ed07
-dist/2024-05-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=6bb0b231319507013f6556b88c7b32e640e182249935935796b33063f77d8c5f
-dist/2024-05-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=e029f9e9176d0562d6729ad87ba9dbaf474c003854f140da0a57ca52b2794a68
-dist/2024-05-26/clippy-beta-x86_64-unknown-netbsd.tar.gz=5aff0b8818b2639d2bb792288464b042aa2987e63e4b8d885ceed14fbd2425a6
-dist/2024-05-26/clippy-beta-x86_64-unknown-netbsd.tar.xz=6edd1afcf6bf4d9118a1dfbd8fc7f862026d179277b465da51b6b455957bc30b
-dist/2024-05-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=8969bae5fee4a30591b55d57b06d03d7d2be08ee20d2e5d04f055f916a8e248a
-dist/2024-05-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=7dfddd258c8cfa4f6b26f739fe52bb0519543472476595d901486b53ab22ebe5
-dist/2024-05-26/clippy-beta-x86_64-unknown-freebsd.tar.gz=2462c2fdc6215312ec7a12e98f74f9cfb06c0bed30812441268bb91feb2e4a8a
-dist/2024-05-26/clippy-beta-x86_64-unknown-freebsd.tar.xz=154d43b7db31cf9c25f6379c6bc0bb828fcaba99d9313e8267f705bdf810655d
-dist/2024-05-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=ed50a1f702e574c754a0c6eabfe120b5b3286bfe004dcc58b6a857684ae44033
-dist/2024-05-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=c7431985caefaa2d995483b0af592f828157d517828e6792c8abec0a52e2e600
-dist/2024-05-26/clippy-beta-i686-pc-windows-msvc.tar.gz=870b60708cb7fb9bd76d6c1ec2572502bbb7a86152d7e2ffb0e3d023674193a7
-dist/2024-05-26/clippy-beta-i686-pc-windows-msvc.tar.xz=292183dc34bbc648564ef99230efdb8749d3d2e34a190b62b318ef1b8f4546fc
-dist/2024-05-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=c28d6ba3d8319ca2a3c810ef13637dc67df6ab5c6d3e67e085009b296a4e87d3
-dist/2024-05-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=ba1e59c352e3e10696f3b1e5516af1d7b9fc480f4b9b45f313234a9151f4db57
-dist/2024-05-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=2efadde71b4bfbd6713b381f4e2df77a51be47818c4d7a0a9000d4f31502d50a
-dist/2024-05-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=82347bd970ad3a6e6d9565d9e6bfa994e23f849591ae6fda109f876928033952
-dist/2024-05-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=c3deeda6061109a09b123df68fd83a9c11c30419b91fc73be7653e4650b1b544
-dist/2024-05-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=a93bab60e6133734771ccbc807b44263c368bdb66b05491359897a23803d31be
-dist/2024-05-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=e71d212b7e25d7bbd0bdc4d04de8fa9c896239f1063f5e33067baf5278134cc5
-dist/2024-05-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=467191e0463a1f465304ffa37724da8199a112691147ae0c49fc311007fce410
-dist/2024-05-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=e2be1ffefa6c19b2682d8ac219ad88956485c99d41bcdd76fe78c80ce214f331
-dist/2024-05-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=7c801202c1c575c2522782f4346b4fc08abfc7f952a0cf3ad36a184e8e3c59ce
-dist/2024-05-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=cbc04f5efa7849c51944612974aeadef63479202f2c0426d9301f38a54f3e023
-dist/2024-05-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=e0deed883ba554d9b863bad8f9903b5952813439469282673fcd322ab7692751
-dist/2024-05-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=d3c4d54c15e8dbc45e2182354510cb705068fd32e604d289c0c612a6942ae82c
-dist/2024-05-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=a112b66030fc6d861ac988fbdb9496040a702d84409e41936c192af21d0ac7e2
-dist/2024-05-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=633f765dfa420b35aead7f8e0be99d28c90dd8d76dc452321e0b1102563f9f5e
-dist/2024-05-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=5db0f26d1705666dd1b6aa9c00bd24679698c7afc5b9a5df7d5588dd8be4dbd8
-dist/2024-05-29/rustfmt-nightly-x86_64-apple-darwin.tar.gz=a919f09c70fb61986dc0b4a52a75641edf18d7a4a9396fb0aae1009510bfdef1
-dist/2024-05-29/rustfmt-nightly-x86_64-apple-darwin.tar.xz=1d5781a9e6c705dd0a14ae75d4a49e5b0bf149d5d157ee19afc4fcbf6c31de29
-dist/2024-05-29/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=866667cc443b61ada4e25b816ee3d8e9de0d3114a9f5ce26fa36f311731f5726
-dist/2024-05-29/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=66cfae5d45a256b8d838a93e49a1cab0263418158ea238e07ba673dc7b3df6f1
-dist/2024-05-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=57b29a2e3bd7d5aad05d6ac6ec8acd3f0b747ce679ea0fb53a203c5383895765
-dist/2024-05-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=b8a5f95ab75b9a645934adb9a76513e0ff85f98de7b82aba494bd74289597d43
-dist/2024-05-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=d1ec7e5e6c8b13ef47359b1e64b972be0c4f740d18d341190db347cd89a868e7
-dist/2024-05-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=84f60a1fb717916a03c8f054610f543efd687bbfeee3b58bf8e99fa976bc7faf
-dist/2024-05-29/rustfmt-nightly-aarch64-apple-darwin.tar.gz=3016ced168060e3e2ba6147d3f4d13b18c76338ca80a827557b7882f168bb5ef
-dist/2024-05-29/rustfmt-nightly-aarch64-apple-darwin.tar.xz=cd45818ace482132afef6b6d59d892d002a476fbad00f28182b865b56687d239
-dist/2024-05-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=d49c9b195f063d2268074ecf9366380a968700a007f71593b1fcd8e5324b3a28
-dist/2024-05-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=66209a3abe1d64c7b00d55f526045d553e782ae994520da3a0ebdcef72142eda
-dist/2024-05-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=40f9c57aaa01f165604e47a967c2ce2af83a8c1d79f7cfa5cb737dc1513c12a0
-dist/2024-05-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=b5e067643239ef064de01776806de26a3d728aa9a3e2b88fb619400a6a2cf4ad
-dist/2024-05-29/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=2a860e5b10568f388252eb531913aad8aa0389d37cd2af49480802773a596be2
-dist/2024-05-29/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=6587860267c67a64977275f5d16b856d934f2a683ee1a6155dbf4bc9e52dc841
-dist/2024-05-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=979abfded9f0758334c867f2f493ac4741f9321c8321d9f5425adba51e19e5cf
-dist/2024-05-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=392924fe23bbe9df2723e67af3cd5aba27b176c04878c62904e97fbed9bc946d
-dist/2024-05-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=9e809bab970bad03e9fc2bbae8302498053115a8db46a8bd617014d751d153be
-dist/2024-05-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=8abee908fa9bfcf6e48b3e62581875ae65cc2b79b31c8df0976aa680c58e0ca8
-dist/2024-05-29/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=48a98383da0741207106ccf93414739d7dcc37b83bfbd79b3789acd1481ca7e0
-dist/2024-05-29/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=9706e65357de932a3325ed03153f455cc9af1d551a41327049c72a7a7cfd811b
-dist/2024-05-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=eb328f79f4fa5afa2ecef6869555b5303761ef0b8fe5d69ef6eb03a01c93af9d
-dist/2024-05-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=d5e7f54a4b972f8f6192a85e0185307406cfbcc50465a21c22d2fe64bbccc03c
-dist/2024-05-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=b3964c1199d4cf6ed8926a5442ad95eb6c5bca8639576b5a423df0afaddf2353
-dist/2024-05-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=3b3711a87366e42348321efcb87b232f0cb9c68f8fef9f651893d599bbd03bf6
-dist/2024-05-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=2900e5fff29a5bff6bdbcd4205dd8bf5992df44534f04c1279a7cd47d050a15b
-dist/2024-05-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=e5269da876cfbb5d0eb0ac24b34cf38e950a6904188fb4a7171f0504cbce654c
-dist/2024-05-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=4ccb7a272765c9c59776922f0e034f2ffdc236e959d4500df9d928078016ec9c
-dist/2024-05-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=5da7e0f39a0bb8c527f1db46c24713265ea7a3c9fb1bfaf84be6c6268ce68893
-dist/2024-05-29/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=de475ba7e107a5c144a417bb6b482b779ff954e0210c181a71a960c091a71532
-dist/2024-05-29/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=431c7d2d5a0c7bdb27dc15079c92cf71ce496978f1f2922e444da49e1b12affc
-dist/2024-05-29/rustc-nightly-i686-pc-windows-gnu.tar.gz=5e08f7be71e0ba29abcc3486a727df8444b818d6e4deac4728108c25382a4cc1
-dist/2024-05-29/rustc-nightly-i686-pc-windows-gnu.tar.xz=df5b548d795cf89bc6bd6bc5608cca377e46e5829485a4f3b7d43e294e2b48d4
-dist/2024-05-29/rustc-nightly-i686-unknown-linux-gnu.tar.gz=2f2f62d57833250c2b36509e820d7d4860bfdd297f46af5eacecb6c0f27430b9
-dist/2024-05-29/rustc-nightly-i686-unknown-linux-gnu.tar.xz=d819323b185b9cb9b5fb2f1521d9f71408c026ffe345cd6b76f7ffca0917b054
-dist/2024-05-29/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=af87663dc3677d7a697192cd9f7e2e73f6825cd86109a3a1af424e39c2e20f5f
-dist/2024-05-29/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=fdd0b838ff62feebfec9a7b8d516cab45568141a751641654b6ebd63165cd023
-dist/2024-05-29/rustc-nightly-aarch64-apple-darwin.tar.gz=9c328c9692688ee51fff66e43d92155752fdd67128c0f2fa3e5a642f43d7dd08
-dist/2024-05-29/rustc-nightly-aarch64-apple-darwin.tar.xz=d4f17356232fd136d2844d5888cc1425c0b942aa5ccaaf877fb8a8b357b6d4f1
-dist/2024-05-29/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=fe6533f08d7ce2e06e9fb337cdc32d865e8e00b8f91908737bc6354d3206eaf2
-dist/2024-05-29/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=dcec47a722fde1ec2eb61523a3a0efb06deed29f33e64ed1b11a01abccd20c2b
-dist/2024-05-29/rustc-nightly-x86_64-unknown-netbsd.tar.gz=82f159b866d58fc7183ff923d714183f319459d9e47719551d17c8c2345ca138
-dist/2024-05-29/rustc-nightly-x86_64-unknown-netbsd.tar.xz=6bf7bcd9ba441e35bb2cc6ca2b91c8fa9dbaf72e11d57bb3371b0303701aa66c
-dist/2024-05-29/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=e205ebc20e54660c7698f589f367dbed50bdbe46380b4505f96e8a90f9620c52
-dist/2024-05-29/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=8c2f2f53a77d638f36014b294dfc30d30b44899af92837d54237e7035e365d44
-dist/2024-05-29/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=dafb95b4125eb098fac7cbbf775f82247705f4ae39081966f1cc6530e47ab9eb
-dist/2024-05-29/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=e450864ba5db1035016100e83e36574a50bd1037f5613abe9fb2171506458069
-dist/2024-05-29/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=79d563c9dbf525955da2f0e666b8e1d8aaed2beccf8ed400ce0ee0916892bbb1
-dist/2024-05-29/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=886cabea80578d4bddad4fd9eaeada7b7295c1a26f9d65a7466b078ce8f455e2
-dist/2024-05-29/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=96c7e311c97e0739bdb27d114e2c70b4f0300695dea7b17867b17f87609d75f4
-dist/2024-05-29/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=e59464ace28065d7b3ebc21bcde836c5cf6d7e442cb69dfb9751cf08f597958f
-dist/2024-05-29/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=43016ec0b5b33c7f16cf4f4c486b0d4e3554cc7fef139a78558c177856f047ea
-dist/2024-05-29/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=e74571f5b4dfb498aef90454b12ea33e927a86cc31fbfb83ab33b3e0439afa09
-dist/2024-05-29/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=7a7479cd717019f2e18cb022d96deb5d27c554cf411920d04229f940fbc7226c
-dist/2024-05-29/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=bbd708d94f94da90010eb574aac0fed82490989a3f4b3b66e51d65526e0b3629
-dist/2024-05-29/rustc-nightly-x86_64-unknown-illumos.tar.gz=f60e5f253ce5f17631620a5ed99873e6067d65a547dfbb0ea751e7b151cdf971
-dist/2024-05-29/rustc-nightly-x86_64-unknown-illumos.tar.xz=71448313016bd45a7bbf083207a5f334c1a921b8a68bc9618cb4644c7e134716
-dist/2024-05-29/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=69c481a820c25d7b59d3d63081e93f9784c00cc4efd301fb5b9680b3166e2d9b
-dist/2024-05-29/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=3a33c45bce9fcc91730bfed44db0c1781f9a6c8c0a4382af775f4c9b638ee5a7
-dist/2024-05-29/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=d8d12e8b1f70353fd9b84ebea1ccb3a0f4bb561e99283c77ccb970ad6838cd19
-dist/2024-05-29/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=2890c1e4eb5eb0cfb57cf947088c43efd11e5e071bdb6191609639d541244394
-dist/2024-05-29/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=0ba52772ae17e47cabd816980f0cb22bd25254ccc213da6a968bd8e635607c4c
-dist/2024-05-29/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=4da826ffedd6468d336d97722b20f8ba49cbe7d77c7667addab19c39f731dd69
-dist/2024-05-29/rustc-nightly-x86_64-unknown-freebsd.tar.gz=463bd6103900d486e874195bd65646265449333dd5dd5f007cc57120289a5553
-dist/2024-05-29/rustc-nightly-x86_64-unknown-freebsd.tar.xz=0f4b1b482056ca489e9e74c634b733d1903ac0e6196506e635cc7edd6dc8f4d0
-dist/2024-05-29/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=42b41b32eceec839cedf88ffea93c99b04ee4bc9ce095e0872bfe3a67a6f6421
-dist/2024-05-29/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=644896626ec0177c21ab549eff85fcf28d307848454055b4e43909455df51b01
-dist/2024-05-29/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=43698606a91a090ebdcd6ab5f40f8d62fc0d653eaec74ab851438abe7da8a89e
-dist/2024-05-29/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=19b759811b9193c7b0d710b18427d7324c7ca4dafeca5d7cfebb6686761f9e67
-dist/2024-05-29/rustc-nightly-i686-pc-windows-msvc.tar.gz=c52226e19cff041f23552589f872399723d4c6d6514db93c2d6201f70f36e013
-dist/2024-05-29/rustc-nightly-i686-pc-windows-msvc.tar.xz=49c5b9d7551462e29ef4a036b3a6dd8905455256aff636b4fd4defc516d62e3f
-dist/2024-05-29/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=b04be4f9b1eaf4bb5e9a2a544614ac99f466d5925108633fb8c5b700e7aece7b
-dist/2024-05-29/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=8638b2106fbf7e5dc6837caaf07af1750b6aa24dc845e22a35d8e8e53584b2d6
-dist/2024-05-29/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=99710480631e11119640f6955257838648db572c4ed0d8d1b0081bace32313b0
-dist/2024-05-29/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=daab5b6364ad2afe80c96e8d905160e75c0783192296e88fd2b639c49b09d829
-dist/2024-05-29/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=0f6e0e64bbe42aae577cc0cb87d81ecb64a21c745277872177025611993c47a0
-dist/2024-05-29/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=fd45d7b870257bce91a33f5b971b11e0c6743e1c03eaa3c26bd201fe9be0c083
-dist/2024-05-29/rustc-nightly-x86_64-apple-darwin.tar.gz=29c34129ce3fef647140a0302fa1699af5460dab518b56d6a2257c7d7c288487
-dist/2024-05-29/rustc-nightly-x86_64-apple-darwin.tar.xz=fdf25c965c5218fad6e2949da8df88eeb9f886a8f5b9c72ec9d79a993c4829c6
\ No newline at end of file
+dist/2024-06-11/rustc-beta-x86_64-unknown-freebsd.tar.gz=4bf5a3ae2656a992beedec2f41dc98c791426a1a6a88f3503b003b4d6f0ddc1f
+dist/2024-06-11/rustc-beta-x86_64-unknown-freebsd.tar.xz=feaa1484586e78d77225734328d460277dde14baaf1299a30b30ef91e9a26a82
+dist/2024-06-11/rustc-beta-x86_64-unknown-illumos.tar.gz=9c692a71916f7ca9d41a97416f51d463b0495311491ba92b4d3cdb0f6c4e7c87
+dist/2024-06-11/rustc-beta-x86_64-unknown-illumos.tar.xz=97dece0cc2e4856a49f9ae17f09171fb55f140987acd0f988bbd0aa1e8971936
+dist/2024-06-11/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=6ad2e87e637302e8458d47dc1af923e38bffd7332775cfa5520c29110594d9b9
+dist/2024-06-11/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=84f6755c1377ced8ed2700b5ca9a2d38dd2e26a03e1fd636841ad46d3cf63895
+dist/2024-06-11/rustc-beta-i686-unknown-linux-gnu.tar.gz=11b439045379be2722cb42409b8bc342ff4b5f7df85e42566006cd72bb1a4e8a
+dist/2024-06-11/rustc-beta-i686-unknown-linux-gnu.tar.xz=4e5103702b4e43ea71914e9c508aeb0db6382ea331c31981142163b2a89e19e1
+dist/2024-06-11/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=396a3aaefca9511086f7e5442209b70622082d133b96783b4237c3f01f42bf87
+dist/2024-06-11/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=66e46ed344af9f165b7c4fde2c576340fa81ecade61c45ecc1562de70a9203da
+dist/2024-06-11/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=831420b262c5a2f44459e0daceebe271f298179c37aa5b7a1704a15bbbb1fb97
+dist/2024-06-11/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=691a6c4d0276add72cfab40968520ff48f683d4e660a50d1626ba9564dbf4914
+dist/2024-06-11/rustc-beta-aarch64-unknown-linux-musl.tar.gz=ebe1efe3c5d74e37d1c40dbd585ada7a7e256ce76911746f54994dfa15f9907f
+dist/2024-06-11/rustc-beta-aarch64-unknown-linux-musl.tar.xz=3bb37fcab069713fe8aa5ca72291a439eba5af4a3cc0be9d152e5f29ccaef864
+dist/2024-06-11/rustc-beta-s390x-unknown-linux-gnu.tar.gz=c00c2ecb5aae552069395d03f4135f051da073efc68ed645348f026c1884799b
+dist/2024-06-11/rustc-beta-s390x-unknown-linux-gnu.tar.xz=2c72347688058091a4bcb0c2fbcff49020df2b2c1733bc19d93b6e5149d5b13a
+dist/2024-06-11/rustc-beta-aarch64-pc-windows-msvc.tar.gz=517977edaa51470d460aa9ec09309eea2082cffa6adb13571a8f36efa9351dff
+dist/2024-06-11/rustc-beta-aarch64-pc-windows-msvc.tar.xz=0cc0b740cb267fde814b4971591b5797faa528b1e6250ef7b2d5220f0916208d
+dist/2024-06-11/rustc-beta-x86_64-pc-windows-gnu.tar.gz=9fe7d85fdbca12fbfdb776789c336f726303c8845a6f6c93b2dc6ea8487585d4
+dist/2024-06-11/rustc-beta-x86_64-pc-windows-gnu.tar.xz=38130e3d9779ad54bd890c4001b34b7c58368ed1940e7e676947e9c05a8f6649
+dist/2024-06-11/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=acca3e045de3c0d908caec4249e3905d207d96b4a1722644457b3cbe5707422c
+dist/2024-06-11/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=e4e92fc4b672f72b1f03db62ae712d9f944b982db89cf0d8dcb94adb1d560b3e
+dist/2024-06-11/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=63274e707bd0d2b2f08c49f170f26773f802db833347d2aa694d345d11c841f5
+dist/2024-06-11/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=13702b24228d983710d5678e0a1003e4f77e2244fbdf599015f52adbbb77bfcc
+dist/2024-06-11/rustc-beta-x86_64-pc-windows-msvc.tar.gz=ca877491bf7bf50989b9ac21c12e335fd0ff002ccf4a2c07316ae1df1a3d7e6b
+dist/2024-06-11/rustc-beta-x86_64-pc-windows-msvc.tar.xz=d757a328595887039d8017e9e3faf79448850c3dd9bd3c26d309a313ccc09a38
+dist/2024-06-11/rustc-beta-x86_64-unknown-linux-musl.tar.gz=155497f2abe036f09f6aa014969d58132a9e2e4e148fea485b483e0dc3705a39
+dist/2024-06-11/rustc-beta-x86_64-unknown-linux-musl.tar.xz=6204d1fa08beeadcf1564e334cbb65a7317c571557cbc5517eb6bf08f5b0ce75
+dist/2024-06-11/rustc-beta-aarch64-apple-darwin.tar.gz=3bd7db536344c6a3d0d0bdf95986136d5db8996228802444b561783f2e7c3c9c
+dist/2024-06-11/rustc-beta-aarch64-apple-darwin.tar.xz=b425561b3e7d9130fae94e78522bb262c634304ced32030828743fb332b11ecb
+dist/2024-06-11/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=e2f78198d33f98aa34bedd4f5920868a8f68620e29eca2917833f6a8f23f787c
+dist/2024-06-11/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=22f3b45678081fe52a9c8e89234a9939aad5623eb43ec54921effc28c0bdcd80
+dist/2024-06-11/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=beb5ec95069cbac4e53c51ea3e785ab5f25122132c8b78b196372bb2a31ed46f
+dist/2024-06-11/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=17242f74c96cf581f2e40a82f6d7fbd585af2c2990cc73ad4ba7a3503dd279a3
+dist/2024-06-11/rustc-beta-x86_64-apple-darwin.tar.gz=d952d90397c70c5b53caa98b2e5d48e35780e1e5b342775c10fcbf504717d2ec
+dist/2024-06-11/rustc-beta-x86_64-apple-darwin.tar.xz=14bd4336eb396a133ddbb2acd01ae799f2f68a7ac723a00a9db8c3e06bfa8027
+dist/2024-06-11/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=a2118f80091d62ebb762df0bdd159d19befb440d754034da7348aae50d63628f
+dist/2024-06-11/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=a4b9d1a04d8f9cfd4daaf57fbeed3615d000c5107c6fa1b2992dad6ca552e35a
+dist/2024-06-11/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=d5c16c5621e43cd3007ba4d2bc0f6e8a3a2376bc2a911e42bd2f2670ff94c12c
+dist/2024-06-11/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=202662492afd863b6b6428a3bc5ed822c62ac2aeb8a0264df1d69cc5a3728d8f
+dist/2024-06-11/rustc-beta-i686-pc-windows-msvc.tar.gz=a9fb64cac53595444bdbe8f152e52214812498e0c6e2b664db10f1f693a92dca
+dist/2024-06-11/rustc-beta-i686-pc-windows-msvc.tar.xz=fe78c5ac51d96c3c3e222828dca3d105a2d4d7f8acd6e0d86ecd4b27ea70a4c3
+dist/2024-06-11/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=8c584010c964ef1b02e1014ca1c6ed9584c1ff781f8af115ee001e3a13213954
+dist/2024-06-11/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=4a407fb59db284ddf6fc0ccd487116fafbcd7c227f3dfd4e0b7b64dd560dc113
+dist/2024-06-11/rustc-beta-x86_64-unknown-netbsd.tar.gz=2f07a283bb0e57ad50366b67d216503a423867eae205e4354b74b748e9d3ce85
+dist/2024-06-11/rustc-beta-x86_64-unknown-netbsd.tar.xz=8008331b32e9d0daeb275327082e38671dcc91864a3ac95be67bd15ecaa852ad
+dist/2024-06-11/rustc-beta-i686-pc-windows-gnu.tar.gz=c42637a8aa8666d746a45c9f47b437a9720d355b5bc6db42c2a90fb03d2c4a26
+dist/2024-06-11/rustc-beta-i686-pc-windows-gnu.tar.xz=eabe3a7e72829e0e5904ef381157cc3da169d9f5942e0367b2d1b1781c387560
+dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=f4010eea815cbab895c96311a456c4e3aa24c5f0d55f09052bcde59de7f286e6
+dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=a8f555c713cbe4a1860ee5bc812eb624f2775e034da54bd0e37c325453d70448
+dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=c89619ed4ec28d4f48ef2f7e51155716483a7f4bb51fe38235e69d4694cfcbe5
+dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=89aa3d1add14298bd40e3bcbc6b41df91312258ac6f203fff9eca4422f0c5e9f
+dist/2024-06-11/rust-std-beta-x86_64-apple-darwin.tar.gz=2303e7926bcc4fa2c67c7063fcac3a7b581fdd91fb89123cb6cdf514ff38afed
+dist/2024-06-11/rust-std-beta-x86_64-apple-darwin.tar.xz=9ddf392d8c696e902c2924ff938a4bd099b9a54834dc62710e42527e464e776f
+dist/2024-06-11/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=6016b465a0cfc628f2c978ed18bc19a4a27e20a5ac11a170c40d01a857a5f50a
+dist/2024-06-11/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=8e3d6f7ef6efead7d08b1c889bcc6e520d0a6d29226ade1b150aeb625fdb9abd
+dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=5f53b7630fa7703fc6752c3fb8c8eba8e25b9f77a3b91e14982510a0091d9e44
+dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=8ed3c2f0b0f81d197d0dbd01aa777eb17ebc7303176601be2b2b05ebe1bcc971
+dist/2024-06-11/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=dbc1a1bb8cfb4472739d7f3a52bcd571357d2d2761f3723aa4c7d69abe9a5dfc
+dist/2024-06-11/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=58f46f20d58669d497ff683d6ea85e18ff68d51a442f6e21bc20ddee779e1c4f
+dist/2024-06-11/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=d71947b5ddcfe538162b14d6b785c365c34f2b6ac2f1abdc90b020c4a446a313
+dist/2024-06-11/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=ca0a665e566b3ff74c5f552e7e4e030d3cae9080dbb6055dce3aa41206b5b111
+dist/2024-06-11/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=e927c0890d2c5135d86b1960b6b182d5c47853b53eeb196b4748e7b8ec9362e4
+dist/2024-06-11/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=df33672f826ce8681d6c18ec2129ef47623b7cbaf6515cd921d39dfc05cb7a06
+dist/2024-06-11/rust-std-beta-i686-linux-android.tar.gz=2559fdcf250e7e0a1b5589e8f2bc69340f5610b7e6ddf08185936fa2e6f10534
+dist/2024-06-11/rust-std-beta-i686-linux-android.tar.xz=442f0aa53f343eec2b6984934bbf0651ff45f314d1f46dad2aa11a2f5c5a5a5b
+dist/2024-06-11/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=cb657852d05766e1c18b11d99a94f3570b6c6147dbf9b2113b80236566d2d4ac
+dist/2024-06-11/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=943de72c556821b67d59afd9dd128bfb01b3ba743dd3e7561c50559afd3768f4
+dist/2024-06-11/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=a7c6d3f54d925be073007e3737173b0def7d781b6bfd5345971a69300aeee9c3
+dist/2024-06-11/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=cb9115328bf6f5ae661ce5bc9cc9165c6c9e6f759f3cc5038154531b314e6013
+dist/2024-06-11/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=2a2dac9fba84958818f6b31f30f91fcfef521111827937c88aa696b646f5b075
+dist/2024-06-11/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=d16b28da0196a815f028d432dfa0957d0bfb512b259129969548bd050afac872
+dist/2024-06-11/rust-std-beta-armv7a-none-eabi.tar.gz=d78f96102490f9025598b11cb72e31e96d3f5fd566e8f7b2b2c503a37b0dc6c3
+dist/2024-06-11/rust-std-beta-armv7a-none-eabi.tar.xz=a439af58e90970b4dadaa04d8f94ea53c6c7a159117926c46b7da0eaa0d0ca5b
+dist/2024-06-11/rust-std-beta-i686-pc-windows-msvc.tar.gz=d7847f3d9b1a2f50541ef3d2c25eeda469b28412817cadca52756aeb4f2c57b1
+dist/2024-06-11/rust-std-beta-i686-pc-windows-msvc.tar.xz=622cafc347ec1d3f0ef70354a0713cd255029730b17ad1f1ee951d9b0cb515e5
+dist/2024-06-11/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=5fee2542ee8ee8d155edc0ac36ec8822896e6f93f9f573b9284d70aeb186a05d
+dist/2024-06-11/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=dfe9ca3e3f217922b65db0d65826c0962369fefd3d5d72d6f03039acd710f122
+dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=b0937c5dcd458f313aabe07668ea338f2629bfc9c45d6139211b6923a7c7eb0e
+dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=65973a26c69f8ca7d3022180e2729161f7a618706cd9974fc54b14cf48f1af79
+dist/2024-06-11/rust-std-beta-aarch64-unknown-none.tar.gz=def2fc3aca20a74d023156606067f88ea8f1c8b602fb628b8f27ee43e3b62cfd
+dist/2024-06-11/rust-std-beta-aarch64-unknown-none.tar.xz=43cdb54af35a6c00ee10759a3f6ff6ca5c9080ba817aaf2eab7df8f239d77196
+dist/2024-06-11/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=ae2cbe53d304442e112585dd968f72454cc33bb75d3b4d7854a04575ff7b5301
+dist/2024-06-11/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=b3192290a45ff978126f4f08e7ddaf6de8720a2f6abbc5b41536fad6f994d7ae
+dist/2024-06-11/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=0e2dc167dbb66366252100fc87b94a67cca3360343302697c2989beb2eb14704
+dist/2024-06-11/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=6144604269f533eed11471b4c5d2f31a9f8340d9edf0f398a42e6e970c95b991
+dist/2024-06-11/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=b57e11248924ac54500d80525b8fe823e7dc74bc579c2b7f3f076c0a4c85ee2a
+dist/2024-06-11/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=9e473a5de0d02e6d8278a9e2430af135e3d6d4ecf5ce59827b384c8f20af39c2
+dist/2024-06-11/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=1a62b5af52767e68146a45a47384b33c93b32a4579e51d41f66746e38dfa6eba
+dist/2024-06-11/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=81bcf448ec54470edf60c2079ad9ef03f34052aef5fe9d8f5af933c565fdfd29
+dist/2024-06-11/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=88eb49f86265a7fdb49b455cf5a9a373ac1e0f7cbcac08ef2194eaefbb039b22
+dist/2024-06-11/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=bf9a278615765e199786d16f154006007ddfca0d5a5869c55a05e513a7b06580
+dist/2024-06-11/rust-std-beta-thumbv7em-none-eabihf.tar.gz=13f16402dea66facba6e10a9556e0afdbd6b004e8aa5d08e106cf76ea59b8288
+dist/2024-06-11/rust-std-beta-thumbv7em-none-eabihf.tar.xz=7ecd66dc65758cdf32cdebc38f6f399392788a7085d69ec7e8fbd63be7b3e904
+dist/2024-06-11/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=96ccb2252defcd5bcd9eca19380b9d4e4115ffb135efebe6717b1527ee440bf8
+dist/2024-06-11/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=c31f4ef95857a445bc480b73babb886e259443b3137efd694c4b67f913838212
+dist/2024-06-11/rust-std-beta-thumbv7em-none-eabi.tar.gz=0637fe1ab1284334ed4f9aec87a4b51b6983418997844e10ffe20326078f6d18
+dist/2024-06-11/rust-std-beta-thumbv7em-none-eabi.tar.xz=ac7f13ba1a107d03c1b7bb0d2e6753b926a26554c82de38263113e2d5dfeca21
+dist/2024-06-11/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=0e8a21970d4ea6331968b10e990cb6dbe3d38af393e4dc8d603efec1b59aa0bd
+dist/2024-06-11/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=04b9663cef2d3507c96b77b18aff7c9beee0f6bd0e0cb9ef37b8c9cacadbb198
+dist/2024-06-11/rust-std-beta-wasm32-unknown-emscripten.tar.gz=01d4da0efebf4615da7c92c6cfdaedaf283d3f5e66c58a1b1e2e17488d86b3d3
+dist/2024-06-11/rust-std-beta-wasm32-unknown-emscripten.tar.xz=c203ec9216407f90d0bcc451e40a29e50279dae8ee161f05d9245e3cc8e1b30a
+dist/2024-06-11/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=3621e0a16f7e6d9f292894a343941399a54b5d76a858fe5a69b83c95f15ada07
+dist/2024-06-11/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=5944208b88c6924f8586304abea6827cdf756066158dc64200e207027143e843
+dist/2024-06-11/rust-std-beta-aarch64-unknown-uefi.tar.gz=1887e342d5c6453a63336023e51c124838762f89e9289d1abd8226a717bb96d3
+dist/2024-06-11/rust-std-beta-aarch64-unknown-uefi.tar.xz=ba0ca831ed66a72a14c8c9dd591e97d7d6cbc55762c961283088e897de4a8669
+dist/2024-06-11/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=59790fb6982ebfefc40d352d411604840b7540a6ddfb26ad14d70e139df3ab99
+dist/2024-06-11/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=c022c80da2debecdbea32ce34ef040bdebc8566a78e2867512815532746e1c95
+dist/2024-06-11/rust-std-beta-armebv7r-none-eabihf.tar.gz=4d4a380bed233e86ea957c173412b819fce00d66d369657a0778da5e4f244034
+dist/2024-06-11/rust-std-beta-armebv7r-none-eabihf.tar.xz=577763a4758c42bcf0c875d606a6dd538c07866e9a65c2b73271f0e9d0762830
+dist/2024-06-11/rust-std-beta-i586-unknown-linux-gnu.tar.gz=29f8e4dc5d88bfd66f600402022267ad85d4afcffd7142107d0fd28d0cae4cd8
+dist/2024-06-11/rust-std-beta-i586-unknown-linux-gnu.tar.xz=d030db59dd1788fa8438c52b9a8cbc6754eaf529de60fa4fa9693a687e644dfb
+dist/2024-06-11/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=df978c1519ea4b50fcec2ec18d2cd9a6b813982dc50f6442af9ce340b98a8c46
+dist/2024-06-11/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=13585b56ce162922dbf03d0b6432a6af9b9059a664063a6adca957301c23b905
+dist/2024-06-11/rust-std-beta-wasm32-unknown-unknown.tar.gz=6365c96d363a345c4882ad47a3e9242f37c930a10bdc89d137e5e05b1b599351
+dist/2024-06-11/rust-std-beta-wasm32-unknown-unknown.tar.xz=480e07d3f110ff9f201315f5a01bf674ead911773241d80d9005772cfe4a3d88
+dist/2024-06-11/rust-std-beta-armv7r-none-eabi.tar.gz=0514e7022540078895be3000fa0405157bf1165762e77672f78230e62ef2c8ec
+dist/2024-06-11/rust-std-beta-armv7r-none-eabi.tar.xz=659cec4d3e3f0783bf9a8b42a245b995e00b36a8ff04a9b6b458ace016d825d1
+dist/2024-06-11/rust-std-beta-i686-pc-windows-gnu.tar.gz=2c6b17e0fa22a9d528217fdb8231aefd21839e29babad0fd975fd3654a9706f2
+dist/2024-06-11/rust-std-beta-i686-pc-windows-gnu.tar.xz=c2c98b0c6b21618d5c49283f19ccdd3ba76159afd904c9683251d36317582615
+dist/2024-06-11/rust-std-beta-x86_64-pc-solaris.tar.gz=9433aed1f5f87157cf02d13e7ad375e9a2e9a260afb8419a05eeb1856069ab26
+dist/2024-06-11/rust-std-beta-x86_64-pc-solaris.tar.xz=2a39a792676fd60f47db90979fd56f3fee709d05d91b5c8bf4e0a01f39fed14e
+dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=29e4553e9889c3e202f550042555b5c24cf52ce68979870fe33d9e9eaad37db0
+dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=7d56ef2eb64550f95b2ec1e1cfb9f153e9c6b412dcceef35f76db44eccd4d8a1
+dist/2024-06-11/rust-std-beta-i586-pc-windows-msvc.tar.gz=da7c08348c6834793263e136747e0e3dfcd5cd805c0c6ca25323fab8a30de427
+dist/2024-06-11/rust-std-beta-i586-pc-windows-msvc.tar.xz=3d60ea1671800cb8f271f1869186ed099f35ee8171d23df7c6ef0c79b4567540
+dist/2024-06-11/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=f3cfa8625f3586ddf48c301b7016d49d216324daaa3b76168a97f15506346c3a
+dist/2024-06-11/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=2e5388097f10a3640514d1a4040f6fec090e1c4aba0259cbdd900ead7fcdfd94
+dist/2024-06-11/rust-std-beta-i686-unknown-freebsd.tar.gz=cf38eeced5efe6139043e123b217a5c3f43bef3d86001a9a51fa21b012c9b468
+dist/2024-06-11/rust-std-beta-i686-unknown-freebsd.tar.xz=e078625da24308d78603400e96454e60606bed23f1132b64efbbbc815791d58c
+dist/2024-06-11/rust-std-beta-aarch64-apple-ios.tar.gz=2f1dcaa67df6adacbb850bf17ed5df8258fd2087668d028814874fc8292bf420
+dist/2024-06-11/rust-std-beta-aarch64-apple-ios.tar.xz=2a11e0abb8b162a12f72825cac59cc0df993b5582d911bdf6b97252078887651
+dist/2024-06-11/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=d7f4366df7f3599f031b9654d3c0bebd9c21ec530330283e6560cceccc17365b
+dist/2024-06-11/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=cb9e8470fd9934870cbb881f7611a0bd614416faa42cfa6096a1ed19abdf9cac
+dist/2024-06-11/rust-std-beta-wasm32-wasi.tar.gz=5e7d7b535a7c1449a4dcac4022de279c7676852a7da3e63dc063595dd3fa1b54
+dist/2024-06-11/rust-std-beta-wasm32-wasi.tar.xz=c4db5ad4aa261a01ba3fd8a191c7ac6323e6134b2e17522b3fe0891a642d4c87
+dist/2024-06-11/rust-std-beta-x86_64-apple-ios.tar.gz=a27f3ff22b233c72673e32bf257f766ad8e11abfaf9f83fc7c3e756f785ee83e
+dist/2024-06-11/rust-std-beta-x86_64-apple-ios.tar.xz=8592a2f8b1d6c3cab199cabe8b6e9a668b90bd77bf6a5e0869e2b4f3cc6d1170
+dist/2024-06-11/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=ffd9d5acd9a2a33e6a699b850d1776521da443b52504ba77fc71d6dd7353e18d
+dist/2024-06-11/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=e92eec9cd55b37f135237c98cfe00c4ee23d2ef400cc3470deb8f1a0010e94c3
+dist/2024-06-11/rust-std-beta-x86_64-unknown-illumos.tar.gz=b1d2e427120295375eecc3d8fc647fe57e1195210d7d0243b20d156f173c3155
+dist/2024-06-11/rust-std-beta-x86_64-unknown-illumos.tar.xz=b97fe83bb5050460465c57c37456868368d0ce18e5134fedad07ae00df8b7432
+dist/2024-06-11/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=25ad2d1a91456394427a5db691ebd903e56e60daa89d73598155655caf6592b6
+dist/2024-06-11/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=88b0a7fb002922f78af0f8e9580acdfeb4c341c9fad35e53daf4d6073c73ab8f
+dist/2024-06-11/rust-std-beta-x86_64-unknown-netbsd.tar.gz=b5e129c655bdc051eaa5aca8c8a577914100137a5bca753df619edd22889a1c2
+dist/2024-06-11/rust-std-beta-x86_64-unknown-netbsd.tar.xz=5fc42453c00c3498af2fd60fa4345c2047f302113666bf4a1d044539e3c1e66d
+dist/2024-06-11/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=afb1e9e37af72ba42b71f2a8a78ef7ba8593dbf8e35501e20a81e2aae204722e
+dist/2024-06-11/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=3b7f63b544a5e8aad8a18097b915e01c1fb880d48514bd1fefe3a5d4872eae28
+dist/2024-06-11/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=bc151debda651b76573e77c489c3b9c2be4af0f632e0061e067889f21ab254fb
+dist/2024-06-11/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=f2f9225460e2e7fa7d28cee2dfdab483698c6f51b0eeafe49e2d8e44381a727c
+dist/2024-06-11/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=5418a327d270c603ddc903ae6061fcb6bc9bca14593f13fe10ab3fe0f4a656ca
+dist/2024-06-11/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=423e7f6fd6555c6d850e7317a8677d4778bc1270d3cfefc05614ef1acc61fd96
+dist/2024-06-11/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=d30d36a72c1e874a7f9df7f805f5cea3617f912b5ad5e7163616b07022e0f7ae
+dist/2024-06-11/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=4afd0b4ab3787dcbb2b2f686d56844c6aa3af69fbd72d04bd57901fdd58b6333
+dist/2024-06-11/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=0a9b8bd1d39d346a20803ede808815dbf0cd55d9167561c8aabe7db3300a3dda
+dist/2024-06-11/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=e36372611dd3cdabd1f32fb942c79bd31b5fc13946448cbf9a178ad5005dc7b5
+dist/2024-06-11/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=2fe6221704614b167d837f52cfd439d9586e27ae82a34577659f86382c3192fe
+dist/2024-06-11/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=55ffdc97b8b6d309b1aa8443b49a5fd6133f5d7653069eb7f32625c1c0bf86ea
+dist/2024-06-11/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=87386371b64d4d922dc2fd01a0db28191748002b74a59437ddbab572b0d6fce5
+dist/2024-06-11/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=6c1f9a6683a9d3ad8203b9d08ed829e4990675cb07fdc2214fc1f7970dee7e60
+dist/2024-06-11/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=525a64f28aa0d757e82558737db3150ff90ecb885c3da8e0215370e47fb2ff23
+dist/2024-06-11/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=af49d1730949036a48c05a147a3c67885326df5bea314fef2828e04433f33ef0
+dist/2024-06-11/rust-std-beta-armebv7r-none-eabi.tar.gz=eba00bc621ee0235444698e5bc67780bc93765e70bed11634a8555d8d645635b
+dist/2024-06-11/rust-std-beta-armebv7r-none-eabi.tar.xz=236fe5262d76fd8ab7c12ab6c231608c7e704e5fc0d95210b47e0c86201d8a8d
+dist/2024-06-11/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=ac98cc34543e6faa0429cb9756d1b0d30dc13d8d8a44380b5feecc0e7d083e40
+dist/2024-06-11/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=ed8fffbe7899a7c35e5985adae1b35b7eabd076970a8eac280e834b7877f272c
+dist/2024-06-11/rust-std-beta-x86_64-linux-android.tar.gz=fa53ef5ea66f93f9fa46ac84d3cf6a16743b46a941910b092c9c71208a15defd
+dist/2024-06-11/rust-std-beta-x86_64-linux-android.tar.xz=66b394876549c4faaf872d4103ee49ef59cfba5c78777c01ad1df00dc6babd14
+dist/2024-06-11/rust-std-beta-sparcv9-sun-solaris.tar.gz=63794d1cc16a541cc07b56870d86db2212c2c8e3f06e11fd9bdca90fd93aa56f
+dist/2024-06-11/rust-std-beta-sparcv9-sun-solaris.tar.xz=4d419a3c4402c303b9437c7564e2bea79575623eaa0b300c2fe688d9d8f9db95
+dist/2024-06-11/rust-std-beta-aarch64-linux-android.tar.gz=b82186abf1bb250753a2640def13aa477b606e0601c5c1fdb25af0e37ea638b0
+dist/2024-06-11/rust-std-beta-aarch64-linux-android.tar.xz=57065c7b4f1f5d51d1366164b62b4114ab95f1a68cf551d12db8e9a2dad044dd
+dist/2024-06-11/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=bef7ed6391f906226a20f8d2d842fbc335891d7fb92f91b1c5873ce778d70675
+dist/2024-06-11/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=d80843f5f25923605681541b285ebf6868c0368841efacd376aac4dc9f01d0ce
+dist/2024-06-11/rust-std-beta-armv7r-none-eabihf.tar.gz=5b7d75f5f9294327ffb3c441b2e99fbc8402d1dfe0afaa20b2981a987e96801b
+dist/2024-06-11/rust-std-beta-armv7r-none-eabihf.tar.xz=ab56542b3be354d6c4f19fefe90af2daf59507e969a4144b6553a900e37e2a4e
+dist/2024-06-11/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=7365d0ccde4cd000b44992c80cf0e48ead99c2a00e18cde4446d9401792606a3
+dist/2024-06-11/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=69124687ee3ff876f557b7b21c8f78f7015c5f3b6537b65480613469772e00ec
+dist/2024-06-11/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=d1307c1b3fab3dcb6b1e5cfd5c30e1ef1c7b7e1e831ccecb00ce35bc2c1d8b9c
+dist/2024-06-11/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=8685907906feb9e16e34d4ea72e3ad338df9d6407dca6da81739b100926efcd2
+dist/2024-06-11/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=d8c1c3d800eaedcf23c25f436e30892df1938a618200f0f041fc1921a5b517ac
+dist/2024-06-11/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=53493d039721d5a2f54eb49ba7e16a205dd846bee559519182ca0af30111d182
+dist/2024-06-11/rust-std-beta-x86_64-unknown-redox.tar.gz=3f9842f81f45cbf35fd923ea69f1c88696070edfec0dcecac286519820741078
+dist/2024-06-11/rust-std-beta-x86_64-unknown-redox.tar.xz=73bc6b9b72bf6a9ba7dabe63b7a7d426eb47716466000d05802ef78ccb9128e4
+dist/2024-06-11/rust-std-beta-i686-unknown-uefi.tar.gz=c9954b477c329c3706891f77e9163d98aeadd96b1aa8a71f1eac20f316a9269f
+dist/2024-06-11/rust-std-beta-i686-unknown-uefi.tar.xz=88876cb6cf03707065fe172540e82faaf5dd55332c939891253476d4da3f8a00
+dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=e731faa24568e97821c5960229dd9a489ea7ead964a5aa052a6db322bcc55c18
+dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=47b529a6e19c9d609c41809fd62906c34f23a5c515bf62d91e88a87cf7cc0c85
+dist/2024-06-11/rust-std-beta-loongarch64-unknown-none.tar.gz=c6150b3b7481f2396b305188a16c4ce2206c440e9d7639446c76566d00dc5159
+dist/2024-06-11/rust-std-beta-loongarch64-unknown-none.tar.xz=e641747ef4ae46e4d0a8a3050d00b1b8c21c0f25da53a54de8e540a9953468db
+dist/2024-06-11/rust-std-beta-wasm32-wasip1-threads.tar.gz=37d141ba5beeaefd08834154f66219df734c379c9315c094433aebb75b82bca7
+dist/2024-06-11/rust-std-beta-wasm32-wasip1-threads.tar.xz=2045a0b765de96eb17e18d8028ed2e553cc998fb71a4811e3d848db320f6b9a3
+dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=82de12e6a2b01c0b98c83b4264a4e00ceefc424f673c97826bb28729c3f31382
+dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=c97b8a57ed8eefd60bbfe2df54121c548d9e271d9691def843185bac9d82b703
+dist/2024-06-11/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=6903175fa7cc3fdda5545ce11f4cc504e4183e56c626e25ff2b0d20a4f5190c4
+dist/2024-06-11/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=df06eee91ba57ff2c0a779da5d746db02f682514b8c03de875f03c96d05188e5
+dist/2024-06-11/rust-std-beta-thumbv7m-none-eabi.tar.gz=d7023edb8c723803e114e5b8ed316a6839e0c37d92cf6a2a09b767ee5ea2b7b9
+dist/2024-06-11/rust-std-beta-thumbv7m-none-eabi.tar.xz=41e19659bc0e0445ebafc49740579f0ac23a9af8e233c529ba2132f3d111faa9
+dist/2024-06-11/rust-std-beta-arm-linux-androideabi.tar.gz=42c0a6bfed8ca53b8833dbee78f2eab92bee061c42a4d629e870c8e655bc3728
+dist/2024-06-11/rust-std-beta-arm-linux-androideabi.tar.xz=5f85c99315a18bfc7fcc3f0caa7218ddc3b6548eb04be0ded835b5c45ec2ae89
+dist/2024-06-11/rust-std-beta-wasm32-wasip1.tar.gz=97abd2b9a68973263da0116eb5a0b9ead2145c1550f3190d02b35606bb9dcf58
+dist/2024-06-11/rust-std-beta-wasm32-wasip1.tar.xz=4ba0ef9b136761e739ab8ef125ffd993ccf71161d69e7640d94de6d5df601dff
+dist/2024-06-11/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=886562504ee3e73ceedce6cfcc8d128f22a80f0a33c84b9c29920d7760a8a208
+dist/2024-06-11/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=a8f28e60aa1938cdc7b7d46a1fa770d587be9534a291f5367a80a52772a0b458
+dist/2024-06-11/rust-std-beta-x86_64-unknown-none.tar.gz=642e7fbeaa76403ccfaf6c3c1bfaa8b94ded7311abfece44c863df231c282406
+dist/2024-06-11/rust-std-beta-x86_64-unknown-none.tar.xz=b1441ef88a1a97ecb6d7b674b571beeefab9f59fc8799d9e63b8a01078042f15
+dist/2024-06-11/rust-std-beta-i686-unknown-linux-gnu.tar.gz=fba54c97da35d0f11af99dca7cb0f43784da2104c461518149974da1f2248301
+dist/2024-06-11/rust-std-beta-i686-unknown-linux-gnu.tar.xz=e7acfab1f7bb8b2c2a0f7558b813f627a3f6b6dadcd05f62c5895f753c2f3ffa
+dist/2024-06-11/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=e4d5ec39520d069609f32c4dc7dd4114623bcd112a729529a096c992fc19f61e
+dist/2024-06-11/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=94d508cc6c86516ae5e3bba9366cb466635a1e3f41fd00ba6b1a44a87175fea5
+dist/2024-06-11/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=76e17967c09311f9e0c684531f21588d5bfbbdd4c707e454068df240fcfa56ab
+dist/2024-06-11/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=e627a81855b3d93497b071138917dcf6382b60793a4a76073769537531d01789
+dist/2024-06-11/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=aa5a1b430e31bd5f912d378eab8447ecd920a5840c03b01799a410d86a7c4850
+dist/2024-06-11/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=20f6fc50caaff58aa2883696c61031e9cec5cc24aea94026cf9b84a7642c4d31
+dist/2024-06-11/rust-std-beta-i686-unknown-linux-musl.tar.gz=62d2daf4c1a0a6b4630559c64bc22ceccd658ea0e9e74ebf58a9b791226964fd
+dist/2024-06-11/rust-std-beta-i686-unknown-linux-musl.tar.xz=34681e4cac9a6e18f1952f51d6192c8b71b970a0edaf0a06766e1a576a7898d9
+dist/2024-06-11/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=da45a5c9a7c7c1db32d6664358699ceeb27f59247862190a93ac203e5f49f116
+dist/2024-06-11/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=f881c61a8ed04f02576374a82f28505be2ad4b694254503d30c1ab415b6b5a74
+dist/2024-06-11/rust-std-beta-i586-unknown-linux-musl.tar.gz=2056b8d9d54baeab1fcf7dcf65916645f8404413bff60851fd97108b7822a54b
+dist/2024-06-11/rust-std-beta-i586-unknown-linux-musl.tar.xz=d06fd5dcb976c5331185d308e2ac0e53597275a57603aa171a753b3d005f0667
+dist/2024-06-11/rust-std-beta-armv7-linux-androideabi.tar.gz=27fb1ba34b2331810174f88d0e75075d6af26ef3fb7cd3ec820408e819f36cc8
+dist/2024-06-11/rust-std-beta-armv7-linux-androideabi.tar.xz=f44ff932cecc16cb292a6149ac42fb440b5e4a8a6b56f55634d9031002eb56f7
+dist/2024-06-11/rust-std-beta-aarch64-apple-darwin.tar.gz=3ab3178d3c1d4b9908dc2d0b6236c147e8f787f323c0c02fb924e2d692ec839e
+dist/2024-06-11/rust-std-beta-aarch64-apple-darwin.tar.xz=4b67844f0413cd1b0fde9702542eb2ce297020c29531230c37d3e2f65d56b0e3
+dist/2024-06-11/rust-std-beta-aarch64-apple-ios-sim.tar.gz=317035259b48845882a4561bd1c61108331ce68231b3362fa6e9b0a323ea3fc5
+dist/2024-06-11/rust-std-beta-aarch64-apple-ios-sim.tar.xz=04585ea6b3e53cdf62372dc64f00237d26991a2f7ca6ce06f921065957c2ffc8
+dist/2024-06-11/rust-std-beta-x86_64-unknown-freebsd.tar.gz=048684f3b437110dee704d8ef58f166806d69504a0fbf661ad71d19575cc8436
+dist/2024-06-11/rust-std-beta-x86_64-unknown-freebsd.tar.xz=43762fd9d2cf4dda5e8b64dccbabf5637dde37685530eceba060faeba8212b62
+dist/2024-06-11/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=40b3feff4834beb31125cffff479288adb2cc8a2d9b8963943907ba2b5478589
+dist/2024-06-11/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=f088ad7f9697570c251655adbf6921341f74bb8deaa445cdb0d15e5ab556699c
+dist/2024-06-11/rust-std-beta-thumbv6m-none-eabi.tar.gz=94b65456fa327c6d8acd59f1fd004feea8572374e8eadc022338de75c45a6c03
+dist/2024-06-11/rust-std-beta-thumbv6m-none-eabi.tar.xz=9ca368829aaab88a93abb580a0ecc1195ce5fa3877bd556c856ab52af51095ec
+dist/2024-06-11/rust-std-beta-x86_64-unknown-uefi.tar.gz=1a9892b1efce5e6aaa361675e008c623c47056a64deb73246c4211f5194f31a9
+dist/2024-06-11/rust-std-beta-x86_64-unknown-uefi.tar.xz=e9a2df6f754ff4c1ced354250de51939efb1e003843f1d0d8962c2a25e7c0f46
+dist/2024-06-11/cargo-beta-x86_64-unknown-illumos.tar.gz=d6f794f092c47e97e822dd6526ac2622f8a7b3a3cfa8b8462b3378eb16dc4801
+dist/2024-06-11/cargo-beta-x86_64-unknown-illumos.tar.xz=bcf8204f4750c6ea9ff5667ae07de7d06e5b68e78176adb79fc1bc433f7d90c0
+dist/2024-06-11/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=27ba1abe717de9e96b802c8026a17a6b5f5dc728ba4813c705a03d54c234be3f
+dist/2024-06-11/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=55cbb9abf863c05f13049bc59e99ea3e64523f0193ba1dd155b21cb732db50c2
+dist/2024-06-11/cargo-beta-i686-pc-windows-msvc.tar.gz=ceb0b610395fb2519bc6207b7916f402a17fac9685cf8b5c2ee354b350b396ff
+dist/2024-06-11/cargo-beta-i686-pc-windows-msvc.tar.xz=73f1cca9028510331477a0299e214d50a3b9ad02ac035d056acce110f52a1463
+dist/2024-06-11/cargo-beta-s390x-unknown-linux-gnu.tar.gz=eb0dbf227a1ad39436af2334ddb6e90831881c75c24855e9c040bcbb6ce8d876
+dist/2024-06-11/cargo-beta-s390x-unknown-linux-gnu.tar.xz=1b95d58699e8f534b5d93ad02c4281d8e791e8c266f10820de887fe13b1d88c6
+dist/2024-06-11/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=b078cbb4e2e18b6da3618a1048b038c52bf37a398618179b1c03f25d5e154ce0
+dist/2024-06-11/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=80bd1e79864e21ed914a6a2b8ee5d66867734252002789c6d76c3f7e82133eab
+dist/2024-06-11/cargo-beta-x86_64-unknown-netbsd.tar.gz=e2fb5140e90588e6ab158352e3f198ea71107a1aa01785f692d5ef64925af58d
+dist/2024-06-11/cargo-beta-x86_64-unknown-netbsd.tar.xz=6bf7fc08f593ef8847b3b14a33783fb3c54c542fe61a8a92c0e462a1bbf34b9c
+dist/2024-06-11/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=6cc72fe175632e68fefaea683c0569e9fe8f036488154e4f1ccd6a3135479cfa
+dist/2024-06-11/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=b27004517d35019ead69bcd1a09c81aa20d2b00b57ad42655f1f434f8d66eed3
+dist/2024-06-11/cargo-beta-x86_64-pc-windows-msvc.tar.gz=e5d5945884554970344d16e90f9eed0dd60f61ed57e48b40fac2ee1d7c035475
+dist/2024-06-11/cargo-beta-x86_64-pc-windows-msvc.tar.xz=421ee0fca436d4d4d3bcd03c242f9312fa620da854b906618a1d8ab27979d609
+dist/2024-06-11/cargo-beta-aarch64-unknown-linux-musl.tar.gz=7406ba1c14e53da0a9ca696dc6c90fb816c072734f569c01f49c6b8f7d542d81
+dist/2024-06-11/cargo-beta-aarch64-unknown-linux-musl.tar.xz=917a2e63fcf03be81375143692306afb54fc2addef9f5508dd58fc1729119752
+dist/2024-06-11/cargo-beta-i686-unknown-linux-gnu.tar.gz=bdbd9c4e2808d9dd0acd219c3ba9972634d73fc4f177468bc196c66be620df65
+dist/2024-06-11/cargo-beta-i686-unknown-linux-gnu.tar.xz=e64d3405f99f8ad74984b81238a088b250be4e079e2c05aa68be1cf84f04154c
+dist/2024-06-11/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=bf7c374c02676f9e5a50f4964e6deb4d3aab19ecd66c4d246de0c9a06ebd23bd
+dist/2024-06-11/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=52e7907ca99467c71429d03012a3f6cdd95711b9cf002d3aa06ba25b3e53d2b1
+dist/2024-06-11/cargo-beta-x86_64-unknown-freebsd.tar.gz=bd9aace135befd19104b193e09bf982c79c8cb9cce301ff709cde2ee2dc82821
+dist/2024-06-11/cargo-beta-x86_64-unknown-freebsd.tar.xz=c0d2c3a2e56a1f43f62fb73e41b07def93baa278172d822a2a33f571d54f0463
+dist/2024-06-11/cargo-beta-x86_64-unknown-linux-musl.tar.gz=61526c6e4f0ce1a57d4831ac67252cf5a6cef3c106c6953b329bc0aa9c685e6c
+dist/2024-06-11/cargo-beta-x86_64-unknown-linux-musl.tar.xz=82bcddea6b3d976e7dee07afe7f805f5a6ff66f0721d281d2c896f352f395c89
+dist/2024-06-11/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=70c5bd18c756123f033a7cec027631f71d7400cb4d0c85d7602a8a6309379070
+dist/2024-06-11/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=f8a6c7dd8ba408a5fe623a0ca1d2f8bfe287b13bc09b1d8ea636ebbdec06c557
+dist/2024-06-11/cargo-beta-x86_64-pc-windows-gnu.tar.gz=fe26e842e6e4186437ea679cc75cd37d70a98b1ed0f17ed9ac876aa0501ebd5d
+dist/2024-06-11/cargo-beta-x86_64-pc-windows-gnu.tar.xz=f3fcb2b698736b3df87c06ba829a1f09c218e37b51ff1c59f165aaf8078c619f
+dist/2024-06-11/cargo-beta-i686-pc-windows-gnu.tar.gz=607f623f30e25541d9e6c8412bffcb9c16f7180250a244dfe1e2606edd45db42
+dist/2024-06-11/cargo-beta-i686-pc-windows-gnu.tar.xz=604369c997e05719d0fae92f7904e6b66f662bb75add1d836cb100e0032526a3
+dist/2024-06-11/cargo-beta-aarch64-pc-windows-msvc.tar.gz=de283125b79d17f4cf24bb608819177ac1637525b8c7e67a66e798f0c0b1024a
+dist/2024-06-11/cargo-beta-aarch64-pc-windows-msvc.tar.xz=8228a47ce003faf1edb4a10cf800d3316ba421a97176c97f6952743f7eddf734
+dist/2024-06-11/cargo-beta-aarch64-apple-darwin.tar.gz=8525a4015fa8078921f8bc5f67012c0d5747b7e7111079bffce79f2b696fbd4a
+dist/2024-06-11/cargo-beta-aarch64-apple-darwin.tar.xz=038c700f1b0ab543bb765a4b86638fc7eb1e44257a19d5a5457fcff4fc08f280
+dist/2024-06-11/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=16c75d17531e10f1bb9e95c79d8c3aa05549db3029663c69d2f56b2d2f3214d8
+dist/2024-06-11/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=113d97f781bf8d54f457e07fbe3de1d3a0ce0a1f8054a652083b67b81f4cb642
+dist/2024-06-11/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=7856fc9731c3dd7b360eacf422ce358acb2d33a7fd8b16fa190dc77cd9bdb3de
+dist/2024-06-11/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=85c930785fe9857458c9256c5a2849ae223c5dd162bd20ccc8021b2d2ff0a6ba
+dist/2024-06-11/cargo-beta-x86_64-apple-darwin.tar.gz=aa4aec2cf417a7446c2990d03cfb3dcaab9d99f5ac249cbb955a59a64b5b7b0f
+dist/2024-06-11/cargo-beta-x86_64-apple-darwin.tar.xz=01d4bd8dd8a58f16ee31df775d0d7046ce671dc86f8907514e3713a62aadbb12
+dist/2024-06-11/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=6e5c68d0665add368a6574528184dc1d182e7d72b8da0827b69eb9f9aecbc4ac
+dist/2024-06-11/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=180a6148f5c5be222d4e2626eed9cd7de2e0f62d0b456e520d1ab7c4931e1f4e
+dist/2024-06-11/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=6af892aa858f35708bf9db322abf35967b1e92725e05f6974e1d9ee3cb4c7b84
+dist/2024-06-11/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=40ffc9713504366978bb6f2eea12741400164318945df22290c7b669d3b77878
+dist/2024-06-11/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=9989b0189f7a4c5aa39c39c78be04e7291cc1358ebed597636f404f56980c199
+dist/2024-06-11/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=8c7d7dc2530f25cc771c75d454fd11f3e94c7954bb869e43736860be1f253d2b
+dist/2024-06-11/clippy-beta-i686-unknown-linux-gnu.tar.gz=94505902c45770c45a89ea12759bf46cd97efed657b43322d5dd09c13ed26331
+dist/2024-06-11/clippy-beta-i686-unknown-linux-gnu.tar.xz=14830f6fa92b0d814527a9aa5575d0cd529e76dbe2481533b819c735470ad684
+dist/2024-06-11/clippy-beta-x86_64-unknown-netbsd.tar.gz=5cc5f4202003b940a6a62c2384c749b741a9f6d62461ba13a6179464f6c3e6ea
+dist/2024-06-11/clippy-beta-x86_64-unknown-netbsd.tar.xz=01f4f0ef78f17e4991ddf3d974ef7b1dc9d56702ee2d65ede4918e9db99ec222
+dist/2024-06-11/clippy-beta-aarch64-pc-windows-msvc.tar.gz=ee6b64a7a0fc8d8482c38d2a263f9a9ed0b9462e6bd748a72e33c5cd7dac015b
+dist/2024-06-11/clippy-beta-aarch64-pc-windows-msvc.tar.xz=f91457f5dccfc81a601b075da340bf521e3cc17ba05d12f90c31c7f5b215a7bf
+dist/2024-06-11/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=7da546ff13b3e340f2ba22e6995566cb26e487271e3f1b68b3b7dc0bd5122623
+dist/2024-06-11/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=01807b62c65fe33acd05d10191cb16ee1bdeb1bd7b410a9c0cfd8f53006624da
+dist/2024-06-11/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=64f41430de84569a7b933db7f0c573fecf99f5d0c6900e35598c94a433c0296c
+dist/2024-06-11/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=b30a73278552ddf511ae82620f14ec7324f281582fa4fa9df3fe984510835aa3
+dist/2024-06-11/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=e6b0ac4bcec2871d2a50e644733399e684d7fa86798131243c4022cbe2ee5222
+dist/2024-06-11/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=edc629f04503ce88443ca6cce0b74b5833ce50f428e00a02b544f422577abb1e
+dist/2024-06-11/clippy-beta-s390x-unknown-linux-gnu.tar.gz=ac52f8b4a1b6332aca1ad2363195daf571f7f1870ffa6237441dc7928a408167
+dist/2024-06-11/clippy-beta-s390x-unknown-linux-gnu.tar.xz=96b366fa989d2f739a92ee03bcd141b666b942e0b26922acd620e0fea6d44d8d
+dist/2024-06-11/clippy-beta-aarch64-unknown-linux-musl.tar.gz=8ab584ad05a7836bebb20be8d84b0dd3a29d1823dcee3897abde3a47a10e582b
+dist/2024-06-11/clippy-beta-aarch64-unknown-linux-musl.tar.xz=e7b669a2936a22ed6d2a36b70a6593657488e5ed8d00a911bf33ce51c4c0cc51
+dist/2024-06-11/clippy-beta-x86_64-unknown-illumos.tar.gz=419ef233cfdbe9011d74796e8413a8b6c1f8e6281248969eaf7c9157542c1b70
+dist/2024-06-11/clippy-beta-x86_64-unknown-illumos.tar.xz=673a2f16268fba4d9bf7dca2c0758f3ee60f9754cdcefa36032b8140e6fcddbf
+dist/2024-06-11/clippy-beta-i686-pc-windows-msvc.tar.gz=a3c3bd3b90c951ce404a26a59421f00a03e0dc3351d9dd2876346ff096b7361a
+dist/2024-06-11/clippy-beta-i686-pc-windows-msvc.tar.xz=c3e7c1cc91f48003e1b68fdf753011711ee516bc2ff8c7227d427dd8ee98a72e
+dist/2024-06-11/clippy-beta-aarch64-apple-darwin.tar.gz=ad7b4ac9cfacd860e03f8a41da51b4d279d76b7f3f2f8ac8a048a45f89a7ed04
+dist/2024-06-11/clippy-beta-aarch64-apple-darwin.tar.xz=ca5d2d63b8d7cae00c86383d9075b2292a28d1a85864877a6c8282f5596631f6
+dist/2024-06-11/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=12820c3e8b952dfa931783b550f882dd96c48d3b776fa9cdb29b02d66ad14d96
+dist/2024-06-11/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=394873c6b2499ebc385a11b512c7378b95478a0b6f530c5b313fe86b65a18eaa
+dist/2024-06-11/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=8d9353baa4388d02d89b42403e07d6a61f314fc975b8fcd737d8f4edb0ab027e
+dist/2024-06-11/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=3cf0511bc5b14619dd6ca1cfeed003effa7fbfecb42fc096a45a211d1ccf419a
+dist/2024-06-11/clippy-beta-x86_64-pc-windows-msvc.tar.gz=cfae39e5d5cbc817aa3ba892822fe2ff122df8a648106aaf0ec18b1ce1a02632
+dist/2024-06-11/clippy-beta-x86_64-pc-windows-msvc.tar.xz=1f1f0596bef154eb3fb4e73993794850f8ad903f4dd0ef9697aa8d5b4d6ec2b7
+dist/2024-06-11/clippy-beta-x86_64-pc-windows-gnu.tar.gz=0909caa93377b2aaf2a05a345e8cfea2c69dc27bd7f7d7a9515576e90cd0aad3
+dist/2024-06-11/clippy-beta-x86_64-pc-windows-gnu.tar.xz=9125bfbaae2103f176b1e1b444fd38c7e74d3414536370037ffc6a85d8567551
+dist/2024-06-11/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=3721470fcc17f8d37c66281bb66c65a66181c80775571520fcc2dfdb583dc640
+dist/2024-06-11/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=79ec48af2925aaad12be405fb72dc9bd9e2ca89fd3a6017111020570ddeb6585
+dist/2024-06-11/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=d957f503dd4d9d228b6a445eab1183dbc6509a49ccbd475d25143cf1dd28f03d
+dist/2024-06-11/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=da7ec767b4a85fa327c957888b228671b2311286043165926942504239008d3b
+dist/2024-06-11/clippy-beta-i686-pc-windows-gnu.tar.gz=51ff631084254be43d79d7791000a14ad9f11239e42be73f48383f774109c2cb
+dist/2024-06-11/clippy-beta-i686-pc-windows-gnu.tar.xz=52079acb4f908150d207a838cc7d3c15a725c1d61be35d0d0b2ed85b3386f3fc
+dist/2024-06-11/clippy-beta-x86_64-unknown-linux-musl.tar.gz=99a534de9e5fb552a4e7a10eca2645ad260a723f42e15df3b4e2bacf82e90348
+dist/2024-06-11/clippy-beta-x86_64-unknown-linux-musl.tar.xz=7f9e6da187bb71c384f5040298c43bd303fcbc5e3034dd7fdc7b251c5d7b3a34
+dist/2024-06-11/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=acf05b62fc219ddc2fc4e4bca2bc4c2cca24398d6276bd7e7d9f8504627094c4
+dist/2024-06-11/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=c737aaf9c4bc3a743752b13159902fc5a8ce746f44221799bbcbcb1f9d04dc4c
+dist/2024-06-11/clippy-beta-x86_64-apple-darwin.tar.gz=422e97d9081e66a46ec3f4c2a7ccbf9b6443c7b343e0a2e90845f233536f545c
+dist/2024-06-11/clippy-beta-x86_64-apple-darwin.tar.xz=c9d02836c9d0e48684f0a343d6935848ec75e1faaf7007a6a3e0718b71e77f7b
+dist/2024-06-11/clippy-beta-x86_64-unknown-freebsd.tar.gz=f207fbfca76eb22f7097eb98ccda1da513fed417371a391e43e8d19fad9b76b4
+dist/2024-06-11/clippy-beta-x86_64-unknown-freebsd.tar.xz=61e39b0aa88a1d8e131a461cb3cebd05154c261058b735f29dc6ed603464b5a1
+dist/2024-06-11/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=c68d27b08f9699c7c2cff9e9bdb7485991d8445074e8b84c2e2222fbff209f83
+dist/2024-06-11/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=d5961f82b9688b9c1ccdcaf578b8325e8ac1e0cc2ffa02131fcc3281cc88dcfd
+dist/2024-06-11/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=12ccb5b1d82ad22292b337c49d1c5b0c0d584cfb4e649faf6c53471915df2473
+dist/2024-06-11/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=80fa7cb902135006046c10db64d9060103dfb1452e8e0ef256f8344fe0a9c8c5
+dist/2024-06-11/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=c08499ebec188f67477d0c4eac2e172b59f6d66ad4becb36330b5066af6547d8
+dist/2024-06-11/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=b3f29c79fc8bd64a2e62101468bbaa28338f444839659d4f99df34ccccad5eee
+dist/2024-06-11/rustfmt-nightly-aarch64-apple-darwin.tar.gz=4866e6d478424fb1c01b2b98678107b9c89e67a2cce3db49833bf34007f868b3
+dist/2024-06-11/rustfmt-nightly-aarch64-apple-darwin.tar.xz=e8e6fd846f70a99e6fad735ce4f4c8bca5f6b5f2d63364c2f8a7df85c13b63f4
+dist/2024-06-11/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=f14077408a763f0fa6218ed97d7697499c2bded289a5953336c727e2de93bd92
+dist/2024-06-11/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=27324f62ecfdeeb4a66ce3c62219c491f04ac3822305ea771df0381a5f4e5418
+dist/2024-06-11/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=1147008dfa30891e264bf5f469c9528fe47bdfc729a12215e5a985179513cc66
+dist/2024-06-11/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=95fd945a6c9bcbc9549913906a8f2de20adf54b84b82fe8d981dbb5b767f0cfe
+dist/2024-06-11/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=4f423c5ce278204dce918ece2af84bdb55429b7a11f630de95a1516e7b113f53
+dist/2024-06-11/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=c86fe94c9b6cbc56285478ffa715877d234af19f1b58b3fd4b2af23a0267b657
+dist/2024-06-11/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=f1200f077402474049f6b817688435db0ebef7fb52ef645d5b5d2f7ceea52a08
+dist/2024-06-11/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=a0d801ec3aa93389d5c6ae2a95be25ba3a50f53182c0a84a00c38a2f708447e4
+dist/2024-06-11/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=d4e28ad9b054cdd19fce6bbc37dc86210b0536aee5c23bca53a6bf1340fdb5bf
+dist/2024-06-11/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=b0958ab975026e09ba921234353f5a81b3227d23c10ded4be4fe37831e6abd12
+dist/2024-06-11/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=f1caa15f16aa1c93ee783bf273d0ae6a7abd0b38c93c717f2d49af5444cd4e09
+dist/2024-06-11/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=130687b9de22fb1d0c4c845cff5475e5959278718e3b6a1af7f1b9e8869b527f
+dist/2024-06-11/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=32e3881c61abfff7f9c006083045ffa5765c0b3a5a6ec46607e5428423ab76da
+dist/2024-06-11/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=c1859b8a44306b5b3ca27b9226bbf351cd3ff3cacb4faf61200d7baa76009367
+dist/2024-06-11/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=4f5c23ba3426719c39a7c767be8db83382c84ff7798c5194aefbeda821462269
+dist/2024-06-11/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=18d9a2084cd5e55792f3841fc7d6602bd4a973726662b516289385b7908ffa4c
+dist/2024-06-11/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=df5478f63a49c55ffe9cf62a1882feeca019290c0cc9a9ed5a4122b8aa1325cd
+dist/2024-06-11/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=f54c3b8febfa4023a0334dfeee59d75a44f5c1d3a02d2d57959473d6ad51205a
+dist/2024-06-11/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=dd2d83a7bcd45a0d5de312a2a4a28b2471a9597d318135214b45a69e1e449f91
+dist/2024-06-11/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=02a8ada9d737e115033d26b0691f2ef22428ba2f67b7fbab7c4205df8162a96b
+dist/2024-06-11/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=20bde0cb3ddca790c0d126d5d590b9a35a1c8631b42fbc2d4e85cfe5aa880d04
+dist/2024-06-11/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=dd29e278f79ce1be14ad44d61039e5a6a63e0e597c4736ab153beb758ad37fb9
+dist/2024-06-11/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=09d98f5c61def16b62b980a6cef3b1b3704cde5c0ad2fdd7d23521db410b6b8d
+dist/2024-06-11/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=ef43e61c2d3d90b09494a8dcbb5d2375223fcba6078f2bfb02ea43750b1a76a3
+dist/2024-06-11/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=80318fdf7d55c71beb8ff1434b79776c59008f5d62c63530da9f19a67cc18484
+dist/2024-06-11/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=05ae6d4f8ed07cc75b333e606af14f239978abe197b70409a5f2aadc7de43a4d
+dist/2024-06-11/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=a079a478e9a89c3a24864b44670bdffcebc139bbec9c54e7aab6394c08bcaab4
+dist/2024-06-11/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=243c2d7c23e8aeddf9729e1f7f9add6f88f50d012efa02644030110cba111713
+dist/2024-06-11/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=76b69b4b25e8c0d47b80491bcbb724a25c02d95e7f9cfe7a9c3c3570c24363c1
+dist/2024-06-11/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=027e075c94f53403f03a4fb29d4575928e1cba141fc0713c93edaa4ea5917e42
+dist/2024-06-11/rustfmt-nightly-x86_64-apple-darwin.tar.gz=b34d3f33e7ae81a5a95927997658d738a3d39db01408dad2d9fa72efb539c73f
+dist/2024-06-11/rustfmt-nightly-x86_64-apple-darwin.tar.xz=7efe129502b732219d1d24d59584b5ad002e7dc5288e047b06bbc81fab36e054
+dist/2024-06-11/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=231f11ec1c6e4f57556aa32226d22328656d2ceab075cff67c8ab0a1ec32a823
+dist/2024-06-11/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=b1cd7aa45a516df3a68814ce52753eeead4134943d610449456a30c682079ad0
+dist/2024-06-11/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=3fb86c9281ae8203e1119bc00e8001afe7e894360adc791a9a0ca1d50e6a9032
+dist/2024-06-11/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=6380fcfb015a40c4605ff18f8ba54c3be9a8e6a0115ede378565d9cc9943c627
+dist/2024-06-11/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=f3ff749dedcfb259a4b2d66ae30245caeb79fdec3b41a3bb4f65d50b1cf18120
+dist/2024-06-11/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=1ca50ca8ff36df7433a4ab4c8a63c3c91e214f6c7889843edfb9120c1f4f68d4
+dist/2024-06-11/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=a7f5f171dfef5b67498c93354d9dc5a7443d69f3f9bc0bc56b660d1450e9b7a5
+dist/2024-06-11/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=dff02f7a7e9ae58c41faf4c5731862d11fee06d17099c1ed18863219a4a82815
+dist/2024-06-11/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=71dc189c1d29d3fec849b47f64deb831569515e56821511b1221983eb9ed99a9
+dist/2024-06-11/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=17736f80644c8cdf8239940812962e6f55c1924896f79bd2581d20582a9c752a
+dist/2024-06-11/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=b77e4a1e42c7169d91e268972a9195f7c8494e5cffa5fc71720df799a4eaf74a
+dist/2024-06-11/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=8cf89f982aaa5559f2cd1721edfdc25f5e99518c418e1a6818c566d668c8f842
+dist/2024-06-11/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=7703c27800aa2d871624563380596a18deb90081e38cdf6c05cab8e794e5805c
+dist/2024-06-11/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=ca9dcda51c8945db32e004424eaf26d4f541a51a78be87be0063e5a0b06fdd4f
+dist/2024-06-11/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=59a2173462baaea0cef3e0f088b4e6ef64e2fe469d1833798d92e844f0126902
+dist/2024-06-11/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=0cab2fde15bbfab741eead0b084886f8b640aeb181251368464bd833fd08df73
+dist/2024-06-11/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=8473ef60ff1d5c7aee90b8e0a984c9be7e095446d87e0f13ebcf10f245c0ef0f
+dist/2024-06-11/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=657a55f27794460bad174c4f9412e771c679c6b608cc3dbe32903efb075418da
+dist/2024-06-11/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=bea7aff88f7d7622a23e91c437d9616a9f1adfbd56ddcb42ee33589d064d5161
+dist/2024-06-11/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=a5ab0850c71e322b1042815c443c79505f1daab2b4a69f8cce05e3761a24f10c
+dist/2024-06-11/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=8c00db9c85fa8053f78285c8a546afb32d6b864795388f1ee7a6a49d12643625
+dist/2024-06-11/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=c137f5f943d1c3f14a4a8b5eca2b541c43c82738452646df524e57a6ef0cbd3c
+dist/2024-06-11/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=a4087ded3076e4d487efcd4a957554255ea1fad5052a01529ea1847559f7b40f
+dist/2024-06-11/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=ed2b01ad985668564ba2c3f87dcac4f5c4bcf7ea0b5ecca6a30c1f1c4b63a4ef
+dist/2024-06-11/rustc-nightly-i686-pc-windows-msvc.tar.gz=41db0331bc8f9d164d4198c93234dae41c1b9d2f53d466ee8cdfba4f9704c45b
+dist/2024-06-11/rustc-nightly-i686-pc-windows-msvc.tar.xz=49766cd2ad581f253f3fc0ba4f755a4aeaae954c75d41fa29a9302568e78aa75
+dist/2024-06-11/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=b57be1a1dc9e70c47564253877bc0cbbdde8a8064a6a4bcf68f8adc6b4c5d4df
+dist/2024-06-11/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=cf2c4651297993671f033eb9bb9877b157638bc41cb40ccac3294c3fd13786ef
+dist/2024-06-11/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=619c2eb3ed3f153d2c0ba6cbeb7f0e72c67fbb1e40c025752f94b46c9b740426
+dist/2024-06-11/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=105560769c3672133ecb063ac0a8ef541229490401470180af75151403287d3a
+dist/2024-06-11/rustc-nightly-i686-unknown-linux-gnu.tar.gz=211498f7eb884908c8110ce922183bbd6cc05d96d9c8b5c9068dcfc4d29010cd
+dist/2024-06-11/rustc-nightly-i686-unknown-linux-gnu.tar.xz=61beb47b917ce644defed991afa6d82028cb8f1e6a191cf5c84e8be883ad3870
+dist/2024-06-11/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=06036f5bfc00950e03a66e8dcab0eb7420fd055aadb85bd42e11845eef122122
+dist/2024-06-11/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=39d3dc95b1e0cfcc381d27540d100b8325728ef9a6a8b72a0e4ad85e2e957a63
+dist/2024-06-11/rustc-nightly-x86_64-unknown-freebsd.tar.gz=9b7badc1c8443571aec7b403e890d14846c3972b02159c8aacf3157ede69af9a
+dist/2024-06-11/rustc-nightly-x86_64-unknown-freebsd.tar.xz=a1fdcbe1ca277b22c2dc8aced8ac0f34f841e7a7512fe421c2b045608c4ce07d
+dist/2024-06-11/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=5e6105bc6304ea630a8170c785df11cd435521a2ac90348284898c4aab6ed5f2
+dist/2024-06-11/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=97dc7091b1ffa6a23a4b609a680c1f2f63debab80b5c01bc90fe271d6599bf89
+dist/2024-06-11/rustc-nightly-x86_64-apple-darwin.tar.gz=64769377c3714749acf6404d75f46b00ede0107840e736432d759dbfff15b6f9
+dist/2024-06-11/rustc-nightly-x86_64-apple-darwin.tar.xz=8ce829c39fdf21467307ee540c6b06b510d45c76c395947afdc2e5592d775977
+dist/2024-06-11/rustc-nightly-i686-pc-windows-gnu.tar.gz=4c9425ef2d5fdf9badec75783fe61ce0a251fde672c993c5b0069182449e2d7c
+dist/2024-06-11/rustc-nightly-i686-pc-windows-gnu.tar.xz=442467ab4199e2fb62c69a96cc1c9f03478a415877996f0fef20c54760b2e8b9
+dist/2024-06-11/rustc-nightly-x86_64-unknown-illumos.tar.gz=0b4c3520ff6e5b053a6b37f7d3708fb115fbb99981f337a1786d675e70034acc
+dist/2024-06-11/rustc-nightly-x86_64-unknown-illumos.tar.xz=d192e69dd328e6f930ad5b578065ebab12913762845f68ee55b43ddc9ba074a1
+dist/2024-06-11/rustc-nightly-x86_64-unknown-netbsd.tar.gz=0828f2d9395cdac8e9db6ad5c6b3cab3587fc82bccdec9962cd096e43e4f7793
+dist/2024-06-11/rustc-nightly-x86_64-unknown-netbsd.tar.xz=542f61a4c5a719f2583b0ba820207dc9d09cb9a2bb802da7cfbee5273bbfddfc
+dist/2024-06-11/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=289b1bee22b8d9d84e92461694c6558476f944ac07caf2d22f0c4ccf3d29dbcf
+dist/2024-06-11/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=23c86fc06ed9e7bcf8da72085ff88ec224ccddeca78ddc31032b314cb254ad64
+dist/2024-06-11/rustc-nightly-aarch64-apple-darwin.tar.gz=cf045620e63a5e623047490af956e0daf0bb321ed6a215ae355b8829c047e58e
+dist/2024-06-11/rustc-nightly-aarch64-apple-darwin.tar.xz=0abec976185b9573dbc91868ab4fb84ba2837d25f3fa1d74b3a193609387f3fa
+dist/2024-06-11/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=0b1146e24e4e59e4577b1e40d3ca45096864e87bcf9f258a34b9d9cf5abc3eef
+dist/2024-06-11/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=289e97314fd22da08c8943d1240fa94b1cfd2cdf061dea15bfb582a9d482d6a6
+dist/2024-06-11/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=8957493cf92d57381b35d6ce5bbdb408a05c2a6becc8e2cd37b0502e3ef35ffb
+dist/2024-06-11/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=9015e492f773b91054c53aca92ac704336504959779e4b916d42fc966e6058ea
+dist/2024-06-11/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=aea2dc3831864dc5ea2c389c8208fc82baf1566f4e5688511495db25525e6020
+dist/2024-06-11/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=9b6f1c3b1656ee2037afe170d6909aa037d484897a83679e2115392a35559062
+dist/2024-06-11/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=3a962a42e427675df5d8fbc4e638949ec0669a95ecabcdddf5103a9c19f291ac
+dist/2024-06-11/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=6fe48c92425b41ad7c3e812abe2e5decb117be178a16f6910bd60000fe8f355b
+dist/2024-06-11/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=0a3147dd45cbf54e66b92baec479a5550c63327185baef3df9638c5a740e0921
+dist/2024-06-11/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=d35948d49fa1e526434ca89c2f7542fcfeb86b4ec35bb92f87f387ec37f4ccda
\ No newline at end of file
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 9f33e431274..b4d47cba7c5 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -495,7 +495,7 @@ impl Builder {
                 Some(p) => p,
                 None => return false,
             };
-            pkg.target.get(&c.target).is_some()
+            pkg.target.contains_key(&c.target)
         };
         extensions.retain(&has_component);
         components.retain(&has_component);
diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs
index a3c857b0268..b4522de6897 100644
--- a/src/tools/build_helper/src/git.rs
+++ b/src/tools/build_helper/src/git.rs
@@ -21,7 +21,7 @@ fn output_result(cmd: &mut Command) -> Result<String, String> {
             String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))?
         ));
     }
-    Ok(String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?)
+    String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))
 }
 
 /// Finds the remote for rust-lang/rust.
@@ -64,18 +64,14 @@ pub fn rev_exists(rev: &str, git_dir: Option<&Path>) -> Result<bool, String> {
     match output.status.code() {
         Some(0) => Ok(true),
         Some(128) => Ok(false),
-        None => {
-            return Err(format!(
-                "git didn't exit properly: {}",
-                String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))?
-            ));
-        }
-        Some(code) => {
-            return Err(format!(
-                "git command exited with status code: {code}: {}",
-                String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))?
-            ));
-        }
+        None => Err(format!(
+            "git didn't exit properly: {}",
+            String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))?
+        )),
+        Some(code) => Err(format!(
+            "git command exited with status code: {code}: {}",
+            String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))?
+        )),
     }
 }
 
@@ -96,7 +92,7 @@ pub fn updated_master_branch(
         }
     }
 
-    Err(format!("Cannot find any suitable upstream master branch"))
+    Err("Cannot find any suitable upstream master branch".to_owned())
 }
 
 pub fn get_git_merge_base(
@@ -118,7 +114,7 @@ pub fn get_git_merge_base(
 pub fn get_git_modified_files(
     config: &GitConfig<'_>,
     git_dir: Option<&Path>,
-    extensions: &Vec<&str>,
+    extensions: &[&str],
 ) -> Result<Option<Vec<String>>, String> {
     let merge_base = get_git_merge_base(config, git_dir)?;
 
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 4dcbca118ab7f9ffac4728004c983754bc6a04f
+Subproject a1f47ec3f7cd076986f1bfcd7061f2e8cb1a726
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index d5115f70f66..d7bcd7a1968 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,11 +6,69 @@ document.
 
 ## Unreleased / Beta / In Rust Nightly
 
-[93f0a9a9...master](https://github.com/rust-lang/rust-clippy/compare/93f0a9a9...master)
+[ca3b3937...master](https://github.com/rust-lang/rust-clippy/compare/ca3b3937...master)
+
+## Rust 1.79
+
+Current stable, released 2024-06-13
+
+[View all 102 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-03-08T11%3A13%3A58Z..2024-04-18T15%3A50%3A50Z+base%3Amaster)
+
+### New Lints
+
+* Added [`legacy_numeric_constants`] to `style`
+  [#12312](https://github.com/rust-lang/rust-clippy/pull/12312)
+* Added [`missing_transmute_annotations`] to `suspicious`
+  [#12239](https://github.com/rust-lang/rust-clippy/pull/12239)
+* Added [`integer_division_remainder_used`] to `restriction`
+  [#12451](https://github.com/rust-lang/rust-clippy/pull/12451)
+* Added [`duplicated_attributes`] to `suspicious`
+  [#12378](https://github.com/rust-lang/rust-clippy/pull/12378)
+* Added [`manual_unwrap_or_default`] to `suspicious`
+  [#12440](https://github.com/rust-lang/rust-clippy/pull/12440)
+* Added [`zero_repeat_side_effects`] to `suspicious`
+  [#12449](https://github.com/rust-lang/rust-clippy/pull/12449)
+* Added [`const_is_empty`] to `suspicious`
+  [#12310](https://github.com/rust-lang/rust-clippy/pull/12310)
+
+### Moves and Deprecations
+
+* Moved [`box_default`] to `style` (From `perf`)
+  [#12601](https://github.com/rust-lang/rust-clippy/pull/12601)
+* Moved [`manual_clamp`] to `complexity` (From `nursery` now warn-by-default)
+  [#12543](https://github.com/rust-lang/rust-clippy/pull/12543)
+* Moved [`readonly_write_lock`] to `perf` (From `nursery` now warn-by-default)
+  [#12479](https://github.com/rust-lang/rust-clippy/pull/12479)
+
+### Enhancements
+
+* [`module_name_repetitions`]: Added the [`allowed-prefixes`] configuration to allow common prefixes.
+  [#12573](https://github.com/rust-lang/rust-clippy/pull/12573)
+* [`cast_sign_loss`], [`cast_possible_truncation`], [`cast_lossless`]: Are now allowed in macros
+  [#12631](https://github.com/rust-lang/rust-clippy/pull/12631)
+* [`manual_clamp`]: Now only lints on constant min and max values
+  [#12543](https://github.com/rust-lang/rust-clippy/pull/12543)
+* [`assigning_clones`]: Now considers the [`msrv`] configuration
+  [#12511](https://github.com/rust-lang/rust-clippy/pull/12511)
+* [`needless_return`], [`useless_let_if_seq`], [`mut_mut`], [`read_zero_byte_vec`], [`unused_io_amount`],
+  [`unused_peekable`]: Now respects `#[allow]` attributes on the affected statement instead
+  [#12446](https://github.com/rust-lang/rust-clippy/pull/12446)
+
+### False Positive Fixes
+
+* [`cast_lossless`]: No longer lints when casting to `u128`
+  [#12496](https://github.com/rust-lang/rust-clippy/pull/12496)
+* [`std_instead_of_core`] No longer lints on modules that are only in `std`
+  [#12447](https://github.com/rust-lang/rust-clippy/pull/12447)
+
+### ICE Fixes
+
+* [`needless_return`]: No longer crashes on non-ascii characters
+  [#12493](https://github.com/rust-lang/rust-clippy/pull/12493)
 
 ## Rust 1.78
 
-Current stable, released 2024-05-02
+Released 2024-05-02
 
 [View all 112 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-01-26T05%3A46%3A23Z..2024-03-07T16%3A25%3A52Z+base%3Amaster)
 
@@ -5474,6 +5532,7 @@ Released 2018-09-13
 [`manual_next_back`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_next_back
 [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive
 [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or
+[`manual_pattern_char_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_pattern_char_comparison
 [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains
 [`manual_range_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_patterns
 [`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid
@@ -5567,6 +5626,7 @@ Released 2018-09-13
 [`needless_borrow`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
 [`needless_borrowed_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference
 [`needless_borrows_for_generic_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args
+[`needless_character_iteration`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_character_iteration
 [`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect
 [`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue
 [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main
@@ -5576,6 +5636,7 @@ Released 2018-09-13
 [`needless_late_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_late_init
 [`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
 [`needless_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_match
+[`needless_maybe_sized`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_maybe_sized
 [`needless_option_as_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_as_deref
 [`needless_option_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_take
 [`needless_parens_on_range_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_parens_on_range_literals
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index b48f3ab3919..43788499055 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.1.80"
+version = "0.1.81"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index fa18447090c..ec76a6dfb08 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -172,7 +172,7 @@ You can add options to your code to `allow`/`warn`/`deny` Clippy lints:
 
 Note: `allow` means to suppress the lint for your code. With `warn` the lint
 will only emit a warning, while with `deny` the lint will emit an error, when
-triggering for your code. An error causes clippy to exit with an error code, so
+triggering for your code. An error causes Clippy to exit with an error code, so
 is useful in scripts like CI/CD.
 
 If you do not want to include your lint levels in your code, you can globally
@@ -238,7 +238,7 @@ define the `CLIPPY_DISABLE_DOCS_LINKS` environment variable.
 ### Specifying the minimum supported Rust version
 
 Projects that intend to support old versions of Rust can disable lints pertaining to newer features by
-specifying the minimum supported Rust version (MSRV) in the clippy configuration file.
+specifying the minimum supported Rust version (MSRV) in the Clippy configuration file.
 
 ```toml
 msrv = "1.30.0"
diff --git a/src/tools/clippy/book/src/configuration.md b/src/tools/clippy/book/src/configuration.md
index ea549e4df4a..b1305443189 100644
--- a/src/tools/clippy/book/src/configuration.md
+++ b/src/tools/clippy/book/src/configuration.md
@@ -99,7 +99,7 @@ For more details and options, refer to the Cargo documentation.
 ### Specifying the minimum supported Rust version
 
 Projects that intend to support old versions of Rust can disable lints pertaining to newer features by specifying the
-minimum supported Rust version (MSRV) in the clippy configuration file.
+minimum supported Rust version (MSRV) in the Clippy configuration file.
 
 ```toml
 msrv = "1.30.0"
diff --git a/src/tools/clippy/book/src/development/basics.md b/src/tools/clippy/book/src/development/basics.md
index f4c109ff119..166b6aab9fb 100644
--- a/src/tools/clippy/book/src/development/basics.md
+++ b/src/tools/clippy/book/src/development/basics.md
@@ -107,7 +107,7 @@ More about [intellij] command usage and reasons.
 
 ## lintcheck
 
-`cargo lintcheck` will build and run clippy on a fixed set of crates and
+`cargo lintcheck` will build and run Clippy on a fixed set of crates and
 generate a log of the results.  You can `git diff` the updated log against its
 previous version and see what impact your lint made on a small set of crates.
 If you add a new lint, please audit the resulting warnings and make sure there
diff --git a/src/tools/clippy/book/src/development/defining_lints.md b/src/tools/clippy/book/src/development/defining_lints.md
index 806ed0845f0..ceabb255e2d 100644
--- a/src/tools/clippy/book/src/development/defining_lints.md
+++ b/src/tools/clippy/book/src/development/defining_lints.md
@@ -163,11 +163,11 @@ declare_clippy_lint! {
     ///
     /// ### Example
     /// ```rust
-    /// // example code where clippy issues a warning
+    /// // example code where Clippy issues a warning
     /// ```
     /// Use instead:
     /// ```rust
-    /// // example code which does not raise clippy warning
+    /// // example code which does not raise Clippy warning
     /// ```
     #[clippy::version = "1.70.0"] // <- In which version was this implemented, keep it up to date!
     pub LINT_NAME, // <- The lint name IN_ALL_CAPS
diff --git a/src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md b/src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md
index 285488cec55..92fbf733a8f 100644
--- a/src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md
+++ b/src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md
@@ -428,7 +428,7 @@ selection of possible matches is produced by the pattern syntax. In the second
 stage, the named subpattern references can be used to do additional tests like
 asserting that a node hasn't been created as part of a macro expansion.
 
-## Implementing clippy lints using patterns
+## Implementing Clippy lints using patterns
 
 As a "real-world" example, I re-implemented the `collapsible_if` lint using
 patterns. The code can be found
@@ -572,7 +572,7 @@ The pattern syntax and the *PatternTree* are independent of specific syntax tree
 implementations (rust ast / hir, syn, ...). When looking at the different
 pattern examples in the previous sections, it can be seen that the patterns
 don't contain any information specific to a certain syntax tree implementation.
-In contrast, clippy lints currently match against ast / hir syntax tree nodes
+In contrast, Clippy lints currently match against ast / hir syntax tree nodes
 and therefore directly depend on their implementation.
 
 The connection between the *PatternTree* and specific syntax tree
@@ -690,7 +690,7 @@ change, only the `IsMatch` trait implementations need to be adapted and existing
 lints can remain unchanged. This also means that if the `IsMatch` trait
 implementations were integrated into the compiler, updating the `IsMatch`
 implementations would be required for the compiler to compile successfully. This
-could reduce the number of times clippy breaks because of changes in the
+could reduce the number of times Clippy breaks because of changes in the
 compiler. Another advantage of the pattern's independence is that converting an
 `EarlyLintPass` lint into a `LatePassLint` wouldn't require rewriting the whole
 pattern matching code. In fact, the pattern might work just fine without any
@@ -777,7 +777,7 @@ complexity to solve a relatively minor problem.
 
 The issue of users not knowing about the *PatternTree* structure could be solved
 by a tool that, given a rust program, generates a pattern that matches only this
-program (similar to the clippy author lint).
+program (similar to the Clippy author lint).
 
 For some simple cases (like the first example above), it might be possible to
 successfully mix Rust and pattern syntax. This space could be further explored
@@ -789,7 +789,7 @@ The pattern syntax is heavily inspired by regular expressions (repetitions,
 alternatives, sequences, ...).
 
 From what I've seen until now, other linters also implement lints that directly
-work on syntax tree data structures, just like clippy does currently. I would
+work on syntax tree data structures, just like Clippy does currently. I would
 therefore consider the pattern syntax to be *new*, but please correct me if I'm
 wrong.
 
@@ -982,5 +982,5 @@ pattern!{
 }
 ```
 
-In the future, clippy could use this system to also provide lints for custom
+In the future, Clippy could use this system to also provide lints for custom
 syntaxes like those found in macros.
diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml
index 7f7dc9d6cfb..be0b048ac0c 100644
--- a/src/tools/clippy/clippy_config/Cargo.toml
+++ b/src/tools/clippy/clippy_config/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_config"
-version = "0.1.80"
+version = "0.1.81"
 edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/src/tools/clippy/clippy_dummy/PUBLISH.md b/src/tools/clippy/clippy_dummy/PUBLISH.md
index 8e420ec959a..f0021f1594f 100644
--- a/src/tools/clippy/clippy_dummy/PUBLISH.md
+++ b/src/tools/clippy/clippy_dummy/PUBLISH.md
@@ -1,5 +1,5 @@
 This is a dummy crate to publish to crates.io. It primarily exists to ensure
-that folks trying to install clippy from crates.io get redirected to the
+that folks trying to install Clippy from crates.io get redirected to the
 `rustup` technique.
 
 Before publishing, be sure to rename `clippy_dummy` to `clippy` in `Cargo.toml`,
diff --git a/src/tools/clippy/clippy_dummy/crates-readme.md b/src/tools/clippy/clippy_dummy/crates-readme.md
index 0decae8b910..a8ec0a1c36c 100644
--- a/src/tools/clippy/clippy_dummy/crates-readme.md
+++ b/src/tools/clippy/clippy_dummy/crates-readme.md
@@ -1,9 +1,9 @@
-Installing clippy via crates.io is deprecated. Please use the following:
+Installing Clippy via crates.io is deprecated. Please use the following:
 
 ```terminal
 rustup component add clippy
 ```
 
-on a Rust version 1.29 or later. You may need to run `rustup self update` if it complains about a missing clippy binary.
+on a Rust version 1.29 or later. You may need to run `rustup self update` if it complains about a missing Clippy binary.
 
 See [the homepage](https://github.com/rust-lang/rust-clippy/#clippy) for more information
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 5e3a119337c..5708ffba08f 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_lints"
-version = "0.1.80"
+version = "0.1.81"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
diff --git a/src/tools/clippy/clippy_lints/src/attrs/maybe_misused_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/maybe_misused_cfg.rs
deleted file mode 100644
index e6b2e835be8..00000000000
--- a/src/tools/clippy/clippy_lints/src/attrs/maybe_misused_cfg.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-use super::{Attribute, MAYBE_MISUSED_CFG};
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use rustc_ast::{MetaItemKind, NestedMetaItem};
-use rustc_errors::Applicability;
-use rustc_lint::EarlyContext;
-use rustc_span::sym;
-
-pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
-    if attr.has_name(sym::cfg)
-        && let Some(items) = attr.meta_item_list()
-    {
-        check_nested_misused_cfg(cx, &items);
-    }
-}
-
-fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
-    for item in items {
-        if let NestedMetaItem::MetaItem(meta) = item {
-            if let Some(ident) = meta.ident()
-                && ident.name.as_str() == "features"
-                && let Some(val) = meta.value_str()
-            {
-                span_lint_and_sugg(
-                    cx,
-                    MAYBE_MISUSED_CFG,
-                    meta.span,
-                    "'feature' may be misspelled as 'features'",
-                    "did you mean",
-                    format!("feature = \"{val}\""),
-                    Applicability::MaybeIncorrect,
-                );
-            }
-            if let MetaItemKind::List(list) = &meta.kind {
-                check_nested_misused_cfg(cx, list);
-            // If this is not a list, then we check for `cfg(test)`.
-            } else if let Some(ident) = meta.ident()
-                && matches!(ident.name.as_str(), "tests" | "Test")
-            {
-                span_lint_and_sugg(
-                    cx,
-                    MAYBE_MISUSED_CFG,
-                    meta.span,
-                    format!("'test' may be misspelled as '{}'", ident.name.as_str()),
-                    "did you mean",
-                    "test".to_string(),
-                    Applicability::MaybeIncorrect,
-                );
-            }
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mismatched_target_os.rs b/src/tools/clippy/clippy_lints/src/attrs/mismatched_target_os.rs
deleted file mode 100644
index b1cc0a763c5..00000000000
--- a/src/tools/clippy/clippy_lints/src/attrs/mismatched_target_os.rs
+++ /dev/null
@@ -1,90 +0,0 @@
-use super::{Attribute, MISMATCHED_TARGET_OS};
-use clippy_utils::diagnostics::span_lint_and_then;
-use rustc_ast::{MetaItemKind, NestedMetaItem};
-use rustc_errors::Applicability;
-use rustc_lint::EarlyContext;
-use rustc_span::{sym, Span};
-
-static UNIX_SYSTEMS: &[&str] = &[
-    "android",
-    "dragonfly",
-    "emscripten",
-    "freebsd",
-    "fuchsia",
-    "haiku",
-    "illumos",
-    "ios",
-    "l4re",
-    "linux",
-    "macos",
-    "netbsd",
-    "openbsd",
-    "redox",
-    "solaris",
-    "vxworks",
-];
-
-// NOTE: windows is excluded from the list because it's also a valid target family.
-static NON_UNIX_SYSTEMS: &[&str] = &["hermit", "none", "wasi"];
-
-pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
-    fn find_os(name: &str) -> Option<&'static str> {
-        UNIX_SYSTEMS
-            .iter()
-            .chain(NON_UNIX_SYSTEMS.iter())
-            .find(|&&os| os == name)
-            .copied()
-    }
-
-    fn is_unix(name: &str) -> bool {
-        UNIX_SYSTEMS.iter().any(|&os| os == name)
-    }
-
-    fn find_mismatched_target_os(items: &[NestedMetaItem]) -> Vec<(&str, Span)> {
-        let mut mismatched = Vec::new();
-
-        for item in items {
-            if let NestedMetaItem::MetaItem(meta) = item {
-                match &meta.kind {
-                    MetaItemKind::List(list) => {
-                        mismatched.extend(find_mismatched_target_os(list));
-                    },
-                    MetaItemKind::Word => {
-                        if let Some(ident) = meta.ident()
-                            && let Some(os) = find_os(ident.name.as_str())
-                        {
-                            mismatched.push((os, ident.span));
-                        }
-                    },
-                    MetaItemKind::NameValue(..) => {},
-                }
-            }
-        }
-
-        mismatched
-    }
-
-    if attr.has_name(sym::cfg)
-        && let Some(list) = attr.meta_item_list()
-        && let mismatched = find_mismatched_target_os(&list)
-        && !mismatched.is_empty()
-    {
-        let mess = "operating system used in target family position";
-
-        span_lint_and_then(cx, MISMATCHED_TARGET_OS, attr.span, mess, |diag| {
-            // Avoid showing the unix suggestion multiple times in case
-            // we have more than one mismatch for unix-like systems
-            let mut unix_suggested = false;
-
-            for (os, span) in mismatched {
-                let sugg = format!("target_os = \"{os}\"");
-                diag.span_suggestion(span, "try", sugg, Applicability::MaybeIncorrect);
-
-                if !unix_suggested && is_unix(os) {
-                    diag.help("did you mean `unix`?");
-                    unix_suggested = true;
-                }
-            }
-        });
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
index a24bd5ed44b..e4c98a32fd6 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
@@ -7,8 +7,6 @@ mod deprecated_semver;
 mod duplicated_attributes;
 mod empty_line_after;
 mod inline_always;
-mod maybe_misused_cfg;
-mod mismatched_target_os;
 mod mixed_attributes_style;
 mod non_minimal_cfg;
 mod should_panic_without_expect;
@@ -272,39 +270,6 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for cfg attributes having operating systems used in target family position.
-    ///
-    /// ### Why is this bad?
-    /// The configuration option will not be recognised and the related item will not be included
-    /// by the conditional compilation engine.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// #[cfg(linux)]
-    /// fn conditional() { }
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// # mod hidden {
-    /// #[cfg(target_os = "linux")]
-    /// fn conditional() { }
-    /// # }
-    ///
-    /// // or
-    ///
-    /// #[cfg(unix)]
-    /// fn conditional() { }
-    /// ```
-    /// Check the [Rust Reference](https://doc.rust-lang.org/reference/conditional-compilation.html#target_os) for more details.
-    #[clippy::version = "1.45.0"]
-    pub MISMATCHED_TARGET_OS,
-    correctness,
-    "usage of `cfg(operating_system)` instead of `cfg(target_os = \"operating_system\")`"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
     /// Checks for attributes that allow lints without a reason.
     ///
     /// (This requires the `lint_reasons` feature)
@@ -393,38 +358,6 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for `#[cfg(features = "...")]` and suggests to replace it with
-    /// `#[cfg(feature = "...")]`.
-    ///
-    /// It also checks if `cfg(test)` was misspelled.
-    ///
-    /// ### Why is this bad?
-    /// Misspelling `feature` as `features` or `test` as `tests` can be sometimes hard to spot. It
-    /// may cause conditional compilation not work quietly.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// #[cfg(features = "some-feature")]
-    /// fn conditional() { }
-    /// #[cfg(tests)]
-    /// mod tests { }
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// #[cfg(feature = "some-feature")]
-    /// fn conditional() { }
-    /// #[cfg(test)]
-    /// mod tests { }
-    /// ```
-    #[clippy::version = "1.69.0"]
-    pub MAYBE_MISUSED_CFG,
-    suspicious,
-    "prevent from misusing the wrong attr name"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
     /// Checks for `#[cfg_attr(feature = "cargo-clippy", ...)]` and for
     /// `#[cfg(feature = "cargo-clippy")]` and suggests to replace it with
     /// `#[cfg_attr(clippy, ...)]` or `#[cfg(clippy)]`.
@@ -530,7 +463,7 @@ declare_clippy_lint! {
     /// #[allow(dead_code)]
     /// fn foo() {}
     /// ```
-    #[clippy::version = "1.78.0"]
+    #[clippy::version = "1.79.0"]
     pub DUPLICATED_ATTRIBUTES,
     suspicious,
     "duplicated attribute"
@@ -612,11 +545,9 @@ pub struct EarlyAttributes {
 
 impl_lint_pass!(EarlyAttributes => [
     DEPRECATED_CFG_ATTR,
-    MISMATCHED_TARGET_OS,
     EMPTY_LINE_AFTER_OUTER_ATTR,
     EMPTY_LINE_AFTER_DOC_COMMENTS,
     NON_MINIMAL_CFG,
-    MAYBE_MISUSED_CFG,
     DEPRECATED_CLIPPY_CFG_ATTR,
     UNNECESSARY_CLIPPY_CFG,
 ]);
@@ -629,9 +560,7 @@ impl EarlyLintPass for EarlyAttributes {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
         deprecated_cfg_attr::check(cx, attr, &self.msrv);
         deprecated_cfg_attr::check_clippy(cx, attr);
-        mismatched_target_os::check(cx, attr);
         non_minimal_cfg::check(cx, attr);
-        maybe_misused_cfg::check(cx, attr);
     }
 
     extract_msrv_attr!(EarlyContext);
diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs
index 171f3031860..eb05dc96cde 100644
--- a/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs
+++ b/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs
@@ -1,15 +1,11 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_block_with_applicability;
-use clippy_utils::ty::implements_trait;
-use clippy_utils::visitors::{for_each_expr, Descend};
-use clippy_utils::{get_parent_expr, higher, is_from_proc_macro};
-use core::ops::ControlFlow;
+use clippy_utils::{higher, is_from_proc_macro};
 use rustc_errors::Applicability;
 use rustc_hir::{BlockCheckMode, Expr, ExprKind, MatchSource};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::declare_lint_pass;
-use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -124,30 +120,6 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions {
                     );
                 }
             }
-        } else {
-            let _: Option<!> = for_each_expr(cond, |e| {
-                if let ExprKind::Closure(closure) = e.kind {
-                    // do not lint if the closure is called using an iterator (see #1141)
-                    if let Some(parent) = get_parent_expr(cx, e)
-                        && let ExprKind::MethodCall(_, self_arg, _, _) = &parent.kind
-                        && let caller = cx.typeck_results().expr_ty(self_arg)
-                        && let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator)
-                        && implements_trait(cx, caller, iter_id, &[])
-                    {
-                        return ControlFlow::Continue(Descend::No);
-                    }
-
-                    let body = cx.tcx.hir().body(closure.body);
-                    let ex = &body.value;
-                    if let ExprKind::Block(block, _) = ex.kind {
-                        if !body.value.span.from_expansion() && !block.stmts.is_empty() {
-                            span_lint(cx, BLOCKS_IN_CONDITIONS, ex.span, complex_block_message.clone());
-                            return ControlFlow::Continue(Descend::No);
-                        }
-                    }
-                }
-                ControlFlow::Continue(Descend::Yes)
-            });
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index b6341b3fe8e..a1c6c0b608f 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -174,6 +174,25 @@ fn check_inverted_bool_in_condition(
     );
 }
 
+fn check_simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) {
+    if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind
+        && !expr.span.from_expansion()
+        && !inner.span.from_expansion()
+        && let Some(suggestion) = simplify_not(cx, inner)
+        && cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow
+    {
+        span_lint_and_sugg(
+            cx,
+            NONMINIMAL_BOOL,
+            expr.span,
+            "this boolean expression can be simplified",
+            "try",
+            suggestion,
+            Applicability::MachineApplicable,
+        );
+    }
+}
+
 struct NonminimalBoolVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
 }
@@ -232,6 +251,11 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
                 _ => (),
             }
         }
+
+        if self.cx.typeck_results().expr_ty(e).is_never() {
+            return Err("contains never type".to_owned());
+        }
+
         for (n, expr) in self.terminals.iter().enumerate() {
             if eq_expr_value(self.cx, e, expr) {
                 #[expect(clippy::cast_possible_truncation)]
@@ -542,8 +566,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
                 }
             };
             if improvements.is_empty() {
-                let mut visitor = NotSimplificationVisitor { cx: self.cx };
-                visitor.visit_expr(e);
+                check_simplify_not(self.cx, e);
             } else {
                 nonminimal_bool_lint(
                     improvements
@@ -586,30 +609,3 @@ fn implements_ord(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         .get_diagnostic_item(sym::Ord)
         .map_or(false, |id| implements_trait(cx, ty, id, &[]))
 }
-
-struct NotSimplificationVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-        if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind
-            && !expr.span.from_expansion()
-            && !inner.span.from_expansion()
-            && let Some(suggestion) = simplify_not(self.cx, inner)
-            && self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow
-        {
-            span_lint_and_sugg(
-                self.cx,
-                NONMINIMAL_BOOL,
-                expr.span,
-                "this boolean expression can be simplified",
-                "try",
-                suggestion,
-                Applicability::MachineApplicable,
-            );
-        }
-
-        walk_expr(self, expr);
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs b/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs
index 0d9eaac882f..e924542fea2 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs
@@ -71,12 +71,6 @@ struct CargoToml {
     workspace: Workspace,
 }
 
-#[derive(Default, Debug)]
-struct LintsAndGroups {
-    lints: Vec<Spanned<String>>,
-    groups: Vec<(Spanned<String>, Spanned<LintConfig>)>,
-}
-
 fn toml_span(range: Range<usize>, file: &SourceFile) -> Span {
     Span::new(
         file.start_pos + BytePos::from_usize(range.start),
@@ -86,27 +80,28 @@ fn toml_span(range: Range<usize>, file: &SourceFile) -> Span {
     )
 }
 
-fn check_table(cx: &LateContext<'_>, table: LintTable, groups: &FxHashSet<&str>, file: &SourceFile) {
-    let mut by_priority = BTreeMap::<_, LintsAndGroups>::new();
+fn check_table(cx: &LateContext<'_>, table: LintTable, known_groups: &FxHashSet<&str>, file: &SourceFile) {
+    let mut lints = Vec::new();
+    let mut groups = Vec::new();
     for (name, config) in table {
-        let lints_and_groups = by_priority.entry(config.as_ref().priority()).or_default();
-        if groups.contains(name.get_ref().as_str()) {
-            lints_and_groups.groups.push((name, config));
+        if name.get_ref() == "warnings" {
+            continue;
+        }
+
+        if known_groups.contains(name.get_ref().as_str()) {
+            groups.push((name, config));
         } else {
-            lints_and_groups.lints.push(name);
+            lints.push((name, config.into_inner()));
         }
     }
-    let low_priority = by_priority
-        .iter()
-        .find(|(_, lints_and_groups)| !lints_and_groups.lints.is_empty())
-        .map_or(-1, |(&lowest_lint_priority, _)| lowest_lint_priority - 1);
 
-    for (priority, LintsAndGroups { lints, groups }) in by_priority {
-        let Some(last_lint_alphabetically) = lints.last() else {
-            continue;
-        };
-
-        for (group, config) in groups {
+    for (group, group_config) in groups {
+        let priority = group_config.get_ref().priority();
+        let level = group_config.get_ref().level();
+        if let Some((conflict, _)) = lints
+            .iter()
+            .rfind(|(_, lint_config)| lint_config.priority() == priority && lint_config.level() != level)
+        {
             span_lint_and_then(
                 cx,
                 LINT_GROUPS_PRIORITY,
@@ -116,22 +111,23 @@ fn check_table(cx: &LateContext<'_>, table: LintTable, groups: &FxHashSet<&str>,
                     group.as_ref()
                 ),
                 |diag| {
-                    let config_span = toml_span(config.span(), file);
-                    if config.as_ref().is_implicit() {
+                    let config_span = toml_span(group_config.span(), file);
+
+                    if group_config.as_ref().is_implicit() {
                         diag.span_label(config_span, "has an implicit priority of 0");
                     }
-                    // add the label to next lint after this group that has the same priority
-                    let lint = lints
-                        .iter()
-                        .filter(|lint| lint.span().start > group.span().start)
-                        .min_by_key(|lint| lint.span().start)
-                        .unwrap_or(last_lint_alphabetically);
-                    diag.span_label(toml_span(lint.span(), file), "has the same priority as this lint");
+                    diag.span_label(toml_span(conflict.span(), file), "has the same priority as this lint");
                     diag.note("the order of the lints in the table is ignored by Cargo");
+
                     let mut suggestion = String::new();
+                    let low_priority = lints
+                        .iter()
+                        .map(|(_, config)| config.priority().saturating_sub(1))
+                        .min()
+                        .unwrap_or(-1);
                     Serialize::serialize(
                         &LintConfigTable {
-                            level: config.as_ref().level().into(),
+                            level: level.into(),
                             priority: Some(low_priority),
                         },
                         toml::ser::ValueSerializer::new(&mut suggestion),
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
index 864489ee3fc..8bbd41b0db1 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
 
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{for_each_expr_without_closures, Descend};
 use clippy_utils::{method_chain_args, sext};
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -266,7 +266,7 @@ fn expr_add_sign(cx: &LateContext<'_>, expr: &Expr<'_>) -> Sign {
 fn exprs_with_muldiv_binop_peeled<'e>(expr: &'e Expr<'_>) -> Vec<&'e Expr<'e>> {
     let mut res = vec![];
 
-    for_each_expr(expr, |sub_expr| -> ControlFlow<Infallible, Descend> {
+    for_each_expr_without_closures(expr, |sub_expr| -> ControlFlow<Infallible, Descend> {
         // We don't check for mul/div/rem methods here, but we could.
         if let ExprKind::Binary(op, lhs, _rhs) = sub_expr.kind {
             if matches!(op.node, BinOpKind::Mul | BinOpKind::Div) {
@@ -315,7 +315,7 @@ fn exprs_with_muldiv_binop_peeled<'e>(expr: &'e Expr<'_>) -> Vec<&'e Expr<'e>> {
 fn exprs_with_add_binop_peeled<'e>(expr: &'e Expr<'_>) -> Vec<&'e Expr<'e>> {
     let mut res = vec![];
 
-    for_each_expr(expr, |sub_expr| -> ControlFlow<Infallible, Descend> {
+    for_each_expr_without_closures(expr, |sub_expr| -> ControlFlow<Infallible, Descend> {
         // We don't check for add methods here, but we could.
         if let ExprKind::Binary(op, _lhs, _rhs) = sub_expr.kind {
             if matches!(op.node, BinOpKind::Add) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
index a7f7bf7854e..fb0b0cba6a6 100644
--- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::numeric_literal::NumericLiteral;
 use clippy_utils::source::snippet_opt;
-use clippy_utils::visitors::{for_each_expr, Visitable};
+use clippy_utils::visitors::{for_each_expr_without_closures, Visitable};
 use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
 use rustc_ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
@@ -245,7 +245,7 @@ fn fp_ty_mantissa_nbits(typ: Ty<'_>) -> u32 {
 /// TODO: Maybe we should move this to `clippy_utils` so others won't need to go down this dark,
 /// dark path reimplementing this (or something similar).
 fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx>, cast_from: Ty<'tcx>) -> bool {
-    for_each_expr(expr, |expr| {
+    for_each_expr_without_closures(expr, |expr| {
         // Calls are a `Path`, and usage of locals are a `Path`. So, this checks
         // - call() as i32
         // - local as i32
diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index ee1bb63b50d..e41abf42234 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -3,7 +3,7 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::visitors::for_each_expr;
+use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{get_async_fn_body, is_async_fn, LimitStack};
 use core::ops::ControlFlow;
 use rustc_ast::ast::Attribute;
@@ -65,7 +65,7 @@ impl CognitiveComplexity {
 
         let mut cc = 1u64;
         let mut returns = 0u64;
-        let _: Option<!> = for_each_expr(expr, |e| {
+        let _: Option<!> = for_each_expr_without_closures(expr, |e| {
             match e.kind {
                 ExprKind::If(_, _, _) => {
                     cc += 1;
diff --git a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
index 70856b80881..28d9f68d504 100644
--- a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
+++ b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
-use clippy_utils::visitors::{for_each_expr_with_closures, Visitable};
+use clippy_utils::visitors::{for_each_expr, Visitable};
 use clippy_utils::{get_enclosing_block, path_to_local_id};
 use core::ops::ControlFlow;
 use rustc_hir::{Body, ExprKind, HirId, LangItem, LetStmt, Node, PatKind};
@@ -82,7 +82,7 @@ fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirI
     let mut has_read_access = false;
 
     // Inspect all expressions and sub-expressions in the block.
-    for_each_expr_with_closures(cx, block, |expr| {
+    for_each_expr(cx, block, |expr| {
         // Ignore expressions that are not simply `id`.
         if !path_to_local_id(expr, id) {
             return ControlFlow::Continue(());
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index ccf1d9d6f8c..480df675d75 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then};
 use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, snippet_opt};
 use clippy_utils::ty::{needs_ordered_drop, InteriorMut};
-use clippy_utils::visitors::for_each_expr;
+use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{
     capture_local_usage, eq_expr_value, find_binding_init, get_enclosing_block, hash_expr, hash_stmt, if_sequence,
     is_else_clause, is_lint_allowed, path_to_local, search_same, ContainsName, HirEqInterExpr, SpanlessEq,
@@ -362,7 +362,7 @@ fn eq_binding_names(s: &Stmt<'_>, names: &[(HirId, Symbol)]) -> bool {
 
 /// Checks if the statement modifies or moves any of the given locals.
 fn modifies_any_local<'tcx>(cx: &LateContext<'tcx>, s: &'tcx Stmt<'_>, locals: &HirIdSet) -> bool {
-    for_each_expr(s, |e| {
+    for_each_expr_without_closures(s, |e| {
         if let Some(id) = path_to_local(e)
             && locals.contains(&id)
             && !capture_local_usage(cx, e).is_imm_ref()
@@ -413,7 +413,7 @@ fn scan_block_for_eq<'tcx>(
 
     let mut cond_locals = HirIdSet::default();
     for &cond in conds {
-        let _: Option<!> = for_each_expr(cond, |e| {
+        let _: Option<!> = for_each_expr_without_closures(cond, |e| {
             if let Some(id) = path_to_local(e) {
                 cond_locals.insert(id);
             }
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index df2ef465700..7e43a99e9f2 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -58,8 +58,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO,
     crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
     crate::attrs::INLINE_ALWAYS_INFO,
-    crate::attrs::MAYBE_MISUSED_CFG_INFO,
-    crate::attrs::MISMATCHED_TARGET_OS_INFO,
     crate::attrs::MIXED_ATTRIBUTES_STYLE_INFO,
     crate::attrs::NON_MINIMAL_CFG_INFO,
     crate::attrs::SHOULD_PANIC_WITHOUT_EXPECT_INFO,
@@ -419,6 +417,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::MAP_UNWRAP_OR_INFO,
     crate::methods::MUT_MUTEX_LOCK_INFO,
     crate::methods::NAIVE_BYTECOUNT_INFO,
+    crate::methods::NEEDLESS_CHARACTER_ITERATION_INFO,
     crate::methods::NEEDLESS_COLLECT_INFO,
     crate::methods::NEEDLESS_OPTION_AS_DEREF_INFO,
     crate::methods::NEEDLESS_OPTION_TAKE_INFO,
@@ -449,7 +448,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::SEEK_TO_START_INSTEAD_OF_REWIND_INFO,
     crate::methods::SHOULD_IMPLEMENT_TRAIT_INFO,
     crate::methods::SINGLE_CHAR_ADD_STR_INFO,
-    crate::methods::SINGLE_CHAR_PATTERN_INFO,
     crate::methods::SKIP_WHILE_NEXT_INFO,
     crate::methods::STABLE_SORT_PRIMITIVE_INFO,
     crate::methods::STRING_EXTEND_CHARS_INFO,
@@ -531,6 +529,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::needless_for_each::NEEDLESS_FOR_EACH_INFO,
     crate::needless_if::NEEDLESS_IF_INFO,
     crate::needless_late_init::NEEDLESS_LATE_INIT_INFO,
+    crate::needless_maybe_sized::NEEDLESS_MAYBE_SIZED_INFO,
     crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO,
     crate::needless_pass_by_ref_mut::NEEDLESS_PASS_BY_REF_MUT_INFO,
     crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO,
@@ -656,6 +655,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::std_instead_of_core::ALLOC_INSTEAD_OF_CORE_INFO,
     crate::std_instead_of_core::STD_INSTEAD_OF_ALLOC_INFO,
     crate::std_instead_of_core::STD_INSTEAD_OF_CORE_INFO,
+    crate::string_patterns::MANUAL_PATTERN_CHAR_COMPARISON_INFO,
+    crate::string_patterns::SINGLE_CHAR_PATTERN_INFO,
     crate::strings::STRING_ADD_INFO,
     crate::strings::STRING_ADD_ASSIGN_INFO,
     crate::strings::STRING_FROM_UTF8_AS_BYTES_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
index 9aa5af3190f..a0900f46f6a 100644
--- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
@@ -215,3 +215,29 @@ declare_deprecated_lint! {
     pub WRONG_PUB_SELF_CONVENTION,
     "set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items"
 }
+
+declare_deprecated_lint! {
+    /// ### What it does
+    /// Nothing. This lint has been deprecated.
+    ///
+    /// ### Deprecation reason
+    /// This lint has been superseded by rustc's own [`unexpected_cfgs`] lint that is able to detect the `#[cfg(features)]` and `#[cfg(tests)]` typos.
+    ///
+    /// [`unexpected_cfgs`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unexpected-cfgs
+    #[clippy::version = "1.80.0"]
+    pub MAYBE_MISUSED_CFG,
+    "this lint has been replaced by `unexpected_cfgs`"
+}
+
+declare_deprecated_lint! {
+    /// ### What it does
+    /// Nothing. This lint has been deprecated.
+    ///
+    /// ### Deprecation reason
+    /// This lint has been superseded by rustc's own [`unexpected_cfgs`] lint that is able to detect invalid `#[cfg(linux)]` attributes.
+    ///
+    /// [`unexpected_cfgs`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unexpected-cfgs
+    #[clippy::version = "1.80.0"]
+    pub MISMATCHED_TARGET_OS,
+    "this lint has been replaced by `unexpected_cfgs`"
+}
diff --git a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
index 010fab803d9..e3d74840726 100644
--- a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
@@ -37,7 +37,7 @@ pub fn check(
             cx,
             MISSING_SAFETY_DOC,
             span,
-            "unsafe function's docs miss `# Safety` section",
+            "unsafe function's docs are missing a `# Safety` section",
         ),
         (true, Safety::Safe) => span_lint(
             cx,
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 48c4c4206fe..42ec2c00823 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -9,8 +9,8 @@ use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, Saf
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{
-    self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, RegionKind, Ty,
-    TypeVisitableExt, TypeckResults, TyCtxt,
+    self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, RegionKind, Ty, TyCtxt,
+    TypeVisitableExt, TypeckResults,
 };
 use rustc_session::declare_lint_pass;
 use rustc_span::symbol::sym;
@@ -123,7 +123,8 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
                     ExprKind::Path(QPath::Resolved(..) | QPath::TypeRelative(..))
                 ) =>
             {
-                let callee_ty = typeck.expr_ty(callee).peel_refs();
+                let callee_ty_raw = typeck.expr_ty(callee);
+                let callee_ty = callee_ty_raw.peel_refs();
                 if matches!(type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc))
                     || !check_inputs(typeck, body.params, None, args)
                 {
@@ -170,15 +171,25 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
                 {
                     span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
                         if let Some(mut snippet) = snippet_opt(cx, callee.span) {
-                            if let Ok((ClosureKind::FnMut, _)) = cx.tcx.infer_ctxt().build().type_implements_fn_trait(
-                                cx.param_env,
-                                Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
-                                ty::PredicatePolarity::Positive,
-                            ) && path_to_local(callee).map_or(false, |l| {
+                            if path_to_local(callee).map_or(false, |l| {
+                                // FIXME: Do we really need this `local_used_in` check?
+                                // Isn't it checking something like... `callee(callee)`?
+                                // If somehow this check is needed, add some test for it,
+                                // 'cuz currently nothing changes after deleting this check.
                                 local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
                             }) {
-                                // Mutable closure is used after current expr; we cannot consume it.
-                                snippet = format!("&mut {snippet}");
+                                match cx.tcx.infer_ctxt().build().type_implements_fn_trait(
+                                    cx.param_env,
+                                    Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
+                                    ty::PredicatePolarity::Positive,
+                                ) {
+                                    // Mutable closure is used after current expr; we cannot consume it.
+                                    Ok((ClosureKind::FnMut, _)) => snippet = format!("&mut {snippet}"),
+                                    Ok((ClosureKind::Fn, _)) if !callee_ty_raw.is_ref() => {
+                                        snippet = format!("&{snippet}");
+                                    },
+                                    _ => (),
+                                }
                             }
                             diag.span_suggestion(
                                 expr.span,
diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs
index 4ec9bd757ff..4d301daabe4 100644
--- a/src/tools/clippy/clippy_lints/src/float_literal.rs
+++ b/src/tools/clippy/clippy_lints/src/float_literal.rs
@@ -103,7 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
                 return;
             }
 
-            if is_whole && !sym_str.contains(|c| c == 'e' || c == 'E') {
+            if is_whole && !sym_str.contains(['e', 'E']) {
                 // Normalize the literal by stripping the fractional portion
                 if sym_str.split('.').next().unwrap() != float_str {
                     // If the type suffix is missing the suggestion would be
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index 46d47e217b0..68bdf88d0a7 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -2,7 +2,8 @@ use clippy_utils::consts::Constant::{Int, F32, F64};
 use clippy_utils::consts::{constant, constant_simple, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::{
-    eq_expr_value, get_parent_expr, higher, in_constant, is_no_std_crate, numeric_literal, peel_blocks, sugg,
+    eq_expr_value, get_parent_expr, higher, in_constant, is_inherent_method_call, is_no_std_crate, numeric_literal,
+    peel_blocks, sugg,
 };
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};
@@ -759,7 +760,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
         if let ExprKind::MethodCall(path, receiver, args, _) = &expr.kind {
             let recv_ty = cx.typeck_results().expr_ty(receiver);
 
-            if recv_ty.is_floating_point() && !is_no_std_crate(cx) {
+            if recv_ty.is_floating_point() && !is_no_std_crate(cx) && is_inherent_method_call(cx, expr) {
                 match path.ident.name.as_str() {
                     "ln" => check_ln1p(cx, expr, receiver),
                     "log" => check_log_base(cx, expr, receiver, args),
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index 86115807aa4..99def199af0 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -424,14 +424,14 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> {
                 count_needed_derefs(receiver_ty, cx.typeck_results().expr_adjustments(receiver).iter())
             && implements_trait(cx, target, display_trait_id, &[])
             && let Some(sized_trait_id) = cx.tcx.lang_items().sized_trait()
-            && let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
+            && let Some(receiver_snippet) = snippet_opt(cx, receiver.span.source_callsite())
         {
             let needs_ref = !implements_trait(cx, receiver_ty, sized_trait_id, &[]);
             if n_needed_derefs == 0 && !needs_ref {
                 span_lint_and_sugg(
                     cx,
                     TO_STRING_IN_FORMAT_ARGS,
-                    to_string_span.with_lo(receiver.span.hi()),
+                    to_string_span.with_lo(receiver.span.source_callsite().hi()),
                     format!("`to_string` applied to a type that implements `Display` in `{name}!` args"),
                     "remove this",
                     String::new(),
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index e7ec2b3151e..cce8617821e 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -14,7 +14,7 @@ use clippy_utils::attrs::is_proc_macro;
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::is_must_use_ty;
-use clippy_utils::visitors::for_each_expr;
+use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{return_ty, trait_ref_of_method};
 
 use core::ops::ControlFlow;
@@ -226,7 +226,7 @@ fn is_mutated_static(e: &hir::Expr<'_>) -> bool {
 }
 
 fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bool {
-    for_each_expr(body.value, |e| {
+    for_each_expr_without_closures(body.value, |e| {
         use hir::ExprKind::{AddrOf, Assign, AssignOp, Call, MethodCall};
 
         match e.kind {
diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
index b44a5f20ef6..1aeefe73cf6 100644
--- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -5,7 +5,7 @@ use rustc_span::def_id::LocalDefId;
 
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::type_is_unsafe_function;
-use clippy_utils::visitors::for_each_expr_with_closures;
+use clippy_utils::visitors::for_each_expr;
 use clippy_utils::{iter_input_pats, path_to_local};
 
 use core::ops::ControlFlow;
@@ -49,7 +49,7 @@ fn check_raw_ptr<'tcx>(
 
         if !raw_ptrs.is_empty() {
             let typeck = cx.tcx.typeck_body(body.id());
-            let _: Option<!> = for_each_expr_with_closures(cx, body.value, |e| {
+            let _: Option<!> = for_each_expr(cx, body.value, |e| {
                 match e.kind {
                     hir::ExprKind::Call(f, args) if type_is_unsafe_function(cx, typeck.expr_ty(f)) => {
                         for arg in args {
diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs
index cc342007ec6..2f543781c44 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_return.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context, walk_span_to_context};
-use clippy_utils::visitors::for_each_expr;
+use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{get_async_fn_body, is_async_fn};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
@@ -153,7 +153,7 @@ fn lint_implicit_returns(
 
         ExprKind::Loop(block, ..) => {
             let mut add_return = false;
-            let _: Option<!> = for_each_expr(block, |e| {
+            let _: Option<!> = for_each_expr_without_closures(block, |e| {
                 if let ExprKind::Break(dest, sub_expr) = e.kind {
                     if dest.target_id.ok() == Some(expr.hir_id) {
                         if call_site_span.is_none() && e.span.ctxt() == ctxt {
diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs
index 2b389d4f9b1..170ecf896b4 100644
--- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs
@@ -3,8 +3,8 @@ use clippy_utils::source::snippet;
 use rustc_errors::{Applicability, SuggestionStyle};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{
-    GenericArg, GenericBound, GenericBounds, ItemKind, PredicateOrigin, TraitBoundModifier, TyKind, AssocItemConstraint,
-    WherePredicate,
+    AssocItemConstraint, GenericArg, GenericBound, GenericBounds, ItemKind, PredicateOrigin, TraitBoundModifier,
+    TyKind, WherePredicate,
 };
 use rustc_hir_analysis::lower_ty;
 use rustc_lint::{LateContext, LateLintPass};
@@ -83,8 +83,8 @@ fn emit_lint(
 
             let mut sugg = vec![(implied_span_extended, String::new())];
 
-            // We also might need to include associated item constraints that were specified in the implied bound,
-            // but omitted in the implied-by bound:
+            // We also might need to include associated item constraints that were specified in the implied
+            // bound, but omitted in the implied-by bound:
             // `fn f() -> impl Deref<Target = u8> + DerefMut`
             // If we're going to suggest removing `Deref<..>`, we'll need to put `<Target = u8>` on `DerefMut`
             let omitted_constraints: Vec<_> = implied_constraints
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index e3e79749bea..d54f2af65cd 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -2,12 +2,14 @@
 
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
-use clippy_utils::higher;
+use clippy_utils::ty::{deref_chain, get_adt_inherent_method};
+use clippy_utils::{higher, is_from_proc_macro};
 use rustc_ast::ast::RangeLimits;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty;
+use rustc_middle::ty::{self, Ty};
 use rustc_session::impl_lint_pass;
+use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -100,11 +102,21 @@ impl IndexingSlicing {
 
 impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if self.suppress_restriction_lint_in_const && cx.tcx.hir().is_inside_const_context(expr.hir_id) {
+        if (self.suppress_restriction_lint_in_const && cx.tcx.hir().is_inside_const_context(expr.hir_id))
+            || is_from_proc_macro(cx, expr)
+        {
             return;
         }
 
-        if let ExprKind::Index(array, index, _) = &expr.kind {
+        if let ExprKind::Index(array, index, _) = &expr.kind
+            && let expr_ty = cx.typeck_results().expr_ty(array)
+            && let mut deref = deref_chain(cx, expr_ty)
+            && deref.any(|l| {
+                l.peel_refs().is_slice()
+                    || l.peel_refs().is_array()
+                    || ty_has_applicable_get_function(cx, l.peel_refs(), expr_ty, expr)
+            })
+        {
             let note = "the suggestion might not be applicable in constant blocks";
             let ty = cx.typeck_results().expr_ty(array).peel_refs();
             if let Some(range) = higher::Range::hir(index) {
@@ -231,3 +243,33 @@ fn to_const_range(cx: &LateContext<'_>, range: higher::Range<'_>, array_size: u1
 
     (start, end)
 }
+
+/// Checks if the output Ty of the `get` method on this Ty (if any) matches the Ty returned by the
+/// indexing operation (if any).
+fn ty_has_applicable_get_function<'tcx>(
+    cx: &LateContext<'tcx>,
+    ty: Ty<'tcx>,
+    array_ty: Ty<'tcx>,
+    index_expr: &Expr<'_>,
+) -> bool {
+    if let ty::Adt(_, _) = array_ty.kind()
+        && let Some(get_output_ty) = get_adt_inherent_method(cx, ty, sym!(get)).map(|m| {
+            cx.tcx
+                .fn_sig(m.def_id)
+                .skip_binder()
+                .output()
+                .skip_binder()
+        })
+        && let ty::Adt(def, args) = get_output_ty.kind()
+        && cx.tcx.is_diagnostic_item(sym::Option, def.0.did)
+        && let Some(option_generic_param) = args.first()
+        && let generic_ty = option_generic_param.expect_ty().peel_refs()
+        // FIXME: ideally this would handle type params and projections properly, for now just assume it's the same type
+        && (cx.typeck_results().expr_ty(index_expr).peel_refs() == generic_ty.peel_refs()
+            || matches!(generic_ty.peel_refs().kind(), ty::Param(_) | ty::Alias(_, _)))
+    {
+        true
+    } else {
+        false
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/integer_division_remainder_used.rs b/src/tools/clippy/clippy_lints/src/integer_division_remainder_used.rs
index cf598d5045e..a1215491b48 100644
--- a/src/tools/clippy/clippy_lints/src/integer_division_remainder_used.rs
+++ b/src/tools/clippy/clippy_lints/src/integer_division_remainder_used.rs
@@ -22,7 +22,7 @@ declare_clippy_lint! {
     /// ```no_run
     /// let my_div = 10 >> 1;
     /// ```
-    #[clippy::version = "1.78.0"]
+    #[clippy::version = "1.79.0"]
     pub INTEGER_DIVISION_REMAINDER_USED,
     restriction,
     "use of disallowed default division and remainder operations"
diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
index 601d0e151aa..6b03f2597b0 100644
--- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::get_parent_as_impl;
 use clippy_utils::source::snippet;
-use clippy_utils::ty::{implements_trait, make_normalized_projection};
+use clippy_utils::ty::{deref_chain, get_adt_inherent_method, implements_trait, make_normalized_projection};
 use rustc_ast::Mutability;
 use rustc_errors::Applicability;
 use rustc_hir::{FnRetTy, ImplItemKind, ImplicitSelfKind, ItemKind, TyKind};
@@ -9,8 +9,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Symbol};
-use std::iter;
+use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -124,33 +123,6 @@ fn is_ty_exported(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
         .is_some_and(|did| cx.effective_visibilities.is_exported(did))
 }
 
-/// Returns the deref chain of a type, starting with the type itself.
-fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'cx {
-    iter::successors(Some(ty), |&ty| {
-        if let Some(deref_did) = cx.tcx.lang_items().deref_trait()
-            && implements_trait(cx, ty, deref_did, &[])
-        {
-            make_normalized_projection(cx.tcx, cx.param_env, deref_did, sym::Target, [ty])
-        } else {
-            None
-        }
-    })
-}
-
-fn adt_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> bool {
-    if let Some(ty_did) = ty.ty_adt_def().map(ty::AdtDef::did) {
-        cx.tcx.inherent_impls(ty_did).into_iter().flatten().any(|&did| {
-            cx.tcx
-                .associated_items(did)
-                .filter_by_name_unhygienic(method_name)
-                .next()
-                .is_some_and(|item| item.kind == ty::AssocKind::Fn)
-        })
-    } else {
-        false
-    }
-}
-
 impl LateLintPass<'_> for IterWithoutIntoIter {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
         if !in_external_macro(cx.sess(), item.span)
@@ -167,7 +139,7 @@ impl LateLintPass<'_> for IterWithoutIntoIter {
             }
             && !deref_chain(cx, ty).any(|ty| {
                 // We can't check inherent impls for slices, but we know that they have an `iter(_mut)` method
-                ty.peel_refs().is_slice() || adt_has_inherent_method(cx, ty, expected_method_name)
+                ty.peel_refs().is_slice() || get_adt_inherent_method(cx, ty, expected_method_name).is_some()
             })
             && let Some(iter_assoc_span) = imp.items.iter().find_map(|item| {
                 if item.ident.name == sym!(IntoIter) {
diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
index 00124dcdd91..eadfeb6e341 100644
--- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
@@ -28,7 +28,7 @@ declare_clippy_lint! {
     /// ```rust
     /// let eps = f32::EPSILON;
     /// ```
-    #[clippy::version = "1.72.0"]
+    #[clippy::version = "1.79.0"]
     pub LEGACY_NUMERIC_CONSTANTS,
     style,
     "checks for usage of legacy std numeric constants and methods"
diff --git a/src/tools/clippy/clippy_lints/src/lib.deprecated.rs b/src/tools/clippy/clippy_lints/src/lib.deprecated.rs
index 80bde1b1138..0d21261822d 100644
--- a/src/tools/clippy/clippy_lints/src/lib.deprecated.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.deprecated.rs
@@ -67,4 +67,12 @@
         "clippy::wrong_pub_self_convention",
         "set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items",
     );
+    store.register_removed(
+        "clippy::maybe_misused_cfg",
+        "this lint has been replaced by `unexpected_cfgs`",
+    );
+    store.register_removed(
+        "clippy::mismatched_target_os",
+        "this lint has been replaced by `unexpected_cfgs`",
+    );
 }
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 3328d642bd8..c65581d5203 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -251,6 +251,7 @@ mod needless_else;
 mod needless_for_each;
 mod needless_if;
 mod needless_late_init;
+mod needless_maybe_sized;
 mod needless_parens_on_range_literals;
 mod needless_pass_by_ref_mut;
 mod needless_pass_by_value;
@@ -325,6 +326,7 @@ mod size_of_in_element_count;
 mod size_of_ref;
 mod slow_vector_initialization;
 mod std_instead_of_core;
+mod string_patterns;
 mod strings;
 mod strlen_on_c_strings;
 mod suspicious_operation_groupings;
@@ -1058,6 +1060,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(no_mangle_with_rust_abi::NoMangleWithRustAbi));
     store.register_late_pass(|_| Box::new(collection_is_never_read::CollectionIsNeverRead));
     store.register_late_pass(|_| Box::new(missing_assert_message::MissingAssertMessage));
+    store.register_late_pass(|_| Box::new(needless_maybe_sized::NeedlessMaybeSized));
     store.register_late_pass(|_| Box::new(redundant_async_block::RedundantAsyncBlock));
     store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped));
     store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute));
@@ -1165,6 +1168,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
             ..Default::default()
         })
     });
+    store.register_late_pass(|_| Box::new(string_patterns::StringPatterns));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs b/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs
index 84fb183e3f7..17399fb2cc2 100644
--- a/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs
@@ -43,7 +43,7 @@ declare_clippy_lint! {
     /// let x: Option<Vec<String>> = Some(Vec::new());
     /// let y: Vec<String> = x.unwrap_or_default();
     /// ```
-    #[clippy::version = "1.78.0"]
+    #[clippy::version = "1.79.0"]
     pub MANUAL_UNWRAP_OR_DEFAULT,
     suspicious,
     "check if a `match` or `if let` can be simplified with `unwrap_or_default`"
@@ -57,7 +57,8 @@ fn get_some<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<HirId> {
         // Since it comes from a pattern binding, we need to get the parent to actually match
         // against it.
         && let Some(def_id) = cx.tcx.opt_parent(def_id)
-        && cx.tcx.lang_items().get(LangItem::OptionSome) == Some(def_id)
+        && (cx.tcx.lang_items().get(LangItem::OptionSome) == Some(def_id)
+        || cx.tcx.lang_items().get(LangItem::ResultOk) == Some(def_id))
     {
         let mut bindings = Vec::new();
         pat.each_binding(|_, id, _, _| bindings.push(id));
@@ -80,6 +81,14 @@ fn get_none<'tcx>(cx: &LateContext<'tcx>, arm: &Arm<'tcx>) -> Option<&'tcx Expr<
         && cx.tcx.lang_items().get(LangItem::OptionNone) == Some(def_id)
     {
         Some(arm.body)
+    } else if let PatKind::TupleStruct(QPath::Resolved(_, path), _, _)= arm.pat.kind
+        && let Some(def_id) = path.res.opt_def_id()
+        // Since it comes from a pattern binding, we need to get the parent to actually match
+        // against it.
+        && let Some(def_id) = cx.tcx.opt_parent(def_id)
+        && cx.tcx.lang_items().get(LangItem::ResultErr) == Some(def_id)
+    {
+        Some(arm.body)
     } else if let PatKind::Wild = arm.pat.kind {
         // We consider that the `Some` check will filter it out if it's not right.
         Some(arm.body)
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
index a75cf37945f..c2c0fbf439d 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
@@ -2,7 +2,7 @@ use clippy_config::msrvs::Msrv;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::matching_root_macro_call;
 use clippy_utils::source::snippet;
-use clippy_utils::visitors::{for_each_expr, is_local_used};
+use clippy_utils::visitors::{for_each_expr_without_closures, is_local_used};
 use clippy_utils::{in_constant, path_to_local};
 use rustc_ast::{BorrowKind, LitKind};
 use rustc_errors::Applicability;
@@ -249,7 +249,7 @@ fn emit_redundant_guards<'tcx>(
 /// an error in the future, and rustc already actively warns against this (see rust#41620),
 /// so we don't consider those as usable within patterns for linting purposes.
 fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    for_each_expr(expr, |expr| {
+    for_each_expr_without_closures(expr, |expr| {
         if match expr.kind {
             ExprKind::ConstBlock(..) => cx.tcx.features().inline_const_pat,
             ExprKind::Call(c, ..) if let ExprKind::Path(qpath) = c.kind => {
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
index 78973984fb0..0e4b2d9d34a 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet, walk_span_to_context};
 use clippy_utils::sugg::{make_unop, Sugg};
 use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop};
-use clippy_utils::visitors::{any_temporaries_need_ordered_drop, for_each_expr};
+use clippy_utils::visitors::{any_temporaries_need_ordered_drop, for_each_expr_without_closures};
 use clippy_utils::{higher, is_expn_of, is_trait_method};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
@@ -283,7 +283,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
                 // to see that there aren't any let chains anywhere in the guard, as that would break
                 // if we suggest `t.is_none() && (let X = y && z)` for:
                 // `match t { None if let X = y && z => true, _ => false }`
-                let has_nested_let_chain = for_each_expr(guard, |expr| {
+                let has_nested_let_chain = for_each_expr_without_closures(guard, |expr| {
                     if matches!(expr.kind, ExprKind::Let(..)) {
                         ControlFlow::Break(())
                     } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs b/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
index 5409ede6008..1fab6c0e499 100644
--- a/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
-use clippy_utils::visitors::for_each_expr;
+use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{eq_expr_value, get_parent_expr};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
@@ -46,7 +46,7 @@ fn collect_replace_calls<'tcx>(
     let mut methods = VecDeque::new();
     let mut from_args = VecDeque::new();
 
-    let _: Option<()> = for_each_expr(expr, |e| {
+    let _: Option<()> = for_each_expr_without_closures(expr, |e| {
         if let Some(("replace", _, [from, to], _, _)) = method_call(e) {
             if eq_expr_value(cx, to_arg, to) && cx.typeck_results().expr_ty(from).peel_refs().is_char() {
                 methods.push_front(e);
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 75a86c0c834..6200716afbe 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -66,6 +66,7 @@ mod map_flatten;
 mod map_identity;
 mod map_unwrap_or;
 mod mut_mutex_lock;
+mod needless_character_iteration;
 mod needless_collect;
 mod needless_option_as_deref;
 mod needless_option_take;
@@ -93,7 +94,6 @@ mod seek_from_current;
 mod seek_to_start_instead_of_rewind;
 mod single_char_add_str;
 mod single_char_insert_string;
-mod single_char_pattern;
 mod single_char_push_string;
 mod skip_while_next;
 mod stable_sort_primitive;
@@ -1142,38 +1142,6 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for string methods that receive a single-character
-    /// `str` as an argument, e.g., `_.split("x")`.
-    ///
-    /// ### Why is this bad?
-    /// While this can make a perf difference on some systems,
-    /// benchmarks have proven inconclusive. But at least using a
-    /// char literal makes it clear that we are looking at a single
-    /// character.
-    ///
-    /// ### Known problems
-    /// Does not catch multi-byte unicode characters. This is by
-    /// design, on many machines, splitting by a non-ascii char is
-    /// actually slower. Please do your own measurements instead of
-    /// relying solely on the results of this lint.
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// _.split("x");
-    /// ```
-    ///
-    /// Use instead:
-    /// ```rust,ignore
-    /// _.split('x');
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub SINGLE_CHAR_PATTERN,
-    pedantic,
-    "using a single-character str where a char could be used, e.g., `_.split(\"x\")`"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
     /// Checks for calling `.step_by(0)` on iterators which panics.
     ///
     /// ### Why is this bad?
@@ -4084,12 +4052,33 @@ declare_clippy_lint! {
     /// ```no_run
     /// println!("the string is empty");
     /// ```
-    #[clippy::version = "1.78.0"]
+    #[clippy::version = "1.79.0"]
     pub CONST_IS_EMPTY,
     suspicious,
     "is_empty() called on strings known at compile time"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks if an iterator is used to check if a string is ascii.
+    ///
+    /// ### Why is this bad?
+    /// The `str` type already implements the `is_ascii` method.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// "foo".chars().all(|c| c.is_ascii());
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// "foo".is_ascii();
+    /// ```
+    #[clippy::version = "1.80.0"]
+    pub NEEDLESS_CHARACTER_ITERATION,
+    suspicious,
+    "is_ascii() called on a char iterator"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
@@ -4147,7 +4136,6 @@ impl_lint_pass!(Methods => [
     FLAT_MAP_OPTION,
     INEFFICIENT_TO_STRING,
     NEW_RET_NO_SELF,
-    SINGLE_CHAR_PATTERN,
     SINGLE_CHAR_ADD_STR,
     SEARCH_IS_SOME,
     FILTER_NEXT,
@@ -4255,6 +4243,7 @@ impl_lint_pass!(Methods => [
     UNNECESSARY_RESULT_MAP_OR_ELSE,
     MANUAL_C_STR_LITERALS,
     UNNECESSARY_GET_THEN_CHECK,
+    NEEDLESS_CHARACTER_ITERATION,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -4301,7 +4290,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                 inefficient_to_string::check(cx, expr, method_call.ident.name, receiver, args);
                 single_char_add_str::check(cx, expr, receiver, args);
                 into_iter_on_ref::check(cx, expr, method_span, method_call.ident.name, receiver);
-                single_char_pattern::check(cx, expr, method_call.ident.name, receiver, args);
                 unnecessary_to_owned::check(cx, expr, method_call.ident.name, receiver, args, &self.msrv);
             },
             ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => {
@@ -4462,6 +4450,7 @@ impl Methods {
                 },
                 ("all", [arg]) => {
                     unused_enumerate_index::check(cx, expr, recv, arg);
+                    needless_character_iteration::check(cx, expr, recv, arg, true);
                     if let Some(("cloned", recv2, [], _, _)) = method_call(recv) {
                         iter_overeager_cloned::check(
                             cx,
@@ -4482,6 +4471,7 @@ impl Methods {
                 },
                 ("any", [arg]) => {
                     unused_enumerate_index::check(cx, expr, recv, arg);
+                    needless_character_iteration::check(cx, expr, recv, arg, false);
                     match method_call(recv) {
                         Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(
                             cx,
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs
new file mode 100644
index 00000000000..e3d78207715
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs
@@ -0,0 +1,124 @@
+use rustc_errors::Applicability;
+use rustc_hir::{Closure, Expr, ExprKind, HirId, StmtKind, UnOp};
+use rustc_lint::LateContext;
+use rustc_middle::ty;
+use rustc_span::Span;
+
+use super::utils::get_last_chain_binding_hir_id;
+use super::NEEDLESS_CHARACTER_ITERATION;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::{match_def_path, path_to_local_id, peel_blocks};
+
+fn peels_expr_ref<'a, 'tcx>(mut expr: &'a Expr<'tcx>) -> &'a Expr<'tcx> {
+    while let ExprKind::AddrOf(_, _, e) = expr.kind {
+        expr = e;
+    }
+    expr
+}
+
+fn handle_expr(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    first_param: HirId,
+    span: Span,
+    before_chars: Span,
+    revert: bool,
+    is_all: bool,
+) {
+    match expr.kind {
+        ExprKind::MethodCall(method, receiver, [], _) => {
+            // If we have `!is_ascii`, then only `.any()` should warn. And if the condition is
+            // `is_ascii`, then only `.all()` should warn.
+            if revert != is_all
+                && method.ident.name.as_str() == "is_ascii"
+                && path_to_local_id(receiver, first_param)
+                && let char_arg_ty = cx.typeck_results().expr_ty_adjusted(receiver).peel_refs()
+                && *char_arg_ty.kind() == ty::Char
+                && let Some(snippet) = snippet_opt(cx, before_chars)
+            {
+                span_lint_and_sugg(
+                    cx,
+                    NEEDLESS_CHARACTER_ITERATION,
+                    span,
+                    "checking if a string is ascii using iterators",
+                    "try",
+                    format!("{}{snippet}.is_ascii()", if revert { "!" } else { "" }),
+                    Applicability::MachineApplicable,
+                );
+            }
+        },
+        ExprKind::Block(block, _) => {
+            if block.stmts.iter().any(|stmt| !matches!(stmt.kind, StmtKind::Let(_))) {
+                // If there is something else than let bindings, then better not emit the lint.
+                return;
+            }
+            if let Some(block_expr) = block.expr
+                // First we ensure that this is a "binding chain" (each statement is a binding
+                // of the previous one) and that it is a binding of the closure argument.
+                && let Some(last_chain_binding_id) =
+                    get_last_chain_binding_hir_id(first_param, block.stmts)
+            {
+                handle_expr(
+                    cx,
+                    block_expr,
+                    last_chain_binding_id,
+                    span,
+                    before_chars,
+                    revert,
+                    is_all,
+                );
+            }
+        },
+        ExprKind::Unary(UnOp::Not, expr) => handle_expr(cx, expr, first_param, span, before_chars, !revert, is_all),
+        ExprKind::Call(fn_path, [arg]) => {
+            // If we have `!is_ascii`, then only `.any()` should warn. And if the condition is
+            // `is_ascii`, then only `.all()` should warn.
+            if revert != is_all
+                && let ExprKind::Path(path) = fn_path.kind
+                && let Some(fn_def_id) = cx.qpath_res(&path, fn_path.hir_id).opt_def_id()
+                && match_def_path(cx, fn_def_id, &["core", "char", "methods", "<impl char>", "is_ascii"])
+                && path_to_local_id(peels_expr_ref(arg), first_param)
+                && let Some(snippet) = snippet_opt(cx, before_chars)
+            {
+                span_lint_and_sugg(
+                    cx,
+                    NEEDLESS_CHARACTER_ITERATION,
+                    span,
+                    "checking if a string is ascii using iterators",
+                    "try",
+                    format!("{}{snippet}.is_ascii()", if revert { "!" } else { "" }),
+                    Applicability::MachineApplicable,
+                );
+            }
+        },
+        _ => {},
+    }
+}
+
+pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>, closure_arg: &Expr<'_>, is_all: bool) {
+    if let ExprKind::Closure(&Closure { body, .. }) = closure_arg.kind
+        && let body = cx.tcx.hir().body(body)
+        && let Some(first_param) = body.params.first()
+        && let ExprKind::MethodCall(method, mut recv, [], _) = recv.kind
+        && method.ident.name.as_str() == "chars"
+        && let str_ty = cx.typeck_results().expr_ty_adjusted(recv).peel_refs()
+        && *str_ty.kind() == ty::Str
+    {
+        let expr_start = recv.span;
+        while let ExprKind::MethodCall(_, new_recv, _, _) = recv.kind {
+            recv = new_recv;
+        }
+        let body_expr = peel_blocks(body.value);
+
+        handle_expr(
+            cx,
+            body_expr,
+            first_param.pat.hir_id,
+            recv.span.with_hi(call_expr.span.hi()),
+            recv.span.with_hi(expr_start.hi()),
+            false,
+            is_all,
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
index ca331f3e756..3d326bc99f9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -60,7 +60,7 @@ pub(super) fn check<'tcx>(
 
             let map = cx.tcx.hir();
             let body = map.body_owned_by(map.enclosing_body_owner(expr.hir_id));
-            reference_visitor.visit_body(&body);
+            reference_visitor.visit_body(body);
 
             if reference_visitor.found_reference {
                 return;
diff --git a/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs b/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs
index 04a27cc98f3..2d3007e50b8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs
@@ -27,7 +27,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
             lit.span,
             "calling `push` with '/' or '\\' (file system root) will overwrite the previous path definition",
             "try",
-            format!("\"{}\"", pushed_path_lit.trim_start_matches(|c| c == '/' || c == '\\')),
+            format!("\"{}\"", pushed_path_lit.trim_start_matches(['/', '\\'])),
             Applicability::MachineApplicable,
         );
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
index f5f1e94bbf4..3b2dd285b8c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::deref_closure_args;
 use clippy_utils::ty::is_type_lang_item;
-use clippy_utils::{get_parent_expr, is_trait_method, strip_pat_refs};
+use clippy_utils::{is_receiver_of_method_call, is_trait_method, strip_pat_refs};
 use hir::ExprKind;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -156,13 +156,3 @@ pub(super) fn check<'tcx>(
         }
     }
 }
-
-fn is_receiver_of_method_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
-    if let Some(parent_expr) = get_parent_expr(cx, expr)
-        && let ExprKind::MethodCall(_, receiver, ..) = parent_expr.kind
-        && receiver.hir_id == expr.hir_id
-    {
-        return true;
-    }
-    false
-}
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs
index 20ec2b74d81..e2f76ac114c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs
@@ -1,8 +1,8 @@
-use super::utils::get_hint_if_single_char_arg;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::source::{snippet_with_applicability, str_literal_to_char_literal};
+use rustc_ast::BorrowKind;
 use rustc_errors::Applicability;
-use rustc_hir as hir;
+use rustc_hir::{self as hir, ExprKind};
 use rustc_lint::LateContext;
 
 use super::SINGLE_CHAR_ADD_STR;
@@ -10,7 +10,7 @@ use super::SINGLE_CHAR_ADD_STR;
 /// lint for length-1 `str`s as argument for `insert_str`
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
     let mut applicability = Applicability::MachineApplicable;
-    if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability, false) {
+    if let Some(extension_string) = str_literal_to_char_literal(cx, &args[1], &mut applicability, false) {
         let base_string_snippet =
             snippet_with_applicability(cx, receiver.span.source_callsite(), "_", &mut applicability);
         let pos_arg = snippet_with_applicability(cx, args[0].span, "..", &mut applicability);
@@ -25,4 +25,43 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::
             applicability,
         );
     }
+
+    if let ExprKind::AddrOf(BorrowKind::Ref, _, arg) = &args[1].kind
+        && let ExprKind::MethodCall(path_segment, method_arg, _, _) = &arg.kind
+        && path_segment.ident.name == rustc_span::sym::to_string
+        && (is_ref_char(cx, method_arg) || is_char(cx, method_arg))
+    {
+        let base_string_snippet =
+            snippet_with_applicability(cx, receiver.span.source_callsite(), "..", &mut applicability);
+        let extension_string =
+            snippet_with_applicability(cx, method_arg.span.source_callsite(), "..", &mut applicability);
+        let pos_arg = snippet_with_applicability(cx, args[0].span, "..", &mut applicability);
+        let deref_string = if is_ref_char(cx, method_arg) { "*" } else { "" };
+
+        let sugg = format!("{base_string_snippet}.insert({pos_arg}, {deref_string}{extension_string})");
+        span_lint_and_sugg(
+            cx,
+            SINGLE_CHAR_ADD_STR,
+            expr.span,
+            "calling `insert_str()` using a single-character converted to string",
+            "consider using `insert` without `to_string()`",
+            sugg,
+            applicability,
+        );
+    }
+}
+
+fn is_ref_char(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+    if cx.typeck_results().expr_ty(expr).is_ref()
+        && let rustc_middle::ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(expr).kind()
+        && ty.is_char()
+    {
+        return true;
+    }
+
+    false
+}
+
+fn is_char(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+    cx.typeck_results().expr_ty(expr).is_char()
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs
deleted file mode 100644
index 982a7901c45..00000000000
--- a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-use super::utils::get_hint_if_single_char_arg;
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use rustc_errors::Applicability;
-use rustc_hir as hir;
-use rustc_lint::LateContext;
-use rustc_middle::ty;
-use rustc_span::symbol::Symbol;
-
-use super::SINGLE_CHAR_PATTERN;
-
-const PATTERN_METHODS: [(&str, usize); 22] = [
-    ("contains", 0),
-    ("starts_with", 0),
-    ("ends_with", 0),
-    ("find", 0),
-    ("rfind", 0),
-    ("split", 0),
-    ("split_inclusive", 0),
-    ("rsplit", 0),
-    ("split_terminator", 0),
-    ("rsplit_terminator", 0),
-    ("splitn", 1),
-    ("rsplitn", 1),
-    ("split_once", 0),
-    ("rsplit_once", 0),
-    ("matches", 0),
-    ("rmatches", 0),
-    ("match_indices", 0),
-    ("rmatch_indices", 0),
-    ("trim_start_matches", 0),
-    ("trim_end_matches", 0),
-    ("replace", 0),
-    ("replacen", 0),
-];
-
-/// lint for length-1 `str`s for methods in `PATTERN_METHODS`
-pub(super) fn check(
-    cx: &LateContext<'_>,
-    _expr: &hir::Expr<'_>,
-    method_name: Symbol,
-    receiver: &hir::Expr<'_>,
-    args: &[hir::Expr<'_>],
-) {
-    for &(method, pos) in &PATTERN_METHODS {
-        if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(receiver).kind()
-            && ty.is_str()
-            && method_name.as_str() == method
-            && args.len() > pos
-            && let arg = &args[pos]
-            && let mut applicability = Applicability::MachineApplicable
-            && let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability, true)
-        {
-            span_lint_and_sugg(
-                cx,
-                SINGLE_CHAR_PATTERN,
-                arg.span,
-                "single-character string constant used as pattern",
-                "consider using a `char`",
-                hint,
-                applicability,
-            );
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs
index 97c13825bc1..4ae8634305d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs
@@ -1,8 +1,8 @@
-use super::utils::get_hint_if_single_char_arg;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::source::{snippet_with_applicability, str_literal_to_char_literal};
+use rustc_ast::BorrowKind;
 use rustc_errors::Applicability;
-use rustc_hir as hir;
+use rustc_hir::{self as hir, ExprKind};
 use rustc_lint::LateContext;
 
 use super::SINGLE_CHAR_ADD_STR;
@@ -10,7 +10,7 @@ use super::SINGLE_CHAR_ADD_STR;
 /// lint for length-1 `str`s as argument for `push_str`
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
     let mut applicability = Applicability::MachineApplicable;
-    if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[0], &mut applicability, false) {
+    if let Some(extension_string) = str_literal_to_char_literal(cx, &args[0], &mut applicability, false) {
         let base_string_snippet =
             snippet_with_applicability(cx, receiver.span.source_callsite(), "..", &mut applicability);
         let sugg = format!("{base_string_snippet}.push({extension_string})");
@@ -24,4 +24,42 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::
             applicability,
         );
     }
+
+    if let ExprKind::AddrOf(BorrowKind::Ref, _, arg) = &args[0].kind
+        && let ExprKind::MethodCall(path_segment, method_arg, _, _) = &arg.kind
+        && path_segment.ident.name == rustc_span::sym::to_string
+        && (is_ref_char(cx, method_arg) || is_char(cx, method_arg))
+    {
+        let base_string_snippet =
+            snippet_with_applicability(cx, receiver.span.source_callsite(), "..", &mut applicability);
+        let extension_string =
+            snippet_with_applicability(cx, method_arg.span.source_callsite(), "..", &mut applicability);
+        let deref_string = if is_ref_char(cx, method_arg) { "*" } else { "" };
+
+        let sugg = format!("{base_string_snippet}.push({deref_string}{extension_string})");
+        span_lint_and_sugg(
+            cx,
+            SINGLE_CHAR_ADD_STR,
+            expr.span,
+            "calling `push_str()` using a single-character converted to string",
+            "consider using `push` without `to_string()`",
+            sugg,
+            applicability,
+        );
+    }
+}
+
+fn is_ref_char(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+    if cx.typeck_results().expr_ty(expr).is_ref()
+        && let rustc_middle::ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(expr).kind()
+        && ty.is_char()
+    {
+        return true;
+    }
+
+    false
+}
+
+fn is_char(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+    cx.typeck_results().expr_ty(expr).is_char()
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
index e8c12bbeea0..4f42fb73547 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -3,7 +3,7 @@ use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::usage::local_used_after_expr;
-use clippy_utils::visitors::{for_each_expr_with_closures, Descend};
+use clippy_utils::visitors::{for_each_expr, Descend};
 use clippy_utils::{is_diag_item_method, match_def_path, path_to_local_id, paths};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
@@ -209,7 +209,7 @@ fn indirect_usage<'tcx>(
     }) = stmt.kind
     {
         let mut path_to_binding = None;
-        let _: Option<!> = for_each_expr_with_closures(cx, init_expr, |e| {
+        let _: Option<!> = for_each_expr(cx, init_expr, |e| {
             if path_to_local_id(e, binding) {
                 path_to_binding = Some(e);
             }
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
index daf99d98614..c9b9d98dbe6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -2,7 +2,7 @@ use super::utils::clone_or_copy_needed;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::is_copy;
 use clippy_utils::usage::mutated_variables;
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{for_each_expr_without_closures, Descend};
 use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
 use core::ops::ControlFlow;
 use rustc_hir as hir;
@@ -26,7 +26,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a
 
         let (mut found_mapping, mut found_filtering) = check_expression(cx, arg_id, body.value);
 
-        let _: Option<!> = for_each_expr(body.value, |e| {
+        let _: Option<!> = for_each_expr_without_closures(body.value, |e| {
             if let hir::ExprKind::Ret(Some(e)) = &e.kind {
                 let (found_mapping_res, found_filtering_res) = check_expression(cx, arg_id, e);
                 found_mapping |= found_mapping_res;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index d1300dd43c2..70885e46e95 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::ForLoop;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::{get_iterator_item_ty, implements_trait};
-use clippy_utils::visitors::for_each_expr;
+use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{can_mut_borrow_both, fn_def_id, get_parent_expr, path_to_local};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
@@ -61,7 +61,7 @@ pub fn check_for_loop_iter(
         fn is_caller_or_fields_change(cx: &LateContext<'_>, body: &Expr<'_>, caller: &Expr<'_>) -> bool {
             let mut change = false;
             if let ExprKind::Block(block, ..) = body.kind {
-                for_each_expr(block, |e| {
+                for_each_expr_without_closures(block, |e| {
                     match e.kind {
                         ExprKind::Assign(assignee, _, _) | ExprKind::AssignOp(_, assignee, _) => {
                             change |= !can_mut_borrow_both(cx, caller, assignee);
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
index cdfaa690d5f..c14a87c1534 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
@@ -4,10 +4,11 @@ use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::{Closure, Expr, ExprKind, HirId, QPath, Stmt, StmtKind};
+use rustc_hir::{Closure, Expr, ExprKind, HirId, QPath};
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
 
+use super::utils::get_last_chain_binding_hir_id;
 use super::UNNECESSARY_RESULT_MAP_OR_ELSE;
 
 fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &Expr<'_>) {
@@ -25,22 +26,6 @@ fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &E
     );
 }
 
-fn get_last_chain_binding_hir_id(mut hir_id: HirId, statements: &[Stmt<'_>]) -> Option<HirId> {
-    for stmt in statements {
-        if let StmtKind::Let(local) = stmt.kind
-            && let Some(init) = local.init
-            && let ExprKind::Path(QPath::Resolved(_, path)) = init.kind
-            && let hir::def::Res::Local(local_hir_id) = path.res
-            && local_hir_id == hir_id
-        {
-            hir_id = local.pat.hir_id;
-        } else {
-            return None;
-        }
-    }
-    Some(hir_id)
-}
-
 fn handle_qpath(
     cx: &LateContext<'_>,
     expr: &Expr<'_>,
diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs
index 1a55b7160fb..0d2b0a31317 100644
--- a/src/tools/clippy/clippy_lints/src/methods/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs
@@ -1,10 +1,7 @@
-use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{get_parent_expr, path_to_local_id, usage};
-use rustc_ast::ast;
-use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, Mutability, Pat};
+use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, QPath, Stmt, StmtKind};
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty};
@@ -49,48 +46,6 @@ pub(super) fn derefs_to_slice<'tcx>(
     }
 }
 
-pub(super) fn get_hint_if_single_char_arg(
-    cx: &LateContext<'_>,
-    arg: &Expr<'_>,
-    applicability: &mut Applicability,
-    ascii_only: bool,
-) -> Option<String> {
-    if let ExprKind::Lit(lit) = &arg.kind
-        && let ast::LitKind::Str(r, style) = lit.node
-        && let string = r.as_str()
-        && let len = if ascii_only {
-            string.len()
-        } else {
-            string.chars().count()
-        }
-        && len == 1
-    {
-        let snip = snippet_with_applicability(cx, arg.span, string, applicability);
-        let ch = if let ast::StrStyle::Raw(nhash) = style {
-            let nhash = nhash as usize;
-            // for raw string: r##"a"##
-            &snip[(nhash + 2)..(snip.len() - 1 - nhash)]
-        } else {
-            // for regular string: "a"
-            &snip[1..(snip.len() - 1)]
-        };
-
-        let hint = format!(
-            "'{}'",
-            match ch {
-                "'" => "\\'",
-                r"\" => "\\\\",
-                "\\\"" => "\"", // no need to escape `"` in `'"'`
-                _ => ch,
-            }
-        );
-
-        Some(hint)
-    } else {
-        None
-    }
-}
-
 /// The core logic of `check_for_loop_iter` in `unnecessary_iter_cloned.rs`, this function wraps a
 /// use of `CloneOrCopyVisitor`.
 pub(super) fn clone_or_copy_needed<'tcx>(
@@ -175,3 +130,19 @@ impl<'cx, 'tcx> CloneOrCopyVisitor<'cx, 'tcx> {
             .any(|hir_id| path_to_local_id(expr, *hir_id))
     }
 }
+
+pub(super) fn get_last_chain_binding_hir_id(mut hir_id: HirId, statements: &[Stmt<'_>]) -> Option<HirId> {
+    for stmt in statements {
+        if let StmtKind::Let(local) = stmt.kind
+            && let Some(init) = local.init
+            && let ExprKind::Path(QPath::Resolved(_, path)) = init.kind
+            && let rustc_hir::def::Res::Local(local_hir_id) = path.res
+            && local_hir_id == hir_id
+        {
+            hir_id = local.pat.hir_id;
+        } else {
+            return None;
+        }
+    }
+    Some(hir_id)
+}
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/zero_prefixed_literal.rs b/src/tools/clippy/clippy_lints/src/misc_early/zero_prefixed_literal.rs
index 4f9578d1b25..61f4684c9e3 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/zero_prefixed_literal.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/zero_prefixed_literal.rs
@@ -6,7 +6,7 @@ use rustc_span::Span;
 use super::ZERO_PREFIXED_LITERAL;
 
 pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str) {
-    let trimmed_lit_snip = lit_snip.trim_start_matches(|c| c == '_' || c == '0');
+    let trimmed_lit_snip = lit_snip.trim_start_matches(['_', '0']);
     span_lint_and_then(
         cx,
         ZERO_PREFIXED_LITERAL,
@@ -20,7 +20,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str) {
                 Applicability::MaybeIncorrect,
             );
             // do not advise to use octal form if the literal cannot be expressed in base 8.
-            if !lit_snip.contains(|c| c == '8' || c == '9') {
+            if !lit_snip.contains(['8', '9']) {
                 diag.span_suggestion(
                     lit_span,
                     "if you mean to use an octal constant, use `0o`",
diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs
index 752723a0c68..94c91b09517 100644
--- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs
@@ -4,7 +4,7 @@ use std::ops::ControlFlow;
 use clippy_utils::comparisons::{normalize_comparison, Rel};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
-use clippy_utils::visitors::for_each_expr;
+use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{eq_expr_value, hash_expr, higher};
 use rustc_ast::{LitKind, RangeLimits};
 use rustc_data_structures::packed::Pu128;
@@ -405,7 +405,7 @@ impl LateLintPass<'_> for MissingAssertsForIndexing {
     fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) {
         let mut map = UnhashMap::default();
 
-        for_each_expr(body.value, |expr| {
+        for_each_expr_without_closures(body.value, |expr| {
             check_index(cx, expr, &mut map);
             check_assert(cx, expr, &mut map);
             ControlFlow::<!, ()>::Continue(())
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index 9ba19e0a865..4592324809f 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -1,7 +1,6 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::qualify_min_const_fn::is_min_const_fn;
-use clippy_utils::ty::has_drop;
 use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, trait_ref_of_method};
 use rustc_hir as hir;
 use rustc_hir::def_id::CRATE_DEF_ID;
@@ -121,10 +120,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
                 }
             },
             FnKind::Method(_, sig, ..) => {
-                if trait_ref_of_method(cx, def_id).is_some()
-                    || already_const(sig.header)
-                    || method_accepts_droppable(cx, def_id)
-                {
+                if trait_ref_of_method(cx, def_id).is_some() || already_const(sig.header) {
                     return;
                 }
             },
@@ -151,26 +147,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
 
         let mir = cx.tcx.optimized_mir(def_id);
 
-        if let Err((span, err)) = is_min_const_fn(cx.tcx, mir, &self.msrv) {
-            if cx.tcx.is_const_fn_raw(def_id.to_def_id()) {
-                cx.tcx.dcx().span_err(span, err);
-            }
-        } else {
+        if let Ok(()) = is_min_const_fn(cx.tcx, mir, &self.msrv) {
             span_lint(cx, MISSING_CONST_FOR_FN, span, "this could be a `const fn`");
         }
     }
     extract_msrv_attr!(LateContext);
 }
 
-/// Returns true if any of the method parameters is a type that implements `Drop`. The method
-/// can't be made const then, because `drop` can't be const-evaluated.
-fn method_accepts_droppable(cx: &LateContext<'_>, def_id: LocalDefId) -> bool {
-    let sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder();
-
-    // If any of the params are droppable, return true
-    sig.inputs().iter().any(|&ty| has_drop(cx, ty))
-}
-
 // We don't have to lint on something that's already `const`
 #[must_use]
 fn already_const(header: hir::FnHeader) -> bool {
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 a64faa124f0..77595b121aa 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
@@ -110,7 +110,7 @@ fn should_lint<'tcx>(
     // Is there a call to `DebugStruct::debug_struct`? Do lint if there is.
     let mut has_debug_struct = false;
 
-    for_each_expr(block, |expr| {
+    for_each_expr(cx, block, |expr| {
         if let ExprKind::MethodCall(path, recv, ..) = &expr.kind {
             let recv_ty = typeck_results.expr_ty(recv).peel_refs();
 
@@ -165,7 +165,7 @@ fn check_struct<'tcx>(
     let mut has_direct_field_access = false;
     let mut field_accesses = FxHashSet::default();
 
-    for_each_expr(block, |expr| {
+    for_each_expr(cx, block, |expr| {
         if let ExprKind::Field(target, ident) = expr.kind
             && let target_ty = typeck_results.expr_ty_adjusted(target).peel_refs()
             && target_ty == self_ty
diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
index 5b4ef852f0d..da74a7c7145 100644
--- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::visitors::{for_each_expr_with_closures, Descend, Visitable};
+use clippy_utils::visitors::{for_each_expr, Descend, Visitable};
 use core::ops::ControlFlow::Continue;
 use hir::def::{DefKind, Res};
 use hir::{BlockCheckMode, ExprKind, QPath, Safety, UnOp};
@@ -96,7 +96,7 @@ fn collect_unsafe_exprs<'tcx>(
     node: impl Visitable<'tcx>,
     unsafe_ops: &mut Vec<(&'static str, Span)>,
 ) {
-    for_each_expr_with_closures(cx, node, |expr| {
+    for_each_expr(cx, node, |expr| {
         match expr.kind {
             ExprKind::InlineAsm(_) => unsafe_ops.push(("inline assembly used here", expr.span)),
 
diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs
index e1866eaa18a..9cb4fa41c73 100644
--- a/src/tools/clippy/clippy_lints/src/needless_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs
@@ -6,8 +6,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
-    higher, is_block_like, is_else_clause, is_expn_of, is_parent_stmt, peel_blocks, peel_blocks_with_stmt,
-    span_extract_comment, SpanlessEq,
+    get_parent_expr, higher, is_block_like, is_else_clause, is_expn_of, is_parent_stmt, is_receiver_of_method_call,
+    peel_blocks, peel_blocks_with_stmt, span_extract_comment, SpanlessEq,
 };
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
@@ -154,7 +154,10 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
                     snip = snip.blockify();
                 }
 
-                if condition_needs_parentheses(cond) && is_parent_stmt(cx, e.hir_id) {
+                if (condition_needs_parentheses(cond) && is_parent_stmt(cx, e.hir_id))
+                    || is_receiver_of_method_call(cx, e)
+                    || is_as_argument(cx, e)
+                {
                     snip = snip.maybe_par();
                 }
 
@@ -442,3 +445,7 @@ fn fetch_assign<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<(&'tcx Expr<'tcx>, bool)
         None
     }
 }
+
+fn is_as_argument(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
+    matches!(get_parent_expr(cx, e).map(|e| e.kind), Some(ExprKind::Cast(_, _)))
+}
diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
index 5a0ae1a4d6d..4bfc30fa5cf 100644
--- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::path_to_local;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::needs_ordered_drop;
-use clippy_utils::visitors::{for_each_expr, for_each_expr_with_closures, is_local_used};
+use clippy_utils::visitors::{for_each_expr, for_each_expr_without_closures, is_local_used};
 use core::ops::ControlFlow;
 use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir::{
@@ -63,7 +63,7 @@ declare_clippy_lint! {
 declare_lint_pass!(NeedlessLateInit => [NEEDLESS_LATE_INIT]);
 
 fn contains_assign_expr<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) -> bool {
-    for_each_expr_with_closures(cx, stmt, |e| {
+    for_each_expr(cx, stmt, |e| {
         if matches!(e.kind, ExprKind::Assign(..)) {
             ControlFlow::Break(())
         } else {
@@ -74,7 +74,7 @@ fn contains_assign_expr<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) ->
 }
 
 fn contains_let(cond: &Expr<'_>) -> bool {
-    for_each_expr(cond, |e| {
+    for_each_expr_without_closures(cond, |e| {
         if matches!(e.kind, ExprKind::Let(_)) {
             ControlFlow::Break(())
         } else {
diff --git a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs
new file mode 100644
index 00000000000..06ae1723a03
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs
@@ -0,0 +1,164 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use rustc_errors::Applicability;
+use rustc_hir::def_id::{DefId, DefIdMap};
+use rustc_hir::{GenericBound, Generics, PolyTraitRef, TraitBoundModifier, WherePredicate};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{ClauseKind, PredicatePolarity};
+use rustc_session::declare_lint_pass;
+use rustc_span::symbol::Ident;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Lints `?Sized` bounds applied to type parameters that cannot be unsized
+    ///
+    /// ### Why is this bad?
+    /// The `?Sized` bound is misleading because it cannot be satisfied by an
+    /// unsized type
+    ///
+    /// ### Example
+    /// ```rust
+    /// // `T` cannot be unsized because `Clone` requires it to be `Sized`
+    /// fn f<T: Clone + ?Sized>(t: &T) {}
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// fn f<T: Clone>(t: &T) {}
+    ///
+    /// // or choose alternative bounds for `T` so that it can be unsized
+    /// ```
+    #[clippy::version = "1.79.0"]
+    pub NEEDLESS_MAYBE_SIZED,
+    suspicious,
+    "a `?Sized` bound that is unusable due to a `Sized` requirement"
+}
+declare_lint_pass!(NeedlessMaybeSized => [NEEDLESS_MAYBE_SIZED]);
+
+#[allow(clippy::struct_field_names)]
+struct Bound<'tcx> {
+    /// The [`DefId`] of the type parameter the bound refers to
+    param: DefId,
+    ident: Ident,
+
+    trait_bound: &'tcx PolyTraitRef<'tcx>,
+    modifier: TraitBoundModifier,
+
+    predicate_pos: usize,
+    bound_pos: usize,
+}
+
+/// Finds all of the [`Bound`]s that refer to a type parameter and are not from a macro expansion
+fn type_param_bounds<'tcx>(generics: &'tcx Generics<'tcx>) -> impl Iterator<Item = Bound<'tcx>> {
+    generics
+        .predicates
+        .iter()
+        .enumerate()
+        .filter_map(|(predicate_pos, predicate)| {
+            let WherePredicate::BoundPredicate(bound_predicate) = predicate else {
+                return None;
+            };
+
+            let (param, ident) = bound_predicate.bounded_ty.as_generic_param()?;
+
+            Some(
+                bound_predicate
+                    .bounds
+                    .iter()
+                    .enumerate()
+                    .filter_map(move |(bound_pos, bound)| match bound {
+                        &GenericBound::Trait(ref trait_bound, modifier) => Some(Bound {
+                            param,
+                            ident,
+                            trait_bound,
+                            modifier,
+                            predicate_pos,
+                            bound_pos,
+                        }),
+                        GenericBound::Outlives(_) => None,
+                    })
+                    .filter(|bound| !bound.trait_bound.span.from_expansion()),
+            )
+        })
+        .flatten()
+}
+
+/// Searches the supertraits of the trait referred to by `trait_bound` recursively, returning the
+/// path taken to find a `Sized` bound if one is found
+fn path_to_sized_bound(cx: &LateContext<'_>, trait_bound: &PolyTraitRef<'_>) -> Option<Vec<DefId>> {
+    fn search(cx: &LateContext<'_>, path: &mut Vec<DefId>) -> bool {
+        let trait_def_id = *path.last().unwrap();
+
+        if Some(trait_def_id) == cx.tcx.lang_items().sized_trait() {
+            return true;
+        }
+
+        for &(predicate, _) in cx.tcx.super_predicates_of(trait_def_id).predicates {
+            if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder()
+                && trait_predicate.polarity == PredicatePolarity::Positive
+                && !path.contains(&trait_predicate.def_id())
+            {
+                path.push(trait_predicate.def_id());
+                if search(cx, path) {
+                    return true;
+                }
+                path.pop();
+            }
+        }
+
+        false
+    }
+
+    let mut path = vec![trait_bound.trait_ref.trait_def_id()?];
+    search(cx, &mut path).then_some(path)
+}
+
+impl LateLintPass<'_> for NeedlessMaybeSized {
+    fn check_generics(&mut self, cx: &LateContext<'_>, generics: &Generics<'_>) {
+        let Some(sized_trait) = cx.tcx.lang_items().sized_trait() else {
+            return;
+        };
+
+        let maybe_sized_params: DefIdMap<_> = type_param_bounds(generics)
+            .filter(|bound| {
+                bound.trait_bound.trait_ref.trait_def_id() == Some(sized_trait)
+                    && bound.modifier == TraitBoundModifier::Maybe
+            })
+            .map(|bound| (bound.param, bound))
+            .collect();
+
+        for bound in type_param_bounds(generics) {
+            if bound.modifier == TraitBoundModifier::None
+                && let Some(sized_bound) = maybe_sized_params.get(&bound.param)
+                && let Some(path) = path_to_sized_bound(cx, bound.trait_bound)
+            {
+                span_lint_and_then(
+                    cx,
+                    NEEDLESS_MAYBE_SIZED,
+                    sized_bound.trait_bound.span,
+                    "`?Sized` bound is ignored because of a `Sized` requirement",
+                    |diag| {
+                        let ty_param = sized_bound.ident;
+                        diag.span_note(
+                            bound.trait_bound.span,
+                            format!("`{ty_param}` cannot be unsized because of the bound"),
+                        );
+
+                        for &[current_id, next_id] in path.array_windows() {
+                            let current = cx.tcx.item_name(current_id);
+                            let next = cx.tcx.item_name(next_id);
+                            diag.note(format!("...because `{current}` has the bound `{next}`"));
+                        }
+
+                        diag.span_suggestion_verbose(
+                            generics.span_for_bound_removal(sized_bound.predicate_pos, sized_bound.bound_pos),
+                            "change the bounds that require `Sized`, or remove the `?Sized` bound",
+                            "",
+                            Applicability::MaybeIncorrect,
+                        );
+                    },
+                );
+
+                return;
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index da6ed5fb96f..57ba0da5331 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -1,7 +1,7 @@
 use super::needless_pass_by_value::requires_exact_signature;
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::source::snippet;
-use clippy_utils::visitors::for_each_expr_with_closures;
+use clippy_utils::visitors::for_each_expr;
 use clippy_utils::{inherits_cfg, is_from_proc_macro, is_self};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
@@ -205,7 +205,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
             // We retrieve all the closures declared in the function because they will not be found
             // by `euv::Delegate`.
             let mut closures: FxHashSet<LocalDefId> = FxHashSet::default();
-            for_each_expr_with_closures(cx, body, |expr| {
+            for_each_expr(cx, body, |expr| {
                 if let ExprKind::Closure(closure) = expr.kind {
                     closures.insert(closure.def_id);
                 }
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 932d6fe54d6..de6a1a36f3e 100644
--- a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
@@ -1,10 +1,11 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{is_res_lang_ctor, last_path_segment, path_res, std_or_core};
+use clippy_utils::{is_from_proc_macro, 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};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::EarlyBinder;
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
@@ -111,7 +112,7 @@ declare_lint_pass!(NonCanonicalImpls => [NON_CANONICAL_CLONE_IMPL, NON_CANONICAL
 
 impl LateLintPass<'_> for NonCanonicalImpls {
     #[expect(clippy::too_many_lines)]
-    fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
+    fn check_impl_item<'tcx>(&mut self, cx: &LateContext<'tcx>, impl_item: &ImplItem<'tcx>) {
         let Node::Item(item) = cx.tcx.parent_hir_node(impl_item.hir_id()) else {
             return;
         };
@@ -128,6 +129,9 @@ impl LateLintPass<'_> for NonCanonicalImpls {
         let ExprKind::Block(block, ..) = body.value.kind else {
             return;
         };
+        if in_external_macro(cx.sess(), block.span) || is_from_proc_macro(cx, impl_item) {
+            return;
+        }
 
         if cx.tcx.is_diagnostic_item(sym::Clone, trait_impl.def_id)
             && let Some(copy_def_id) = cx.tcx.get_diagnostic_item(sym::Copy)
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 20a97645af9..5cb8e7bfab2 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -7,7 +7,7 @@ use std::ptr;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::in_constant;
 use clippy_utils::macros::macro_backtrace;
-use clippy_utils::ty::InteriorMut;
+use clippy_utils::ty::{implements_trait, InteriorMut};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{
@@ -18,7 +18,7 @@ use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId};
 use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::impl_lint_pass;
-use rustc_span::{sym, InnerSpan, Span, DUMMY_SP};
+use rustc_span::{sym, Span, DUMMY_SP};
 use rustc_target::abi::VariantIdx;
 
 // FIXME: this is a correctness problem but there's no suitable
@@ -127,19 +127,19 @@ declare_clippy_lint! {
 }
 
 #[derive(Copy, Clone)]
-enum Source {
-    Item { item: Span },
+enum Source<'tcx> {
+    Item { item: Span, ty: Ty<'tcx> },
     Assoc { item: Span },
     Expr { expr: Span },
 }
 
-impl Source {
+impl Source<'_> {
     #[must_use]
     fn lint(&self) -> (&'static Lint, &'static str, Span) {
         match self {
-            Self::Item { item } | Self::Assoc { item, .. } => (
+            Self::Item { item, .. } | Self::Assoc { item, .. } => (
                 DECLARE_INTERIOR_MUTABLE_CONST,
-                "a `const` item should never be interior mutable",
+                "a `const` item should not be interior mutable",
                 *item,
             ),
             Self::Expr { expr } => (
@@ -151,16 +151,24 @@ impl Source {
     }
 }
 
-fn lint(cx: &LateContext<'_>, source: Source) {
+fn lint<'tcx>(cx: &LateContext<'tcx>, source: Source<'tcx>) {
     let (lint, msg, span) = source.lint();
     span_lint_and_then(cx, lint, span, msg, |diag| {
         if span.from_expansion() {
             return; // Don't give suggestions into macros.
         }
         match source {
-            Source::Item { .. } => {
-                let const_kw_span = span.from_inner(InnerSpan::new(0, 5));
-                diag.span_label(const_kw_span, "make this a static item (maybe with lazy_static)");
+            Source::Item { ty, .. } => {
+                let Some(sync_trait) = cx.tcx.lang_items().sync_trait() else {
+                    return;
+                };
+                if implements_trait(cx, ty, sync_trait, &[]) {
+                    diag.help("consider making this a static item");
+                } else {
+                    diag.help(
+                        "consider making this `Sync` so that it can go in a static item or using a `thread_local`",
+                    );
+                }
             },
             Source::Assoc { .. } => (),
             Source::Expr { .. } => {
@@ -311,7 +319,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
                 && self.interior_mut.is_interior_mut_ty(cx, ty)
                 && Self::is_value_unfrozen_poly(cx, body_id, ty)
             {
-                lint(cx, Source::Item { item: it.span });
+                lint(cx, Source::Item { item: it.span, ty });
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
index 910e584a7a0..641d881d974 100644
--- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::visitors::for_each_expr;
+use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{binop_traits, eq_expr_value, trait_ref_of_method};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
@@ -62,7 +62,7 @@ pub(super) fn check<'tcx>(
         };
 
         let mut found = false;
-        let found_multiple = for_each_expr(e, |e| {
+        let found_multiple = for_each_expr_without_closures(e, |e| {
             if eq_expr_value(cx, assignee, e) {
                 if found {
                     return ControlFlow::Break(());
diff --git a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs
index 806638c0505..381975199d2 100644
--- a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs
@@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for PanicInResultFn {
 
 fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir::Body<'tcx>) {
     let mut panics = Vec::new();
-    let _: Option<!> = for_each_expr(body.value, |e| {
+    let _: Option<!> = for_each_expr(cx, body.value, |e| {
         let Some(macro_call) = root_macro_call_first_node(cx, e) else {
             return ControlFlow::Continue(Descend::Yes);
         };
diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
index 0ed957f1f2f..313e4083256 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
@@ -4,7 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::peel_blocks;
 use clippy_utils::source::{snippet, walk_span_to_context};
 use clippy_utils::ty::implements_trait;
-use clippy_utils::visitors::for_each_expr;
+use clippy_utils::visitors::for_each_expr_without_closures;
 use rustc_errors::Applicability;
 use rustc_hir::{
     Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, MatchSource,
@@ -107,7 +107,7 @@ fn desugar_await<'tcx>(expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if let ExprKind::Match(match_value, _, MatchSource::AwaitDesugar) = expr.kind
         && let ExprKind::Call(_, [into_future_arg]) = match_value.kind
         && let ctxt = expr.span.ctxt()
-        && for_each_expr(into_future_arg, |e| {
+        && for_each_expr_without_closures(into_future_arg, |e| {
             walk_span_to_context(e.span, ctxt).map_or(ControlFlow::Break(()), |_| ControlFlow::Continue(()))
         })
         .is_none()
diff --git a/src/tools/clippy/clippy_lints/src/reference.rs b/src/tools/clippy/clippy_lints/src/reference.rs
index 16086ba6637..8f32cf5f2a1 100644
--- a/src/tools/clippy/clippy_lints/src/reference.rs
+++ b/src/tools/clippy/clippy_lints/src/reference.rs
@@ -48,6 +48,9 @@ impl EarlyLintPass for DerefAddrOf {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
         if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.kind
             && let ExprKind::AddrOf(_, ref mutability, ref addrof_target) = without_parens(deref_target).kind
+            // NOTE(tesuji): `*&` forces rustc to const-promote the array to `.rodata` section.
+            // See #12854 for details.
+            && !matches!(addrof_target.kind, ExprKind::Array(_))
             && deref_target.span.eq_ctxt(e.span)
             && !addrof_target.span.from_expansion()
         {
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 48d6fb3c037..c11da3147ef 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
 use clippy_utils::source::{snippet_opt, snippet_with_context};
 use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::visitors::{for_each_expr_with_closures, Descend};
+use clippy_utils::visitors::{for_each_expr, Descend};
 use clippy_utils::{
     binary_expr_needs_parentheses, fn_def_id, is_from_proc_macro, is_inside_let_else, is_res_lang_ctor, path_res,
     path_to_local_id, span_contains_cfg, span_find_starting_semi,
@@ -436,7 +436,7 @@ fn emit_return_lint(
 }
 
 fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
-    for_each_expr_with_closures(cx, expr, |e| {
+    for_each_expr(cx, expr, |e| {
         if let Some(def_id) = fn_def_id(cx, e)
             && cx
                 .tcx
diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
index 038eb92d652..979d6dc77ae 100644
--- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{indent_of, snippet};
 use clippy_utils::{expr_or_init, get_attr, path_to_local, peel_hir_expr_unary};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_expr, Visitor};
@@ -12,6 +12,7 @@ use rustc_session::impl_lint_pass;
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, Span, DUMMY_SP};
 use std::borrow::Cow;
+use std::collections::hash_map::Entry;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -57,7 +58,6 @@ impl_lint_pass!(SignificantDropTightening<'_> => [SIGNIFICANT_DROP_TIGHTENING]);
 pub struct SignificantDropTightening<'tcx> {
     apas: FxIndexMap<HirId, AuxParamsAttr>,
     /// Auxiliary structure used to avoid having to verify the same type multiple times.
-    seen_types: FxHashSet<Ty<'tcx>>,
     type_cache: FxHashMap<Ty<'tcx>, bool>,
 }
 
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
         self.apas.clear();
         let initial_dummy_stmt = dummy_stmt_expr(body.value);
         let mut ap = AuxParams::new(&mut self.apas, &initial_dummy_stmt);
-        StmtsChecker::new(&mut ap, cx, &mut self.seen_types, &mut self.type_cache).visit_body(body);
+        StmtsChecker::new(&mut ap, cx, &mut self.type_cache).visit_body(body);
         for apa in ap.apas.values() {
             if apa.counter <= 1 || !apa.has_expensive_expr_after_last_attr {
                 continue;
@@ -142,28 +142,25 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
 /// Checks the existence of the `#[has_significant_drop]` attribute.
 struct AttrChecker<'cx, 'others, 'tcx> {
     cx: &'cx LateContext<'tcx>,
-    seen_types: &'others mut FxHashSet<Ty<'tcx>>,
     type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
 }
 
 impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
-    pub(crate) fn new(
-        cx: &'cx LateContext<'tcx>,
-        seen_types: &'others mut FxHashSet<Ty<'tcx>>,
-        type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
-    ) -> Self {
-        seen_types.clear();
-        Self {
-            cx,
-            seen_types,
-            type_cache,
-        }
+    pub(crate) fn new(cx: &'cx LateContext<'tcx>, type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>) -> Self {
+        Self { cx, type_cache }
     }
 
     fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
-        // The borrow checker prevents us from using something fancier like or_insert_with.
-        if let Some(ty) = self.type_cache.get(&ty) {
-            return *ty;
+        let ty = self
+            .cx
+            .tcx
+            .try_normalize_erasing_regions(self.cx.param_env, ty)
+            .unwrap_or(ty);
+        match self.type_cache.entry(ty) {
+            Entry::Occupied(e) => return *e.get(),
+            Entry::Vacant(e) => {
+                e.insert(false);
+            },
         }
         let value = self.has_sig_drop_attr_uncached(ty);
         self.type_cache.insert(ty, value);
@@ -185,7 +182,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
             rustc_middle::ty::Adt(a, b) => {
                 for f in a.all_fields() {
                     let ty = f.ty(self.cx.tcx, b);
-                    if !self.has_seen_ty(ty) && self.has_sig_drop_attr(ty) {
+                    if self.has_sig_drop_attr(ty) {
                         return true;
                     }
                 }
@@ -205,16 +202,11 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
             _ => false,
         }
     }
-
-    fn has_seen_ty(&mut self, ty: Ty<'tcx>) -> bool {
-        !self.seen_types.insert(ty)
-    }
 }
 
 struct StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx> {
     ap: &'ap mut AuxParams<'others, 'stmt, 'tcx>,
     cx: &'lc LateContext<'tcx>,
-    seen_types: &'others mut FxHashSet<Ty<'tcx>>,
     type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
 }
 
@@ -222,15 +214,9 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx
     fn new(
         ap: &'ap mut AuxParams<'others, 'stmt, 'tcx>,
         cx: &'lc LateContext<'tcx>,
-        seen_types: &'others mut FxHashSet<Ty<'tcx>>,
         type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
     ) -> Self {
-        Self {
-            ap,
-            cx,
-            seen_types,
-            type_cache,
-        }
+        Self { ap, cx, type_cache }
     }
 
     fn manage_has_expensive_expr_after_last_attr(&mut self) {
@@ -288,7 +274,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o
             apa.counter = apa.counter.wrapping_add(1);
             apa.has_expensive_expr_after_last_attr = false;
         };
-        let mut ac = AttrChecker::new(self.cx, self.seen_types, self.type_cache);
+        let mut ac = AttrChecker::new(self.cx, self.type_cache);
         if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr)) {
             if let hir::StmtKind::Let(local) = self.ap.curr_stmt.kind
                 && let hir::PatKind::Binding(_, hir_id, ident, _) = local.pat.kind
diff --git a/src/tools/clippy/clippy_lints/src/string_patterns.rs b/src/tools/clippy/clippy_lints/src/string_patterns.rs
new file mode 100644
index 00000000000..64b5b8f9f27
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/string_patterns.rs
@@ -0,0 +1,227 @@
+use std::ops::ControlFlow;
+
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::eager_or_lazy::switch_to_eager_eval;
+use clippy_utils::macros::matching_root_macro_call;
+use clippy_utils::path_to_local_id;
+use clippy_utils::source::{snippet, str_literal_to_char_literal};
+use clippy_utils::visitors::{for_each_expr, Descend};
+use itertools::Itertools;
+use rustc_ast::{BinOpKind, LitKind};
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, PatKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
+use rustc_session::declare_lint_pass;
+use rustc_span::{sym, Span};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for manual `char` comparison in string patterns
+    ///
+    /// ### Why is this bad?
+    /// This can be written more concisely using a `char` or an array of `char`.
+    /// This is more readable and more optimized when comparing to only one `char`.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// "Hello World!".trim_end_matches(|c| c == '.' || c == ',' || c == '!' || c == '?');
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// "Hello World!".trim_end_matches(['.', ',', '!', '?']);
+    /// ```
+    #[clippy::version = "1.80.0"]
+    pub MANUAL_PATTERN_CHAR_COMPARISON,
+    style,
+    "manual char comparison in string patterns"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for string methods that receive a single-character
+    /// `str` as an argument, e.g., `_.split("x")`.
+    ///
+    /// ### Why is this bad?
+    /// While this can make a perf difference on some systems,
+    /// benchmarks have proven inconclusive. But at least using a
+    /// char literal makes it clear that we are looking at a single
+    /// character.
+    ///
+    /// ### Known problems
+    /// Does not catch multi-byte unicode characters. This is by
+    /// design, on many machines, splitting by a non-ascii char is
+    /// actually slower. Please do your own measurements instead of
+    /// relying solely on the results of this lint.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// _.split("x");
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust,ignore
+    /// _.split('x');
+    /// ```
+    #[clippy::version = "pre 1.29.0"]
+    pub SINGLE_CHAR_PATTERN,
+    pedantic,
+    "using a single-character str where a char could be used, e.g., `_.split(\"x\")`"
+}
+
+declare_lint_pass!(StringPatterns => [MANUAL_PATTERN_CHAR_COMPARISON, SINGLE_CHAR_PATTERN]);
+
+const PATTERN_METHODS: [(&str, usize); 22] = [
+    ("contains", 0),
+    ("starts_with", 0),
+    ("ends_with", 0),
+    ("find", 0),
+    ("rfind", 0),
+    ("split", 0),
+    ("split_inclusive", 0),
+    ("rsplit", 0),
+    ("split_terminator", 0),
+    ("rsplit_terminator", 0),
+    ("splitn", 1),
+    ("rsplitn", 1),
+    ("split_once", 0),
+    ("rsplit_once", 0),
+    ("matches", 0),
+    ("rmatches", 0),
+    ("match_indices", 0),
+    ("rmatch_indices", 0),
+    ("trim_start_matches", 0),
+    ("trim_end_matches", 0),
+    ("replace", 0),
+    ("replacen", 0),
+];
+
+fn check_single_char_pattern_lint(cx: &LateContext<'_>, arg: &Expr<'_>) {
+    let mut applicability = Applicability::MachineApplicable;
+    if let Some(hint) = str_literal_to_char_literal(cx, arg, &mut applicability, true) {
+        span_lint_and_sugg(
+            cx,
+            SINGLE_CHAR_PATTERN,
+            arg.span,
+            "single-character string constant used as pattern",
+            "consider using a `char`",
+            hint,
+            applicability,
+        );
+    }
+}
+
+fn get_char_span<'tcx>(cx: &'_ LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Span> {
+    if cx.typeck_results().expr_ty_adjusted(expr).is_char()
+        && !expr.span.from_expansion()
+        && switch_to_eager_eval(cx, expr)
+    {
+        Some(expr.span)
+    } else {
+        None
+    }
+}
+
+fn check_manual_pattern_char_comparison(cx: &LateContext<'_>, method_arg: &Expr<'_>) {
+    if let ExprKind::Closure(closure) = method_arg.kind
+        && let body = cx.tcx.hir().body(closure.body)
+        && let Some(PatKind::Binding(_, binding, ..)) = body.params.first().map(|p| p.pat.kind)
+    {
+        let mut set_char_spans: Vec<Span> = Vec::new();
+
+        // We want to retrieve all the comparisons done.
+        // They are ordered in a nested way and so we need to traverse the AST to collect them all.
+        if for_each_expr(cx, body.value, |sub_expr| -> ControlFlow<(), Descend> {
+            match sub_expr.kind {
+                ExprKind::Binary(op, left, right) if op.node == BinOpKind::Eq => {
+                    if path_to_local_id(left, binding)
+                        && let Some(span) = get_char_span(cx, right)
+                    {
+                        set_char_spans.push(span);
+                        ControlFlow::Continue(Descend::No)
+                    } else if path_to_local_id(right, binding)
+                        && let Some(span) = get_char_span(cx, left)
+                    {
+                        set_char_spans.push(span);
+                        ControlFlow::Continue(Descend::No)
+                    } else {
+                        ControlFlow::Break(())
+                    }
+                },
+                ExprKind::Binary(op, _, _) if op.node == BinOpKind::Or => ControlFlow::Continue(Descend::Yes),
+                ExprKind::Match(match_value, [arm, _], _) => {
+                    if matching_root_macro_call(cx, sub_expr.span, sym::matches_macro).is_none()
+                        || arm.guard.is_some()
+                        || !path_to_local_id(match_value, binding)
+                    {
+                        return ControlFlow::Break(());
+                    }
+                    if arm.pat.walk_short(|pat| match pat.kind {
+                        PatKind::Lit(expr) if let ExprKind::Lit(lit) = expr.kind => {
+                            if let LitKind::Char(_) = lit.node {
+                                set_char_spans.push(lit.span);
+                            }
+                            true
+                        },
+                        PatKind::Or(_) => true,
+                        _ => false,
+                    }) {
+                        ControlFlow::Continue(Descend::No)
+                    } else {
+                        ControlFlow::Break(())
+                    }
+                },
+                _ => ControlFlow::Break(()),
+            }
+        })
+        .is_some()
+        {
+            return;
+        }
+        span_lint_and_then(
+            cx,
+            MANUAL_PATTERN_CHAR_COMPARISON,
+            method_arg.span,
+            "this manual char comparison can be written more succinctly",
+            |diag| {
+                if let [set_char_span] = set_char_spans[..] {
+                    diag.span_suggestion(
+                        method_arg.span,
+                        "consider using a `char`",
+                        snippet(cx, set_char_span, "c"),
+                        Applicability::MachineApplicable,
+                    );
+                } else {
+                    diag.span_suggestion(
+                        method_arg.span,
+                        "consider using an array of `char`",
+                        format!(
+                            "[{}]",
+                            set_char_spans.into_iter().map(|span| snippet(cx, span, "c")).join(", ")
+                        ),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            },
+        );
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for StringPatterns {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        if !expr.span.from_expansion()
+            && let ExprKind::MethodCall(method, receiver, args, _) = expr.kind
+            && let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(receiver).kind()
+            && ty.is_str()
+            && let method_name = method.ident.name.as_str()
+            && let Some(&(_, pos)) = PATTERN_METHODS
+                .iter()
+                .find(|(array_method_name, _)| *array_method_name == method_name)
+            && let Some(arg) = args.get(pos)
+        {
+            check_single_char_pattern_lint(cx, arg);
+
+            check_manual_pattern_char_comparison(cx, arg);
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index f8d36d6b92f..7da661485ab 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -399,13 +399,17 @@ impl<'tcx> LateLintPass<'tcx> for StrToString {
             && let ty::Ref(_, ty, ..) = ty.kind()
             && ty.is_str()
         {
-            span_lint_and_help(
+            let mut applicability = Applicability::MachineApplicable;
+            let snippet = snippet_with_applicability(cx, self_arg.span, "..", &mut applicability);
+
+            span_lint_and_sugg(
                 cx,
                 STR_TO_STRING,
                 expr.span,
                 "`to_string()` called on a `&str`",
-                None,
-                "consider using `.to_owned()`",
+                "try",
+                format!("{snippet}.to_owned()"),
+                applicability,
             );
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
index 3f030b80331..744d6392e06 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::visitors::for_each_expr;
+use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{binop_traits, trait_ref_of_method, BINOP_TRAITS, OP_ASSIGN_TRAITS};
 use core::ops::ControlFlow;
 use rustc_hir as hir;
@@ -95,7 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
 
 fn count_binops(expr: &hir::Expr<'_>) -> u32 {
     let mut count = 0u32;
-    let _: Option<!> = for_each_expr(expr, |e| {
+    let _: Option<!> = for_each_expr_without_closures(expr, |e| {
         if matches!(
             e.kind,
             hir::ExprKind::Binary(..)
diff --git a/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs b/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs
index f98ea59a15d..b2892d136fa 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs
@@ -31,7 +31,6 @@ fn get_parent_local_binding_ty<'tcx>(cx: &LateContext<'tcx>, expr_hir_id: HirId)
 fn is_function_block(cx: &LateContext<'_>, expr_hir_id: HirId) -> bool {
     let def_id = cx.tcx.hir().enclosing_body_owner(expr_hir_id);
     if let Some(body) = cx.tcx.hir().maybe_body_owned_by(def_id) {
-        let body = cx.tcx.hir().body(body.id());
         return body.value.peel_blocks().hir_id == expr_hir_id;
     }
     false
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index 598032ccdeb..aa329ec3366 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -546,7 +546,7 @@ declare_clippy_lint! {
     /// let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
     /// # }
     /// ```
-    #[clippy::version = "1.77.0"]
+    #[clippy::version = "1.79.0"]
     pub MISSING_TRANSMUTE_ANNOTATIONS,
     suspicious,
     "warns if a transmute call doesn't have all generics specified"
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index 6cf9229fdd0..93a1089a970 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::is_lint_allowed;
 use clippy_utils::source::walk_span_to_context;
-use clippy_utils::visitors::{for_each_expr_with_closures, Descend};
+use clippy_utils::visitors::{for_each_expr, Descend};
 use hir::HirId;
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
@@ -296,7 +296,7 @@ fn expr_has_unnecessary_safety_comment<'tcx>(
     }
 
     // this should roughly be the reverse of `block_parents_have_safety_comment`
-    if for_each_expr_with_closures(cx, expr, |expr| match expr.kind {
+    if for_each_expr(cx, expr, |expr| match expr.kind {
         hir::ExprKind::Block(
             Block {
                 rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided),
diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs
index a67f53f00ae..3e6102f5982 100644
--- a/src/tools/clippy/clippy_lints/src/unused_self.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_self.rs
@@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
         let parent_item = cx.tcx.hir().expect_item(parent);
         let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
         let contains_todo = |cx, body: &'_ Body<'_>| -> bool {
-            clippy_utils::visitors::for_each_expr(body.value, |e| {
+            clippy_utils::visitors::for_each_expr_without_closures(body.value, |e| {
                 if let Some(macro_call) = root_macro_call_first_node(cx, e) {
                     if cx.tcx.item_name(macro_call.def_id).as_str() == "todo" {
                         ControlFlow::Break(())
diff --git a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
index 197ab0f173b..f77badd97b7 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
@@ -77,7 +77,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tc
         let body = cx.tcx.hir().body(body_id);
         let typeck = cx.tcx.typeck(impl_item.owner_id.def_id);
         let mut result = Vec::new();
-        let _: Option<!> = for_each_expr(body.value, |e| {
+        let _: Option<!> = for_each_expr(cx, body.value, |e| {
             // check for `expect`
             if let Some(arglists) = method_chain_args(e, &["expect"]) {
                 let receiver_ty = typeck.expr_ty(arglists[0].0).peel_refs();
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 18a31abddd0..e9d69407df8 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -733,7 +733,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
         match stmt.value.kind {
             StmtKind::Let(local) => {
                 bind!(self, local);
-                kind!("Local({local})");
+                kind!("Let({local})");
                 self.option(field!(local.init), "init", |init| {
                     self.expr(init);
                 });
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
index 9be225759df..84f84781e71 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
@@ -213,7 +213,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
                     output: &mut self.registered_lints,
                     cx,
                 };
-                let body_id = cx.tcx.hir().body_owned_by(
+                let body = cx.tcx.hir().body_owned_by(
                     impl_item_refs
                         .iter()
                         .find(|iiref| iiref.ident.as_str() == "get_lints")
@@ -222,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
                         .owner_id
                         .def_id,
                 );
-                collector.visit_expr(cx.tcx.hir().body(body_id).value);
+                collector.visit_expr(body.value);
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 5c1ebb922f1..1c149f20456 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -719,7 +719,7 @@ fn get_lint_group_and_level_or_lint(
         Some(sym::clippy),
         &std::iter::once(Ident::with_dummy_span(sym::clippy)).collect(),
     );
-    if let CheckLintNameResult::Tool(Ok(lint_lst)) = result {
+    if let CheckLintNameResult::Tool(lint_lst, None) = result {
         if let Some(group) = get_lint_group(cx, lint_lst[0]) {
             if EXCLUDED_LINT_GROUPS.contains(&group.as_str()) {
                 return None;
diff --git a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
index 8796b8f61d1..ad041e55bda 100644
--- a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::higher::VecArgs;
 use clippy_utils::source::snippet;
-use clippy_utils::visitors::for_each_expr;
+use clippy_utils::visitors::for_each_expr_without_closures;
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{ExprKind, Node};
@@ -36,7 +36,7 @@ declare_clippy_lint! {
     /// side_effect();
     /// let a: [i32; 0] = [];
     /// ```
-    #[clippy::version = "1.75.0"]
+    #[clippy::version = "1.79.0"]
     pub ZERO_REPEAT_SIDE_EFFECTS,
     suspicious,
     "usage of zero-sized initializations of arrays or vecs causing side effects"
@@ -65,7 +65,7 @@ impl LateLintPass<'_> for ZeroRepeatSideEffects {
 
 fn inner_check(cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>, inner_expr: &'_ rustc_hir::Expr<'_>, is_vec: bool) {
     // check if expr is a call or has a call inside it
-    if for_each_expr(inner_expr, |x| {
+    if for_each_expr_without_closures(inner_expr, |x| {
         if let ExprKind::Call(_, _) | ExprKind::MethodCall(_, _, _, _) = x.kind {
             std::ops::ControlFlow::Break(())
         } else {
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index ab883c25338..3a3aeb88216 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_utils"
-version = "0.1.80"
+version = "0.1.81"
 edition = "2021"
 publish = false
 
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index e9e1aa7e445..cfd142fe1ff 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -412,7 +412,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     /// Simple constant folding: Insert an expression, get a constant or none.
     pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
         match e.kind {
-            ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.lcx.tcx.hir().body(body).value), ExprKind::DropTemps(e) => self.expr(e),
+            ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.lcx.tcx.hir().body(body).value),
+            ExprKind::DropTemps(e) => self.expr(e),
             ExprKind::Path(ref qpath) => {
                 self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| {
                     let result = mir_to_const(this.lcx, result)?;
@@ -490,7 +491,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     /// leaves the local crate.
     pub fn expr_is_empty(&mut self, e: &Expr<'_>) -> Option<bool> {
         match e.kind {
-            ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr_is_empty(self.lcx.tcx.hir().body(body).value), ExprKind::DropTemps(e) => self.expr_is_empty(e),
+            ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr_is_empty(self.lcx.tcx.hir().body(body).value),
+            ExprKind::DropTemps(e) => self.expr_is_empty(e),
             ExprKind::Path(ref qpath) => {
                 if !self
                     .typeck_results
@@ -811,12 +813,8 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
             ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
             ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
             ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.to_bits(int.size()))),
-            ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
-                int.try_into().expect("invalid f32 bit representation"),
-            ))),
-            ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
-                int.try_into().expect("invalid f64 bit representation"),
-            ))),
+            ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(int.into()))),
+            ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(int.into()))),
             ty::RawPtr(_, _) => Some(Constant::RawPtr(int.to_bits(int.size()))),
             _ => None,
         },
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 36634817fc9..50dd8430ac0 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -7,9 +7,9 @@ use rustc_data_structures::fx::FxHasher;
 use rustc_hir::def::Res;
 use rustc_hir::MatchSource::TryDesugar;
 use rustc_hir::{
-    ArrayLen, BinOpKind, BindingMode, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
-    GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField, PatKind, Path,
-    PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, AssocItemConstraint,
+    ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy,
+    GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField,
+    PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
 };
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::LateContext;
@@ -519,7 +519,11 @@ impl HirEqInterExpr<'_, '_, '_> {
     }
 
     fn eq_assoc_type_binding(&mut self, left: &AssocItemConstraint<'_>, right: &AssocItemConstraint<'_>) -> bool {
-        left.ident.name == right.ident.name && self.eq_ty(left.ty().expect("expected assoc type binding"), right.ty().expect("expected assoc type binding"))
+        left.ident.name == right.ident.name
+            && self.eq_ty(
+                left.ty().expect("expected assoc type binding"),
+                right.ty().expect("expected assoc type binding"),
+            )
     }
 
     fn check_ctxt(&mut self, left: SyntaxContext, right: SyntaxContext) -> bool {
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 2f6bf920967..7dc341ec8d7 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -126,7 +126,7 @@ use visitors::Visitable;
 use crate::consts::{constant, mir_to_const, Constant};
 use crate::higher::Range;
 use crate::ty::{adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type};
-use crate::visitors::for_each_expr;
+use crate::visitors::for_each_expr_without_closures;
 
 use rustc_middle::hir::nested_filter;
 
@@ -321,6 +321,15 @@ pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str])
         .map_or(false, |trt_id| match_def_path(cx, trt_id, path))
 }
 
+/// Checks if the given method call expression calls an inherent method.
+pub fn is_inherent_method_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
+        cx.tcx.trait_of_item(method_id).is_none()
+    } else {
+        false
+    }
+}
+
 /// Checks if a method is defined in an impl of a diagnostic item
 pub fn is_diag_item_method(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
     if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
@@ -1313,7 +1322,7 @@ pub fn contains_name<'tcx>(name: Symbol, expr: &'tcx Expr<'_>, cx: &LateContext<
 
 /// Returns `true` if `expr` contains a return expression
 pub fn contains_return<'tcx>(expr: impl Visitable<'tcx>) -> bool {
-    for_each_expr(expr, |e| {
+    for_each_expr_without_closures(expr, |e| {
         if matches!(e.kind, ExprKind::Ret(..)) {
             ControlFlow::Break(())
         } else {
@@ -3392,3 +3401,14 @@ pub fn binary_expr_needs_parentheses(expr: &Expr<'_>) -> bool {
 
     contains_block(expr, false)
 }
+
+/// Returns true if the specified expression is in a receiver position.
+pub fn is_receiver_of_method_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    if let Some(parent_expr) = get_parent_expr(cx, expr)
+        && let ExprKind::MethodCall(_, receiver, ..) = parent_expr.kind
+        && receiver.hir_id == expr.hir_id
+    {
+        return true;
+    }
+    false
+}
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 8daab9b0d92..455239cc37f 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -1,6 +1,6 @@
 #![allow(clippy::similar_names)] // `expr` and `expn`
 
-use crate::visitors::{for_each_expr, Descend};
+use crate::visitors::{for_each_expr_without_closures, Descend};
 
 use arrayvec::ArrayVec;
 use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder};
@@ -323,7 +323,7 @@ fn find_assert_args_inner<'a, const N: usize>(
         Some(inner_name) => find_assert_within_debug_assert(cx, expr, expn, Symbol::intern(inner_name))?,
     };
     let mut args = ArrayVec::new();
-    let panic_expn = for_each_expr(expr, |e| {
+    let panic_expn = for_each_expr_without_closures(expr, |e| {
         if args.is_full() {
             match PanicExpn::parse(e) {
                 Some(expn) => ControlFlow::Break(expn),
@@ -349,7 +349,7 @@ fn find_assert_within_debug_assert<'a>(
     expn: ExpnId,
     assert_name: Symbol,
 ) -> Option<(&'a Expr<'a>, ExpnId)> {
-    for_each_expr(expr, |e| {
+    for_each_expr_without_closures(expr, |e| {
         if !e.span.from_expansion() {
             return ControlFlow::Continue(Descend::No);
         }
@@ -397,7 +397,7 @@ impl FormatArgsStorage {
     ///
     /// See also [`find_format_arg_expr`]
     pub fn get(&self, cx: &LateContext<'_>, start: &Expr<'_>, expn_id: ExpnId) -> Option<&FormatArgs> {
-        let format_args_expr = for_each_expr(start, |expr| {
+        let format_args_expr = for_each_expr_without_closures(start, |expr| {
             let ctxt = expr.span.ctxt();
             if ctxt.outer_expn().is_descendant_of(expn_id) {
                 if macro_backtrace(expr.span)
@@ -439,7 +439,7 @@ pub fn find_format_arg_expr<'hir, 'ast>(
         parent: _,
     } = target.expr.span.data();
 
-    for_each_expr(start, |expr| {
+    for_each_expr_without_closures(start, |expr| {
         // When incremental compilation is enabled spans gain a parent during AST to HIR lowering,
         // since we're comparing an AST span to a HIR one we need to ignore the parent field
         let data = expr.span.data();
diff --git a/src/tools/clippy/clippy_utils/src/ptr.rs b/src/tools/clippy/clippy_utils/src/ptr.rs
index 88837d8a143..991ea428dc3 100644
--- a/src/tools/clippy/clippy_utils/src/ptr.rs
+++ b/src/tools/clippy/clippy_utils/src/ptr.rs
@@ -1,5 +1,5 @@
 use crate::source::snippet;
-use crate::visitors::{for_each_expr, Descend};
+use crate::visitors::{for_each_expr_without_closures, Descend};
 use crate::{path_to_local_id, strip_pat_refs};
 use core::ops::ControlFlow;
 use rustc_hir::{Body, BodyId, ExprKind, HirId, PatKind};
@@ -31,7 +31,7 @@ fn extract_clone_suggestions<'tcx>(
     body: &'tcx Body<'_>,
 ) -> Option<Vec<(Span, Cow<'static, str>)>> {
     let mut spans = Vec::new();
-    for_each_expr(body, |e| {
+    for_each_expr_without_closures(body, |e| {
         if let ExprKind::MethodCall(seg, recv, [], _) = e.kind
             && path_to_local_id(recv, id)
         {
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 81e94725a70..42b10f69c0c 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
@@ -40,9 +40,13 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
     )?;
 
     for bb in &*body.basic_blocks {
-        check_terminator(tcx, body, bb.terminator(), msrv)?;
-        for stmt in &bb.statements {
-            check_statement(tcx, body, def_id, stmt, msrv)?;
+        // Cleanup blocks are ignored entirely by const eval, so we can too:
+        // https://github.com/rust-lang/rust/blob/1dea922ea6e74f99a0e97de5cdb8174e4dea0444/compiler/rustc_const_eval/src/transform/check_consts/check.rs#L382
+        if !bb.is_cleanup {
+            check_terminator(tcx, body, bb.terminator(), msrv)?;
+            for stmt in &bb.statements {
+                check_statement(tcx, body, def_id, stmt, msrv)?;
+            }
         }
     }
     Ok(())
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
index fd67e039c29..e2e5cde947d 100644
--- a/src/tools/clippy/clippy_utils/src/source.rs
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -2,6 +2,7 @@
 
 #![allow(clippy::module_name_repetitions)]
 
+use rustc_ast::{LitKind, StrStyle};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::Applicability;
 use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource};
@@ -500,6 +501,50 @@ pub fn expand_past_previous_comma(cx: &LateContext<'_>, span: Span) -> Span {
     extended.with_lo(extended.lo() - BytePos(1))
 }
 
+/// Converts `expr` to a `char` literal if it's a `str` literal containing a single
+/// character (or a single byte with `ascii_only`)
+pub fn str_literal_to_char_literal(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    applicability: &mut Applicability,
+    ascii_only: bool,
+) -> Option<String> {
+    if let ExprKind::Lit(lit) = &expr.kind
+        && let LitKind::Str(r, style) = lit.node
+        && let string = r.as_str()
+        && let len = if ascii_only {
+            string.len()
+        } else {
+            string.chars().count()
+        }
+        && len == 1
+    {
+        let snip = snippet_with_applicability(cx, expr.span, string, applicability);
+        let ch = if let StrStyle::Raw(nhash) = style {
+            let nhash = nhash as usize;
+            // for raw string: r##"a"##
+            &snip[(nhash + 2)..(snip.len() - 1 - nhash)]
+        } else {
+            // for regular string: "a"
+            &snip[1..(snip.len() - 1)]
+        };
+
+        let hint = format!(
+            "'{}'",
+            match ch {
+                "'" => "\\'",
+                r"\" => "\\\\",
+                "\\\"" => "\"", // no need to escape `"` in `'"'`
+                _ => ch,
+            }
+        );
+
+        Some(hint)
+    } else {
+        None
+    }
+}
+
 #[cfg(test)]
 mod test {
     use super::{reindent_multiline, without_block_comments};
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 6e5626297c9..7d4332a3d9d 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -17,9 +17,9 @@ use rustc_middle::mir::ConstValue;
 use rustc_middle::traits::EvaluationResult;
 use rustc_middle::ty::layout::ValidityRequirement;
 use rustc_middle::ty::{
-    self, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, GenericArgsRef,
-    GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
-    TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr,
+    self, AdtDef, AliasTy, AssocItem, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind,
+    GenericArgsRef, GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable,
+    TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr,
 };
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, Span, Symbol, DUMMY_SP};
@@ -861,7 +861,6 @@ impl core::ops::Add<u32> for EnumValue {
 }
 
 /// Attempts to read the given constant as though it were an enum value.
-#[expect(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
 pub fn read_explicit_enum_value(tcx: TyCtxt<'_>, id: DefId) -> Option<EnumValue> {
     if let Ok(ConstValue::Scalar(Scalar::Int(value))) = tcx.const_eval_poly(id) {
         match tcx.type_of(id).instantiate_identity().kind() {
@@ -1314,3 +1313,39 @@ pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>
 pub fn is_manually_drop(ty: Ty<'_>) -> bool {
     ty.ty_adt_def().map_or(false, AdtDef::is_manually_drop)
 }
+
+/// Returns the deref chain of a type, starting with the type itself.
+pub fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'cx {
+    iter::successors(Some(ty), |&ty| {
+        if let Some(deref_did) = cx.tcx.lang_items().deref_trait()
+            && implements_trait(cx, ty, deref_did, &[])
+        {
+            make_normalized_projection(cx.tcx, cx.param_env, deref_did, sym::Target, [ty])
+        } else {
+            None
+        }
+    })
+}
+
+/// Checks if a Ty<'_> has some inherent method Symbol.
+/// This does not look for impls in the type's `Deref::Target` type.
+/// If you need this, you should wrap this call in `clippy_utils::ty::deref_chain().any(...)`.
+pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> Option<&'a AssocItem> {
+    if let Some(ty_did) = ty.ty_adt_def().map(AdtDef::did) {
+        cx.tcx
+            .inherent_impls(ty_did)
+            .into_iter()
+            .flatten()
+            .map(|&did| {
+                cx.tcx
+                    .associated_items(did)
+                    .filter_by_name_unhygienic(method_name)
+                    .next()
+                    .filter(|item| item.kind == AssocKind::Fn)
+            })
+            .next()
+            .flatten()
+    } else {
+        None
+    }
+}
diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
index 80219303450..cba61c841ef 100644
--- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
@@ -206,8 +206,18 @@ fn path_segment_certainty(
             // Checking `res_generics_def_id(..)` before calling `generics_of` avoids an ICE.
             if cx.tcx.res_generics_def_id(path_segment.res).is_some() {
                 let generics = cx.tcx.generics_of(def_id);
-                let count = generics.own_params.len() - usize::from(generics.host_effect_index.is_some());
-                let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && count == 0 {
+
+                let own_count = generics.own_params.len()
+                    - usize::from(generics.host_effect_index.is_some_and(|index| {
+                        // Check that the host index actually belongs to this resolution.
+                        // E.g. for `Add::add`, host_effect_index is `Some(2)`, but it's part of the parent `Add`
+                        // trait's generics.
+                        // Add params:      [Self#0, Rhs#1, host#2]   parent_count=0, count=3
+                        // Add::add params: []                        parent_count=3, count=3
+                        // (3..3).contains(&host_effect_index) => false
+                        (generics.parent_count..generics.count()).contains(&index)
+                    }));
+                let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && own_count == 0 {
                     Certainty::Certain(None)
                 } else {
                     Certainty::Uncertain
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index 2a25d51d8e5..fbf3d95365a 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -1,4 +1,4 @@
-use crate::visitors::{for_each_expr, for_each_expr_with_closures, Descend, Visitable};
+use crate::visitors::{for_each_expr, for_each_expr_without_closures, Descend, Visitable};
 use crate::{self as utils, get_enclosing_loop_or_multi_call_closure};
 use core::ops::ControlFlow;
 use hir::def::Res;
@@ -145,7 +145,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BindingUsageFinder<'a, 'tcx> {
 }
 
 pub fn contains_return_break_continue_macro(expression: &Expr<'_>) -> bool {
-    for_each_expr(expression, |e| {
+    for_each_expr_without_closures(expression, |e| {
         match e.kind {
             ExprKind::Ret(..) | ExprKind::Break(..) | ExprKind::Continue(..) => ControlFlow::Break(()),
             // Something special could be done here to handle while or for loop
@@ -159,7 +159,7 @@ pub fn contains_return_break_continue_macro(expression: &Expr<'_>) -> bool {
 }
 
 pub fn local_used_in<'tcx>(cx: &LateContext<'tcx>, local_id: HirId, v: impl Visitable<'tcx>) -> bool {
-    for_each_expr_with_closures(cx, v, |e| {
+    for_each_expr(cx, v, |e| {
         if utils::path_to_local_id(e, local_id) {
             ControlFlow::Break(())
         } else {
@@ -184,7 +184,7 @@ pub fn local_used_after_expr(cx: &LateContext<'_>, local_id: HirId, after: &Expr
     let loop_start = get_enclosing_loop_or_multi_call_closure(cx, after).map(|e| e.hir_id);
 
     let mut past_expr = false;
-    for_each_expr_with_closures(cx, block, |e| {
+    for_each_expr(cx, block, |e| {
         if past_expr {
             if utils::path_to_local_id(e, local_id) {
                 ControlFlow::Break(())
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 90b56297bb5..3a39e178515 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -100,7 +100,7 @@ visitable_ref!(Stmt, visit_stmt);
 
 /// Calls the given function once for each expression contained. This does not enter any bodies or
 /// nested items.
-pub fn for_each_expr<'tcx, B, C: Continue>(
+pub fn for_each_expr_without_closures<'tcx, B, C: Continue>(
     node: impl Visitable<'tcx>,
     f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>,
 ) -> Option<B> {
@@ -134,7 +134,7 @@ pub fn for_each_expr<'tcx, B, C: Continue>(
 
 /// Calls the given function once for each expression contained. This will enter bodies, but not
 /// nested items.
-pub fn for_each_expr_with_closures<'tcx, B, C: Continue>(
+pub fn for_each_expr<'tcx, B, C: Continue>(
     cx: &LateContext<'tcx>,
     node: impl Visitable<'tcx>,
     f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>,
@@ -181,7 +181,7 @@ pub fn for_each_expr_with_closures<'tcx, B, C: Continue>(
 
 /// returns `true` if expr contains match expr desugared from try
 fn contains_try(expr: &Expr<'_>) -> bool {
-    for_each_expr(expr, |e| {
+    for_each_expr_without_closures(expr, |e| {
         if matches!(e.kind, ExprKind::Match(_, _, hir::MatchSource::TryDesugar(_))) {
             ControlFlow::Break(())
         } else {
@@ -286,7 +286,7 @@ where
 
 /// Checks if the given resolved path is used in the given body.
 pub fn is_res_used(cx: &LateContext<'_>, res: Res, body: BodyId) -> bool {
-    for_each_expr_with_closures(cx, cx.tcx.hir().body(body).value, |e| {
+    for_each_expr(cx, cx.tcx.hir().body(body).value, |e| {
         if let ExprKind::Path(p) = &e.kind {
             if cx.qpath_res(p, e.hir_id) == res {
                 return ControlFlow::Break(());
@@ -299,7 +299,7 @@ pub fn is_res_used(cx: &LateContext<'_>, res: Res, body: BodyId) -> bool {
 
 /// Checks if the given local is used.
 pub fn is_local_used<'tcx>(cx: &LateContext<'tcx>, visitable: impl Visitable<'tcx>, id: HirId) -> bool {
-    for_each_expr_with_closures(cx, visitable, |e| {
+    for_each_expr(cx, visitable, |e| {
         if path_to_local_id(e, id) {
             ControlFlow::Break(())
         } else {
@@ -757,7 +757,7 @@ pub fn for_each_local_assignment<'tcx, B>(
 }
 
 pub fn contains_break_or_continue(expr: &Expr<'_>) -> bool {
-    for_each_expr(expr, |e| {
+    for_each_expr_without_closures(expr, |e| {
         if matches!(e.kind, ExprKind::Break(..) | ExprKind::Continue(..)) {
             ControlFlow::Break(())
         } else {
@@ -776,7 +776,7 @@ pub fn local_used_once<'tcx>(
 ) -> Option<&'tcx Expr<'tcx>> {
     let mut expr = None;
 
-    let cf = for_each_expr_with_closures(cx, visitable, |e| {
+    let cf = for_each_expr(cx, visitable, |e| {
         if path_to_local_id(e, id) && expr.replace(e).is_some() {
             ControlFlow::Break(())
         } else {
diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml
index c8c734c3a7c..86d945c14a5 100644
--- a/src/tools/clippy/declare_clippy_lint/Cargo.toml
+++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "declare_clippy_lint"
-version = "0.1.80"
+version = "0.1.81"
 edition = "2021"
 publish = false
 
diff --git a/src/tools/clippy/lintcheck/README.md b/src/tools/clippy/lintcheck/README.md
index 37cc0453809..61b581ba0fa 100644
--- a/src/tools/clippy/lintcheck/README.md
+++ b/src/tools/clippy/lintcheck/README.md
@@ -1,6 +1,6 @@
 ## `cargo lintcheck`
 
-Runs clippy on a fixed set of crates read from
+Runs Clippy on a fixed set of crates read from
 `lintcheck/lintcheck_crates.toml` and saves logs of the lint warnings into the
 repo.  We can then check the diff and spot new or disappearing warnings.
 
@@ -84,7 +84,7 @@ This lets us spot bad suggestions or false positives automatically in some cases
 
 > Note: Fix mode implies `--all-targets`, so it can fix as much code as it can.
 
-Please note that the target dir should be cleaned afterwards since clippy will modify
+Please note that the target dir should be cleaned afterwards since Clippy will modify
 the downloaded sources which can lead to unexpected results when running lintcheck again afterwards.
 
 ### Recursive mode
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index dd8b9ece773..842c2f3de0d 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2024-05-30"
+channel = "nightly-2024-06-13"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr
index 9177e99f8e6..4fe7f6f7a9e 100644
--- a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr
+++ b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr
@@ -1,17 +1,18 @@
 error: lint group `rust_2018_idioms` has the same priority (0) as a lint
- --> Cargo.toml:7:1
-  |
-7 | rust_2018_idioms = "warn"
-  | ^^^^^^^^^^^^^^^^   ------ has an implicit priority of 0
-8 | bare_trait_objects = "allow"
-  | ------------------ has the same priority as this lint
-  |
-  = note: the order of the lints in the table is ignored by Cargo
-  = note: `#[deny(clippy::lint_groups_priority)]` on by default
+  --> Cargo.toml:7:1
+   |
+7  | rust_2018_idioms = "warn"
+   | ^^^^^^^^^^^^^^^^   ------ has an implicit priority of 0
+...
+12 | unused_attributes = { level = "allow" }
+   | ----------------- has the same priority as this lint
+   |
+   = note: the order of the lints in the table is ignored by Cargo
+   = note: `#[deny(clippy::lint_groups_priority)]` on by default
 help: to have lints override the group set `rust_2018_idioms` to a lower priority
-  |
-7 | rust_2018_idioms = { level = "warn", priority = -1 }
-  |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |
+7  | rust_2018_idioms = { level = "warn", priority = -1 }
+   |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: lint group `unused` has the same priority (0) as a lint
   --> Cargo.toml:10:1
@@ -29,45 +30,45 @@ help: to have lints override the group set `unused` to a lower priority
    |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: lint group `pedantic` has the same priority (-1) as a lint
-  --> Cargo.toml:19:1
+  --> Cargo.toml:15:1
    |
-19 | pedantic = { level = "warn", priority = -1 }
+15 | pedantic = { level = "warn", priority = -1 }
    | ^^^^^^^^
-20 | similar_names = { level = "allow", priority = -1 }
+16 | similar_names = { level = "allow", priority = -1 }
    | ------------- has the same priority as this lint
    |
    = note: the order of the lints in the table is ignored by Cargo
 help: to have lints override the group set `pedantic` to a lower priority
    |
-19 | pedantic = { level = "warn", priority = -2 }
+15 | pedantic = { level = "warn", priority = -2 }
    |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: lint group `rust_2018_idioms` has the same priority (0) as a lint
-  --> Cargo.toml:23:1
+  --> Cargo.toml:19:1
    |
-23 | rust_2018_idioms = "warn"
+19 | rust_2018_idioms = "warn"
    | ^^^^^^^^^^^^^^^^   ------ has an implicit priority of 0
-24 | bare_trait_objects = "allow"
+20 | bare_trait_objects = "allow"
    | ------------------ has the same priority as this lint
    |
    = note: the order of the lints in the table is ignored by Cargo
 help: to have lints override the group set `rust_2018_idioms` to a lower priority
    |
-23 | rust_2018_idioms = { level = "warn", priority = -1 }
+19 | rust_2018_idioms = { level = "warn", priority = -1 }
    |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: lint group `pedantic` has the same priority (0) as a lint
-  --> Cargo.toml:27:1
+  --> Cargo.toml:23:1
    |
-27 | pedantic = "warn"
+23 | pedantic = "warn"
    | ^^^^^^^^   ------ has an implicit priority of 0
-28 | similar_names = "allow"
+24 | similar_names = "allow"
    | ------------- has the same priority as this lint
    |
    = note: the order of the lints in the table is ignored by Cargo
 help: to have lints override the group set `pedantic` to a lower priority
    |
-27 | pedantic = { level = "warn", priority = -1 }
+23 | pedantic = { level = "warn", priority = -1 }
    |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: could not compile `fail` (lib) due to 5 previous errors
diff --git a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml
index e4d4af9cd23..c87662f822e 100644
--- a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml
+++ b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml
@@ -11,10 +11,6 @@ unused = { level = "deny" }
 unused_braces = { level = "allow", priority = 1 }
 unused_attributes = { level = "allow" }
 
-# `warnings` is not a group so the order it is passed does not matter
-warnings = "deny"
-deprecated  = "allow"
-
 [lints.clippy]
 pedantic = { level = "warn", priority = -1 }
 similar_names = { level = "allow", priority = -1 }
diff --git a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/pass/Cargo.toml b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/pass/Cargo.toml
index e9fcf803d93..979c915cf0c 100644
--- a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/pass/Cargo.toml
+++ b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/pass/Cargo.toml
@@ -3,6 +3,13 @@ name = "pass"
 version = "0.1.0"
 publish = false
 
+[lints.rust]
+# Warnings does not conflict with any group or lint
+warnings = "deny"
+# Groups & lints at the same level do not conflict
+rust_2018_idioms = "warn"
+unsafe_code = "warn"
+
 [lints.clippy]
 pedantic = { level = "warn", priority = -1 }
 style = { level = "warn", priority = 1 }
diff --git a/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.rs b/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.rs
index ae4c3f84c29..79c8751468d 100644
--- a/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.rs
+++ b/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.rs
@@ -47,7 +47,7 @@ pub mod __macro {
     pub struct T;
     impl T {
         pub unsafe fn f() {}
-        //~^ ERROR: unsafe function's docs miss `# Safety` section
+        //~^ ERROR: unsafe function's docs are missing a `# Safety` section
     }
 }
 
diff --git a/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.stderr b/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.stderr
index 65ec1a7bebb..a8ee09b9df7 100644
--- a/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.stderr
+++ b/src/tools/clippy/tests/ui-toml/private-doc-errors/doc_lints.stderr
@@ -51,7 +51,7 @@ note: the lint level is defined here
 LL |     clippy::missing_panics_doc
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: unsafe function's docs miss `# Safety` section
+error: unsafe function's docs are missing a `# Safety` section
   --> tests/ui-toml/private-doc-errors/doc_lints.rs:49:9
    |
 LL |         pub unsafe fn f() {}
diff --git a/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.rs b/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.rs
index 2454c10382d..7f93d2071c9 100644
--- a/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.rs
+++ b/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.rs
@@ -1,3 +1,4 @@
+#![allow(clippy::needless_maybe_sized)]
 #![warn(clippy::type_repetition_in_bounds)]
 
 fn f<T>()
diff --git a/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.stderr b/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.stderr
index 6005f76b94b..c5102c39d1c 100644
--- a/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.stderr
+++ b/src/tools/clippy/tests/ui-toml/type_repetition_in_bounds/main.stderr
@@ -1,5 +1,5 @@
 error: this type has already been used as a bound predicate
-  --> tests/ui-toml/type_repetition_in_bounds/main.rs:13:5
+  --> tests/ui-toml/type_repetition_in_bounds/main.rs:14:5
    |
 LL |     T: Unpin + PartialEq,
    |     ^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/author.stdout b/src/tools/clippy/tests/ui/author.stdout
index d448db097a7..eed704e82fe 100644
--- a/src/tools/clippy/tests/ui/author.stdout
+++ b/src/tools/clippy/tests/ui/author.stdout
@@ -1,4 +1,4 @@
-if let StmtKind::Local(local) = stmt.kind
+if let StmtKind::Let(local) = stmt.kind
     && let Some(init) = local.init
     && let ExprKind::Cast(expr, cast_ty) = init.kind
     && let TyKind::Path(ref qpath) = cast_ty.kind
diff --git a/src/tools/clippy/tests/ui/author/blocks.stdout b/src/tools/clippy/tests/ui/author/blocks.stdout
index 80b928dd6cb..6bf48d5ba4e 100644
--- a/src/tools/clippy/tests/ui/author/blocks.stdout
+++ b/src/tools/clippy/tests/ui/author/blocks.stdout
@@ -1,12 +1,12 @@
 if let ExprKind::Block(block, None) = expr.kind
     && block.stmts.len() == 3
-    && let StmtKind::Local(local) = block.stmts[0].kind
+    && let StmtKind::Let(local) = block.stmts[0].kind
     && let Some(init) = local.init
     && let ExprKind::Lit(ref lit) = init.kind
     && let LitKind::Int(42, LitIntType::Signed(IntTy::I32)) = lit.node
     && let PatKind::Binding(BindingMode::NONE, _, name, None) = local.pat.kind
     && name.as_str() == "x"
-    && let StmtKind::Local(local1) = block.stmts[1].kind
+    && let StmtKind::Let(local1) = block.stmts[1].kind
     && let Some(init1) = local1.init
     && let ExprKind::Lit(ref lit1) = init1.kind
     && let LitKind::Float(_, LitFloatType::Suffixed(FloatTy::F32)) = lit1.node
@@ -22,7 +22,7 @@ if let ExprKind::Block(block, None) = expr.kind
 }
 if let ExprKind::Block(block, None) = expr.kind
     && block.stmts.len() == 1
-    && let StmtKind::Local(local) = block.stmts[0].kind
+    && let StmtKind::Let(local) = block.stmts[0].kind
     && let Some(init) = local.init
     && let ExprKind::Call(func, args) = init.kind
     && let ExprKind::Path(ref qpath) = func.kind
diff --git a/src/tools/clippy/tests/ui/author/call.stdout b/src/tools/clippy/tests/ui/author/call.stdout
index f040f6330a6..59d4da490fe 100644
--- a/src/tools/clippy/tests/ui/author/call.stdout
+++ b/src/tools/clippy/tests/ui/author/call.stdout
@@ -1,4 +1,4 @@
-if let StmtKind::Local(local) = stmt.kind
+if let StmtKind::Let(local) = stmt.kind
     && let Some(init) = local.init
     && let ExprKind::Call(func, args) = init.kind
     && let ExprKind::Path(ref qpath) = func.kind
diff --git a/src/tools/clippy/tests/ui/author/if.stdout b/src/tools/clippy/tests/ui/author/if.stdout
index 5d79618820d..a85dcddd331 100644
--- a/src/tools/clippy/tests/ui/author/if.stdout
+++ b/src/tools/clippy/tests/ui/author/if.stdout
@@ -1,4 +1,4 @@
-if let StmtKind::Local(local) = stmt.kind
+if let StmtKind::Let(local) = stmt.kind
     && let Some(init) = local.init
     && let ExprKind::If(cond, then, Some(else_expr)) = init.kind
     && let ExprKind::DropTemps(expr) = cond.kind
diff --git a/src/tools/clippy/tests/ui/author/issue_3849.stdout b/src/tools/clippy/tests/ui/author/issue_3849.stdout
index 32a3127b85a..a5a8c0304ee 100644
--- a/src/tools/clippy/tests/ui/author/issue_3849.stdout
+++ b/src/tools/clippy/tests/ui/author/issue_3849.stdout
@@ -1,4 +1,4 @@
-if let StmtKind::Local(local) = stmt.kind
+if let StmtKind::Let(local) = stmt.kind
     && let Some(init) = local.init
     && let ExprKind::Call(func, args) = init.kind
     && let ExprKind::Path(ref qpath) = func.kind
diff --git a/src/tools/clippy/tests/ui/author/loop.stdout b/src/tools/clippy/tests/ui/author/loop.stdout
index 631105a2238..609d2491061 100644
--- a/src/tools/clippy/tests/ui/author/loop.stdout
+++ b/src/tools/clippy/tests/ui/author/loop.stdout
@@ -12,7 +12,7 @@ if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::Fo
     && let LitKind::Int(10, LitIntType::Unsuffixed) = lit1.node
     && let ExprKind::Block(block, None) = body.kind
     && block.stmts.len() == 1
-    && let StmtKind::Local(local) = block.stmts[0].kind
+    && let StmtKind::Let(local) = block.stmts[0].kind
     && let Some(init) = local.init
     && let ExprKind::Path(ref qpath1) = init.kind
     && match_qpath(qpath1, &["y"])
diff --git a/src/tools/clippy/tests/ui/author/macro_in_closure.stdout b/src/tools/clippy/tests/ui/author/macro_in_closure.stdout
index b90c830e030..66caf382d89 100644
--- a/src/tools/clippy/tests/ui/author/macro_in_closure.stdout
+++ b/src/tools/clippy/tests/ui/author/macro_in_closure.stdout
@@ -1,4 +1,4 @@
-if let StmtKind::Local(local) = stmt.kind
+if let StmtKind::Let(local) = stmt.kind
     && let Some(init) = local.init
     && let ExprKind::Closure { capture_clause: CaptureBy::Ref, fn_decl: fn_decl, body: body_id, closure_kind: ClosureKind::Closure, .. } = init.kind
     && let FnRetTy::DefaultReturn(_) = fn_decl.output
diff --git a/src/tools/clippy/tests/ui/author/matches.stdout b/src/tools/clippy/tests/ui/author/matches.stdout
index 30e4a9b2560..91b3b6f6877 100644
--- a/src/tools/clippy/tests/ui/author/matches.stdout
+++ b/src/tools/clippy/tests/ui/author/matches.stdout
@@ -1,4 +1,4 @@
-if let StmtKind::Local(local) = stmt.kind
+if let StmtKind::Let(local) = stmt.kind
     && let Some(init) = local.init
     && let ExprKind::Match(scrutinee, arms, MatchSource::Normal) = init.kind
     && let ExprKind::Lit(ref lit) = scrutinee.kind
@@ -16,7 +16,7 @@ if let StmtKind::Local(local) = stmt.kind
     && arms[1].guard.is_none()
     && let ExprKind::Block(block, None) = arms[1].body.kind
     && block.stmts.len() == 1
-    && let StmtKind::Local(local1) = block.stmts[0].kind
+    && let StmtKind::Let(local1) = block.stmts[0].kind
     && let Some(init1) = local1.init
     && let ExprKind::Lit(ref lit4) = init1.kind
     && let LitKind::Int(3, LitIntType::Unsuffixed) = lit4.node
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
index 79a95d775b1..4c3df472269 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
@@ -169,3 +169,16 @@ pub fn derive_ignored_unit_pattern(_: TokenStream) -> TokenStream {
         }
     }
 }
+
+#[proc_macro_derive(NonCanonicalClone)]
+pub fn non_canonical_clone_derive(_: TokenStream) -> TokenStream {
+    quote! {
+        struct NonCanonicalClone;
+        impl Clone for NonCanonicalClone {
+            fn clone(&self) -> Self {
+                todo!()
+            }
+        }
+        impl Copy for NonCanonicalClone {}
+    }
+}
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
index 6e6919cd295..ed7412f7c40 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
@@ -58,7 +58,7 @@ fn group_with_span(delimiter: Delimiter, stream: TokenStream, span: Span) -> Gro
 const ESCAPE_CHAR: char = '$';
 
 /// Takes a single token followed by a sequence of tokens. Returns the sequence of tokens with their
-/// span set to that of the first token. Tokens may be escaped with either `#ident` or `#(tokens)`.
+/// span set to that of the first token. Tokens may be escaped with either `$ident` or `$(tokens)`.
 #[proc_macro]
 pub fn with_span(input: TokenStream) -> TokenStream {
     let mut iter = input.into_iter();
@@ -72,7 +72,7 @@ pub fn with_span(input: TokenStream) -> TokenStream {
 }
 
 /// Takes a sequence of tokens and return the tokens with the span set such that they appear to be
-/// from an external macro. Tokens may be escaped with either `#ident` or `#(tokens)`.
+/// from an external macro. Tokens may be escaped with either `$ident` or `$(tokens)`.
 #[proc_macro]
 pub fn external(input: TokenStream) -> TokenStream {
     let mut res = TokenStream::new();
@@ -84,7 +84,7 @@ pub fn external(input: TokenStream) -> TokenStream {
 }
 
 /// Copies all the tokens, replacing all their spans with the given span. Tokens can be escaped
-/// either by `#ident` or `#(tokens)`.
+/// either by `$ident` or `$(tokens)`.
 fn write_with_span(s: Span, mut input: IntoIter, out: &mut TokenStream) -> Result<()> {
     while let Some(tt) = input.next() {
         match tt {
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.fixed b/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
index a2da5f9c5fb..af8e65270d0 100644
--- a/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
@@ -117,4 +117,17 @@ mod issue_12016 {
     }
 }
 
+fn in_closure() {
+    let v = vec![1, 2, 3];
+    if v.into_iter()
+        .filter(|x| {
+            let y = x + 1;
+            y > 3
+        })
+        .any(|x| x == 5)
+    {
+        println!("contains 4!");
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.rs b/src/tools/clippy/tests/ui/blocks_in_conditions.rs
index 608ca4cf267..6adae951a29 100644
--- a/src/tools/clippy/tests/ui/blocks_in_conditions.rs
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions.rs
@@ -117,4 +117,17 @@ mod issue_12016 {
     }
 }
 
+fn in_closure() {
+    let v = vec![1, 2, 3];
+    if v.into_iter()
+        .filter(|x| {
+            let y = x + 1;
+            y > 3
+        })
+        .any(|x| x == 5)
+    {
+        println!("contains 4!");
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions_closure.rs b/src/tools/clippy/tests/ui/blocks_in_conditions_closure.rs
deleted file mode 100644
index db31e4ae1a9..00000000000
--- a/src/tools/clippy/tests/ui/blocks_in_conditions_closure.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-#![warn(clippy::blocks_in_conditions)]
-#![allow(
-    unused,
-    clippy::let_and_return,
-    clippy::needless_if,
-    clippy::unnecessary_literal_unwrap
-)]
-
-fn predicate<F: FnOnce(T) -> bool, T>(pfn: F, val: T) -> bool {
-    pfn(val)
-}
-
-fn pred_test() {
-    let v = 3;
-    let sky = "blue";
-    // This is a sneaky case, where the block isn't directly in the condition,
-    // but is actually inside a closure that the condition is using.
-    // The same principle applies -- add some extra expressions to make sure
-    // linter isn't confused by them.
-    if v == 3
-        && sky == "blue"
-        && predicate(
-            |x| {
-                //~^ ERROR: in an `if` condition, avoid complex blocks or closures with blocks
-                //~| NOTE: `-D clippy::blocks-in-conditions` implied by `-D warnings`
-                let target = 3;
-                x == target
-            },
-            v,
-        )
-    {}
-
-    if predicate(
-        |x| {
-            //~^ ERROR: in an `if` condition, avoid complex blocks or closures with blocks; in
-            let target = 3;
-            x == target
-        },
-        v,
-    ) {}
-}
-
-fn closure_without_block() {
-    if predicate(|x| x == 3, 6) {}
-}
-
-fn macro_in_closure() {
-    let option = Some(true);
-
-    if option.unwrap_or_else(|| unimplemented!()) {
-        unimplemented!()
-    }
-}
-
-fn closure(_: impl FnMut()) -> bool {
-    true
-}
-
-fn function_with_empty_closure() {
-    if closure(|| {}) {}
-}
-
-// issue #11814
-fn match_with_pred() {
-    let v = 3;
-    match Some(predicate(
-        |x| {
-            //~^ ERROR: in a `match` scrutinee, avoid complex blocks or closures with blocks
-            let target = 3;
-            x == target
-        },
-        v,
-    )) {
-        Some(true) => 1,
-        Some(false) => 2,
-        None => 3,
-    };
-}
-
-#[rustfmt::skip]
-fn main() {
-    let mut range = 0..10;
-    range.all(|i| {i < 10} );
-
-    let v = vec![1, 2, 3];
-    if v.into_iter().any(|x| {x == 4}) {
-        println!("contains 4!");
-    }
-}
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions_closure.stderr b/src/tools/clippy/tests/ui/blocks_in_conditions_closure.stderr
deleted file mode 100644
index 2faae680ec0..00000000000
--- a/src/tools/clippy/tests/ui/blocks_in_conditions_closure.stderr
+++ /dev/null
@@ -1,39 +0,0 @@
-error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
-  --> tests/ui/blocks_in_conditions_closure.rs:23:17
-   |
-LL |               |x| {
-   |  _________________^
-LL | |
-LL | |
-LL | |                 let target = 3;
-LL | |                 x == target
-LL | |             },
-   | |_____________^
-   |
-   = note: `-D clippy::blocks-in-conditions` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::blocks_in_conditions)]`
-
-error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
-  --> tests/ui/blocks_in_conditions_closure.rs:34:13
-   |
-LL |           |x| {
-   |  _____________^
-LL | |
-LL | |             let target = 3;
-LL | |             x == target
-LL | |         },
-   | |_________^
-
-error: in a `match` scrutinee, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
-  --> tests/ui/blocks_in_conditions_closure.rs:67:13
-   |
-LL |           |x| {
-   |  _____________^
-LL | |
-LL | |             let target = 3;
-LL | |             x == target
-LL | |         },
-   | |_________^
-
-error: aborting due to 3 previous errors
-
diff --git a/src/tools/clippy/tests/ui/cfg_features.fixed b/src/tools/clippy/tests/ui/cfg_features.fixed
deleted file mode 100644
index 0fe38f169f9..00000000000
--- a/src/tools/clippy/tests/ui/cfg_features.fixed
+++ /dev/null
@@ -1,29 +0,0 @@
-#![warn(clippy::maybe_misused_cfg)]
-
-fn main() {
-    #[cfg(feature = "not-really-a-feature")]
-    //~^ ERROR: 'feature' may be misspelled as 'features'
-    //~| NOTE: `-D clippy::maybe-misused-cfg` implied by `-D warnings`
-    let _ = 1 + 2;
-
-    #[cfg(all(feature = "right", feature = "wrong"))]
-    //~^ ERROR: 'feature' may be misspelled as 'features'
-    let _ = 1 + 2;
-
-    #[cfg(all(feature = "wrong1", any(feature = "right", feature = "wrong2", feature, features)))]
-    //~^ ERROR: 'feature' may be misspelled as 'features'
-    //~| ERROR: 'feature' may be misspelled as 'features'
-    let _ = 1 + 2;
-
-    #[cfg(test)]
-    //~^ ERROR: 'test' may be misspelled as 'tests'
-    let _ = 2;
-    #[cfg(test)]
-    //~^ ERROR: 'test' may be misspelled as 'Test'
-    let _ = 2;
-
-    #[cfg(all(test, test))]
-    //~^ ERROR: 'test' may be misspelled as 'tests'
-    //~| ERROR: 'test' may be misspelled as 'Test'
-    let _ = 2;
-}
diff --git a/src/tools/clippy/tests/ui/cfg_features.rs b/src/tools/clippy/tests/ui/cfg_features.rs
deleted file mode 100644
index 9c0db035eac..00000000000
--- a/src/tools/clippy/tests/ui/cfg_features.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-#![warn(clippy::maybe_misused_cfg)]
-
-fn main() {
-    #[cfg(features = "not-really-a-feature")]
-    //~^ ERROR: 'feature' may be misspelled as 'features'
-    //~| NOTE: `-D clippy::maybe-misused-cfg` implied by `-D warnings`
-    let _ = 1 + 2;
-
-    #[cfg(all(feature = "right", features = "wrong"))]
-    //~^ ERROR: 'feature' may be misspelled as 'features'
-    let _ = 1 + 2;
-
-    #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))]
-    //~^ ERROR: 'feature' may be misspelled as 'features'
-    //~| ERROR: 'feature' may be misspelled as 'features'
-    let _ = 1 + 2;
-
-    #[cfg(tests)]
-    //~^ ERROR: 'test' may be misspelled as 'tests'
-    let _ = 2;
-    #[cfg(Test)]
-    //~^ ERROR: 'test' may be misspelled as 'Test'
-    let _ = 2;
-
-    #[cfg(all(tests, Test))]
-    //~^ ERROR: 'test' may be misspelled as 'tests'
-    //~| ERROR: 'test' may be misspelled as 'Test'
-    let _ = 2;
-}
diff --git a/src/tools/clippy/tests/ui/cfg_features.stderr b/src/tools/clippy/tests/ui/cfg_features.stderr
deleted file mode 100644
index d576271f1a2..00000000000
--- a/src/tools/clippy/tests/ui/cfg_features.stderr
+++ /dev/null
@@ -1,53 +0,0 @@
-error: 'feature' may be misspelled as 'features'
-  --> tests/ui/cfg_features.rs:4:11
-   |
-LL |     #[cfg(features = "not-really-a-feature")]
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `feature = "not-really-a-feature"`
-   |
-   = note: `-D clippy::maybe-misused-cfg` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::maybe_misused_cfg)]`
-
-error: 'feature' may be misspelled as 'features'
-  --> tests/ui/cfg_features.rs:9:34
-   |
-LL |     #[cfg(all(feature = "right", features = "wrong"))]
-   |                                  ^^^^^^^^^^^^^^^^^^ help: did you mean: `feature = "wrong"`
-
-error: 'feature' may be misspelled as 'features'
-  --> tests/ui/cfg_features.rs:13:15
-   |
-LL |     #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))]
-   |               ^^^^^^^^^^^^^^^^^^^ help: did you mean: `feature = "wrong1"`
-
-error: 'feature' may be misspelled as 'features'
-  --> tests/ui/cfg_features.rs:13:59
-   |
-LL |     #[cfg(all(features = "wrong1", any(feature = "right", features = "wrong2", feature, features)))]
-   |                                                           ^^^^^^^^^^^^^^^^^^^ help: did you mean: `feature = "wrong2"`
-
-error: 'test' may be misspelled as 'tests'
-  --> tests/ui/cfg_features.rs:18:11
-   |
-LL |     #[cfg(tests)]
-   |           ^^^^^ help: did you mean: `test`
-
-error: 'test' may be misspelled as 'Test'
-  --> tests/ui/cfg_features.rs:21:11
-   |
-LL |     #[cfg(Test)]
-   |           ^^^^ help: did you mean: `test`
-
-error: 'test' may be misspelled as 'tests'
-  --> tests/ui/cfg_features.rs:25:15
-   |
-LL |     #[cfg(all(tests, Test))]
-   |               ^^^^^ help: did you mean: `test`
-
-error: 'test' may be misspelled as 'Test'
-  --> tests/ui/cfg_features.rs:25:22
-   |
-LL |     #[cfg(all(tests, Test))]
-   |                      ^^^^ help: did you mean: `test`
-
-error: aborting due to 8 previous errors
-
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
index ce3b9495eb1..cd2031af1c6 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
@@ -4,9 +4,7 @@ error[E0412]: cannot find type `PhantomData` in this scope
 LL |     _n: PhantomData,
    |         ^^^^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
-   |
-LL + use core::marker::PhantomData;
+help: consider importing this struct
    |
 LL + use std::marker::PhantomData;
    |
diff --git a/src/tools/clippy/tests/ui/crashes/ice-9445.rs b/src/tools/clippy/tests/ui/crashes/ice-9445.rs
index b6afbd33c79..c67b22f6f8c 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-9445.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-9445.rs
@@ -1,5 +1,3 @@
 const UNINIT: core::mem::MaybeUninit<core::cell::Cell<&'static ()>> = core::mem::MaybeUninit::uninit();
-//~^ ERROR: a `const` item should never be interior mutable
-//~| NOTE: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-9445.stderr b/src/tools/clippy/tests/ui/crashes/ice-9445.stderr
index d6957e9549d..76689cd6f5c 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-9445.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-9445.stderr
@@ -1,11 +1,10 @@
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/crashes/ice-9445.rs:1:1
    |
 LL | const UNINIT: core::mem::MaybeUninit<core::cell::Cell<&'static ()>> = core::mem::MaybeUninit::uninit();
-   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | make this a static item (maybe with lazy_static)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
    = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]`
 
diff --git a/src/tools/clippy/tests/ui/crashes/mut_mut_macro.rs b/src/tools/clippy/tests/ui/crashes/mut_mut_macro.rs
deleted file mode 100644
index 92821b6ecbb..00000000000
--- a/src/tools/clippy/tests/ui/crashes/mut_mut_macro.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-#![deny(clippy::mut_mut, clippy::zero_ptr)]
-#![allow(dead_code)]
-
-// FIXME: compiletest + extern crates doesn't work together. To make this test work, it would need
-// the following three lines and the lazy_static crate.
-//
-//     #[macro_use]
-//     extern crate lazy_static;
-//     use std::collections::HashMap;
-
-/// ensure that we don't suggest `is_null` inside constants
-/// FIXME: once const fn is stable, suggest these functions again in constants
-
-const BAA: *const i32 = 0 as *const i32;
-static mut BAR: *const i32 = BAA;
-static mut FOO: *const i32 = 0 as *const i32;
-
-#[allow(unused_variables, unused_mut)]
-fn main() {
-    /*
-    lazy_static! {
-        static ref MUT_MAP : HashMap<usize, &'static str> = {
-            let mut m = HashMap::new();
-            m.insert(0, "zero");
-            m
-        };
-        static ref MUT_COUNT : usize = MUT_MAP.len();
-    }
-    assert_eq!(*MUT_COUNT, 1);
-    */
-    // FIXME: don't lint in array length, requires `check_body`
-    //let _ = [""; (42.0 < f32::NAN) as usize];
-}
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.stderr b/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.stderr
index 6c0dce6b5ea..22329172c3a 100644
--- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.stderr
+++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/enums.stderr
@@ -1,87 +1,84 @@
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/enums.rs:12:1
    |
 LL | const UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(true));
-   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | make this a static item (maybe with lazy_static)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
    = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]`
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/enums.rs:23:1
    |
 LL | const UNFROZEN_VARIANT_FROM_FN: OptionalCell = unfrozen_variant();
-   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | make this a static item (maybe with lazy_static)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/enums.rs:45:1
    |
-LL |   const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost {
-   |   ^----
-   |   |
-   |  _make this a static item (maybe with lazy_static)
-   | |
+LL | / const NESTED_UNFROZEN_VARIANT: NestedOutermost = NestedOutermost {
 LL | |
 LL | |     outer: NestedOuter::NestedInner(NestedInner {
 LL | |         inner: NestedInnermost::Unfrozen(AtomicUsize::new(2)),
 LL | |     }),
 LL | | };
    | |__^
+   |
+   = help: consider making this a static item
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/enums.rs:60:5
    |
 LL |     const TO_BE_UNFROZEN_VARIANT: OptionalCell;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/enums.rs:61:5
    |
 LL |     const TO_BE_FROZEN_VARIANT: OptionalCell;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/enums.rs:64:5
    |
 LL |     const DEFAULTED_ON_UNFROZEN_VARIANT: OptionalCell = OptionalCell::Unfrozen(Cell::new(false));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/enums.rs:90:5
    |
 LL |     const TO_BE_UNFROZEN_VARIANT: Option<Self::ToBeUnfrozen> = Some(Self::ToBeUnfrozen::new(4));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/enums.rs:102:5
    |
 LL |     const UNFROZEN_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/enums.rs:105:5
    |
 LL |     const GENERIC_VARIANT: BothOfCellAndGeneric<T> = BothOfCellAndGeneric::Generic(std::ptr::null());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/enums.rs:111:5
    |
 LL |     const NO_ENUM: Cell<*const T> = Cell::new(std::ptr::null());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/enums.rs:118:5
    |
 LL | /     const UNFROZEN_VARIANT: BothOfCellAndGeneric<Self::AssocType> =
 LL | |         BothOfCellAndGeneric::Unfrozen(Cell::new(std::ptr::null()));
    | |____________________________________________________________________^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/enums.rs:120:5
    |
 LL |     const GENERIC_VARIANT: BothOfCellAndGeneric<Self::AssocType> = BothOfCellAndGeneric::Generic(std::ptr::null());
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr
index 9dba0c95221..1f2b9561ce5 100644
--- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr
+++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr
@@ -1,31 +1,30 @@
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/others.rs:9:1
    |
 LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5);
-   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | make this a static item (maybe with lazy_static)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = help: consider making this a static item
    = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]`
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/others.rs:10:1
    |
 LL | const CELL: Cell<usize> = Cell::new(6);
-   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | make this a static item (maybe with lazy_static)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider making this `Sync` so that it can go in a static item or using a `thread_local`
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/others.rs:11:1
    |
 LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
-   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | make this a static item (maybe with lazy_static)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider making this a static item
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/others.rs:16:9
    |
 LL |         const $name: $ty = $e;
@@ -36,7 +35,7 @@ LL | declare_const!(_ONCE: Once = Once::new());
    |
    = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/others.rs:44:13
    |
 LL |             const _BAZ: Cell<usize> = Cell::new(0);
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr
index 1d1e9e2002f..4a793d985e5 100644
--- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr
+++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.stderr
@@ -1,4 +1,4 @@
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/traits.rs:16:5
    |
 LL |     const ATOMIC: AtomicUsize;
@@ -7,7 +7,7 @@ LL |     const ATOMIC: AtomicUsize;
    = note: `-D clippy::declare-interior-mutable-const` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]`
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/traits.rs:9:9
    |
 LL |         const $name: $ty = $e;
@@ -18,67 +18,67 @@ LL |     declare_const!(ANOTHER_ATOMIC: AtomicUsize = Self::ATOMIC);
    |
    = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/traits.rs:44:5
    |
 LL |     const TO_BE_CONCRETE: AtomicUsize = AtomicUsize::new(11);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/traits.rs:69:5
    |
 LL |     const TO_BE_UNFROZEN: Self::ToBeUnfrozen = AtomicUsize::new(13);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/traits.rs:70:5
    |
 LL |     const WRAPPED_TO_BE_UNFROZEN: Wrapper<Self::ToBeUnfrozen> = Wrapper(AtomicUsize::new(14));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/traits.rs:89:5
    |
 LL |     const BOUNDED: T::ToBeBounded;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/traits.rs:117:5
    |
 LL |     const SELF: Self = AtomicUsize::new(17);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/traits.rs:118:5
    |
 LL |     const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/traits.rs:124:5
    |
 LL |     const DIRECT: Cell<T>;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/traits.rs:125:5
    |
 LL |     const INDIRECT: Cell<*const T>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/traits.rs:129:5
    |
 LL |     const DIRECT: Cell<T> = Cell::new(T::DEFAULT);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/traits.rs:141:5
    |
 LL |     const ATOMIC: AtomicUsize = AtomicUsize::new(18);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: a `const` item should never be interior mutable
+error: a `const` item should not be interior mutable
   --> tests/ui/declare_interior_mutable_const/traits.rs:147:5
    |
 LL |     const BOUNDED_ASSOC_TYPE: T::ToBeBounded = AtomicUsize::new(19);
diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs
index 07270bd7636..d3c34fb3716 100644
--- a/src/tools/clippy/tests/ui/deprecated.rs
+++ b/src/tools/clippy/tests/ui/deprecated.rs
@@ -18,5 +18,7 @@
 #![warn(clippy::filter_map)]
 #![warn(clippy::pub_enum_variant_names)]
 #![warn(clippy::wrong_pub_self_convention)]
+#![warn(clippy::maybe_misused_cfg)]
+#![warn(clippy::mismatched_target_os)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr
index a9cf04bea52..49b90c70c06 100644
--- a/src/tools/clippy/tests/ui/deprecated.stderr
+++ b/src/tools/clippy/tests/ui/deprecated.stderr
@@ -97,5 +97,17 @@ error: lint `clippy::wrong_pub_self_convention` has been removed: set the `avoid
 LL | #![warn(clippy::wrong_pub_self_convention)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 16 previous errors
+error: lint `clippy::maybe_misused_cfg` has been removed: this lint has been replaced by `unexpected_cfgs`
+  --> tests/ui/deprecated.rs:21:9
+   |
+LL | #![warn(clippy::maybe_misused_cfg)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: lint `clippy::mismatched_target_os` has been removed: this lint has been replaced by `unexpected_cfgs`
+  --> tests/ui/deprecated.rs:22:9
+   |
+LL | #![warn(clippy::mismatched_target_os)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/tests/ui/deref_addrof.fixed b/src/tools/clippy/tests/ui/deref_addrof.fixed
index aa1cf19b76f..b6278c6ca8a 100644
--- a/src/tools/clippy/tests/ui/deref_addrof.fixed
+++ b/src/tools/clippy/tests/ui/deref_addrof.fixed
@@ -43,6 +43,10 @@ fn main() {
     let b = *aref;
 
     let _ = unsafe { *core::ptr::addr_of!(a) };
+
+    let _repeat = [0; 64];
+    // do NOT lint for array as sematic differences with/out `*&`.
+    let _arr = *&[0, 1, 2, 3, 4];
 }
 
 #[derive(Copy, Clone)]
diff --git a/src/tools/clippy/tests/ui/deref_addrof.rs b/src/tools/clippy/tests/ui/deref_addrof.rs
index 38796aef390..572b0fdb102 100644
--- a/src/tools/clippy/tests/ui/deref_addrof.rs
+++ b/src/tools/clippy/tests/ui/deref_addrof.rs
@@ -43,6 +43,10 @@ fn main() {
     let b = **&aref;
 
     let _ = unsafe { *core::ptr::addr_of!(a) };
+
+    let _repeat = *&[0; 64];
+    // do NOT lint for array as sematic differences with/out `*&`.
+    let _arr = *&[0, 1, 2, 3, 4];
 }
 
 #[derive(Copy, Clone)]
diff --git a/src/tools/clippy/tests/ui/deref_addrof.stderr b/src/tools/clippy/tests/ui/deref_addrof.stderr
index 5e3cb417aa0..20069f746c8 100644
--- a/src/tools/clippy/tests/ui/deref_addrof.stderr
+++ b/src/tools/clippy/tests/ui/deref_addrof.stderr
@@ -50,7 +50,13 @@ LL |     let b = **&aref;
    |              ^^^^^^ help: try: `aref`
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:53:17
+  --> tests/ui/deref_addrof.rs:47:19
+   |
+LL |     let _repeat = *&[0; 64];
+   |                   ^^^^^^^^^ help: try: `[0; 64]`
+
+error: immediately dereferencing a reference
+  --> tests/ui/deref_addrof.rs:57:17
    |
 LL |         inline!(*& $(@expr self))
    |                 ^^^^^^^^^^^^^^^^ help: try: `$(@expr self)`
@@ -58,12 +64,12 @@ LL |         inline!(*& $(@expr self))
    = note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: immediately dereferencing a reference
-  --> tests/ui/deref_addrof.rs:57:17
+  --> tests/ui/deref_addrof.rs:61:17
    |
 LL |         inline!(*&mut $(@expr self))
    |                 ^^^^^^^^^^^^^^^^^^^ help: try: `$(@expr self)`
    |
    = note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 10 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/doc_unsafe.stderr b/src/tools/clippy/tests/ui/doc_unsafe.stderr
index 4fcbe716951..929afbceb87 100644
--- a/src/tools/clippy/tests/ui/doc_unsafe.stderr
+++ b/src/tools/clippy/tests/ui/doc_unsafe.stderr
@@ -1,4 +1,4 @@
-error: unsafe function's docs miss `# Safety` section
+error: unsafe function's docs are missing a `# Safety` section
   --> tests/ui/doc_unsafe.rs:9:1
    |
 LL | pub unsafe fn destroy_the_planet() {
@@ -7,13 +7,13 @@ LL | pub unsafe fn destroy_the_planet() {
    = note: `-D clippy::missing-safety-doc` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::missing_safety_doc)]`
 
-error: unsafe function's docs miss `# Safety` section
+error: unsafe function's docs are missing a `# Safety` section
   --> tests/ui/doc_unsafe.rs:32:5
    |
 LL |     pub unsafe fn republished() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: unsafe function's docs miss `# Safety` section
+error: unsafe function's docs are missing a `# Safety` section
   --> tests/ui/doc_unsafe.rs:40:5
    |
 LL |     unsafe fn woefully_underdocumented(self);
@@ -25,13 +25,13 @@ error: docs for unsafe trait missing `# Safety` section
 LL | pub unsafe trait UnsafeTrait {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: unsafe function's docs miss `# Safety` section
+error: unsafe function's docs are missing a `# Safety` section
   --> tests/ui/doc_unsafe.rs:76:5
    |
 LL |     pub unsafe fn more_undocumented_unsafe() -> Self {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: unsafe function's docs miss `# Safety` section
+error: unsafe function's docs are missing a `# Safety` section
   --> tests/ui/doc_unsafe.rs:92:9
    |
 LL |         pub unsafe fn whee() {
diff --git a/src/tools/clippy/tests/ui/double_neg.rs b/src/tools/clippy/tests/ui/double_neg.rs
index da82890443e..3be8c628873 100644
--- a/src/tools/clippy/tests/ui/double_neg.rs
+++ b/src/tools/clippy/tests/ui/double_neg.rs
@@ -5,6 +5,6 @@ fn main() {
     -x;
     -(-x);
     --x;
-    //~^ ERROR: `--x` could be misinterpreted as pre-decrement by C programmers, is usuall
+    //~^ ERROR: `--x` could be misinterpreted as pre-decrement by C programmers, is usually
     //~| NOTE: `-D clippy::double-neg` implied by `-D warnings`
 }
diff --git a/src/tools/clippy/tests/ui/eta.fixed b/src/tools/clippy/tests/ui/eta.fixed
index da28ec2e653..7126f279945 100644
--- a/src/tools/clippy/tests/ui/eta.fixed
+++ b/src/tools/clippy/tests/ui/eta.fixed
@@ -471,3 +471,14 @@ mod issue_10854 {
         }
     }
 }
+
+mod issue_12853 {
+    fn f_by_value<F: Fn(u32)>(f: F) {
+        let x = Box::new(|| None.map(&f));
+        x();
+    }
+    fn f_by_ref<F: Fn(u32)>(f: &F) {
+        let x = Box::new(|| None.map(f));
+        x();
+    }
+}
diff --git a/src/tools/clippy/tests/ui/eta.rs b/src/tools/clippy/tests/ui/eta.rs
index f924100f8f4..0787abf5f3e 100644
--- a/src/tools/clippy/tests/ui/eta.rs
+++ b/src/tools/clippy/tests/ui/eta.rs
@@ -471,3 +471,14 @@ mod issue_10854 {
         }
     }
 }
+
+mod issue_12853 {
+    fn f_by_value<F: Fn(u32)>(f: F) {
+        let x = Box::new(|| None.map(|x| f(x)));
+        x();
+    }
+    fn f_by_ref<F: Fn(u32)>(f: &F) {
+        let x = Box::new(|| None.map(|x| f(x)));
+        x();
+    }
+}
diff --git a/src/tools/clippy/tests/ui/eta.stderr b/src/tools/clippy/tests/ui/eta.stderr
index d9a8768a682..c757601042f 100644
--- a/src/tools/clippy/tests/ui/eta.stderr
+++ b/src/tools/clippy/tests/ui/eta.stderr
@@ -190,5 +190,17 @@ error: redundant closure
 LL |                     test.map(|t| t.method())
    |                              ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `crate::issue_10854::d::Test::method`
 
-error: aborting due to 31 previous errors
+error: redundant closure
+  --> tests/ui/eta.rs:477:38
+   |
+LL |         let x = Box::new(|| None.map(|x| f(x)));
+   |                                      ^^^^^^^^ help: replace the closure with the function itself: `&f`
+
+error: redundant closure
+  --> tests/ui/eta.rs:481:38
+   |
+LL |         let x = Box::new(|| None.map(|x| f(x)));
+   |                                      ^^^^^^^^ help: replace the closure with the function itself: `f`
+
+error: aborting due to 33 previous errors
 
diff --git a/src/tools/clippy/tests/ui/floating_point_log.fixed b/src/tools/clippy/tests/ui/floating_point_log.fixed
index 01f0fc5c671..15cc47eef0d 100644
--- a/src/tools/clippy/tests/ui/floating_point_log.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_log.fixed
@@ -55,4 +55,19 @@ fn check_ln1p() {
     let _ = (1.0 + x - 2.0).ln();
 }
 
+fn issue12881() {
+    pub trait MyLog {
+        fn log(&self) -> Self;
+    }
+
+    impl MyLog for f32 {
+        fn log(&self) -> Self {
+            4.
+        }
+    }
+
+    let x = 2.0;
+    x.log();
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/floating_point_log.rs b/src/tools/clippy/tests/ui/floating_point_log.rs
index 197e3e1ff90..1241af82859 100644
--- a/src/tools/clippy/tests/ui/floating_point_log.rs
+++ b/src/tools/clippy/tests/ui/floating_point_log.rs
@@ -55,4 +55,19 @@ fn check_ln1p() {
     let _ = (1.0 + x - 2.0).ln();
 }
 
+fn issue12881() {
+    pub trait MyLog {
+        fn log(&self) -> Self;
+    }
+
+    impl MyLog for f32 {
+        fn log(&self) -> Self {
+            4.
+        }
+    }
+
+    let x = 2.0;
+    x.log();
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/format_args.fixed b/src/tools/clippy/tests/ui/format_args.fixed
index cab20b11e07..4d812f6bf1d 100644
--- a/src/tools/clippy/tests/ui/format_args.fixed
+++ b/src/tools/clippy/tests/ui/format_args.fixed
@@ -104,6 +104,7 @@ fn main() {
     println!("{foo}{bar}", foo = "foo", bar = "bar");
     println!("{foo}{bar}", bar = "bar", foo = "foo");
     println!("{foo}{bar}", bar = "bar", foo = "foo");
+    println!("{}", my_other_macro!());
 
     // negative tests
     println!("error: something failed at {}", Somewhere.to_string());
diff --git a/src/tools/clippy/tests/ui/format_args.rs b/src/tools/clippy/tests/ui/format_args.rs
index bc3645cb2c2..d242623feb6 100644
--- a/src/tools/clippy/tests/ui/format_args.rs
+++ b/src/tools/clippy/tests/ui/format_args.rs
@@ -104,6 +104,7 @@ fn main() {
     println!("{foo}{bar}", foo = "foo", bar = "bar".to_string());
     println!("{foo}{bar}", bar = "bar".to_string(), foo = "foo");
     println!("{foo}{bar}", bar = "bar", foo = "foo".to_string());
+    println!("{}", my_other_macro!().to_string());
 
     // negative tests
     println!("error: something failed at {}", Somewhere.to_string());
diff --git a/src/tools/clippy/tests/ui/format_args.stderr b/src/tools/clippy/tests/ui/format_args.stderr
index f20cf9eca2f..91a45e27008 100644
--- a/src/tools/clippy/tests/ui/format_args.stderr
+++ b/src/tools/clippy/tests/ui/format_args.stderr
@@ -127,29 +127,35 @@ error: `to_string` applied to a type that implements `Display` in `println!` arg
 LL |     println!("{foo}{bar}", bar = "bar", foo = "foo".to_string());
    |                                                    ^^^^^^^^^^^^ help: remove this
 
+error: `to_string` applied to a type that implements `Display` in `println!` args
+  --> tests/ui/format_args.rs:107:37
+   |
+LL |     println!("{}", my_other_macro!().to_string());
+   |                                     ^^^^^^^^^^^^ help: remove this
+
 error: `to_string` applied to a type that implements `Display` in `print!` args
-  --> tests/ui/format_args.rs:118:37
+  --> tests/ui/format_args.rs:119:37
    |
 LL |     print!("{}", (Location::caller().to_string()));
    |                                     ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `print!` args
-  --> tests/ui/format_args.rs:119:39
+  --> tests/ui/format_args.rs:120:39
    |
 LL |     print!("{}", ((Location::caller()).to_string()));
    |                                       ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `format!` args
-  --> tests/ui/format_args.rs:147:38
+  --> tests/ui/format_args.rs:148:38
    |
 LL |         let x = format!("{} {}", a, b.to_string());
    |                                      ^^^^^^^^^^^^ help: remove this
 
 error: `to_string` applied to a type that implements `Display` in `println!` args
-  --> tests/ui/format_args.rs:161:24
+  --> tests/ui/format_args.rs:162:24
    |
 LL |         println!("{}", original[..10].to_string());
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use this: `&original[..10]`
 
-error: aborting due to 25 previous errors
+error: aborting due to 26 previous errors
 
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.rs b/src/tools/clippy/tests/ui/indexing_slicing_index.rs
index 2e726141649..2af5fcc82a9 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_index.rs
+++ b/src/tools/clippy/tests/ui/indexing_slicing_index.rs
@@ -1,4 +1,5 @@
 //@compile-flags: -Zdeduplicate-diagnostics=yes
+//@aux-build: proc_macros.rs
 
 #![warn(clippy::indexing_slicing)]
 // We also check the out_of_bounds_indexing lint here, because it lints similar things and
@@ -11,6 +12,9 @@
     clippy::useless_vec
 )]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
 const ARR: [i32; 2] = [1, 2];
 const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
 //~^ ERROR: indexing may panic
@@ -22,6 +26,22 @@ const fn idx4() -> usize {
     4
 }
 
+with_span!(
+    span
+
+    fn dont_lint_proc_macro_array() {
+        let x = [1, 2, 3, 4];
+        let index: usize = 1;
+        x[index];
+        x[10];
+
+        let x = vec![0; 5];
+        let index: usize = 1;
+        x[index];
+        x[10];
+    }
+);
+
 fn main() {
     let x = [1, 2, 3, 4];
     let index: usize = 1;
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
index 386f91becf1..71677584d25 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
+++ b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
@@ -1,5 +1,5 @@
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:15:20
+  --> tests/ui/indexing_slicing_index.rs:19:20
    |
 LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
    |                    ^^^^^^^^^^
@@ -10,19 +10,19 @@ LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-re
    = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`
 
 error[E0080]: evaluation of `main::{constant#3}` failed
-  --> tests/ui/indexing_slicing_index.rs:47:14
+  --> tests/ui/indexing_slicing_index.rs:67:14
    |
 LL |     const { &ARR[idx4()] };
    |              ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
 
 note: erroneous constant encountered
-  --> tests/ui/indexing_slicing_index.rs:47:5
+  --> tests/ui/indexing_slicing_index.rs:67:5
    |
 LL |     const { &ARR[idx4()] };
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:28:5
+  --> tests/ui/indexing_slicing_index.rs:48:5
    |
 LL |     x[index];
    |     ^^^^^^^^
@@ -30,7 +30,7 @@ LL |     x[index];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:31:5
+  --> tests/ui/indexing_slicing_index.rs:51:5
    |
 LL |     x[4];
    |     ^^^^
@@ -39,13 +39,13 @@ LL |     x[4];
    = help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]`
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:33:5
+  --> tests/ui/indexing_slicing_index.rs:53:5
    |
 LL |     x[1 << 3];
    |     ^^^^^^^^^
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:44:14
+  --> tests/ui/indexing_slicing_index.rs:64:14
    |
 LL |     const { &ARR[idx()] };
    |              ^^^^^^^^^^
@@ -54,7 +54,7 @@ LL |     const { &ARR[idx()] };
    = note: the suggestion might not be applicable in constant blocks
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:47:14
+  --> tests/ui/indexing_slicing_index.rs:67:14
    |
 LL |     const { &ARR[idx4()] };
    |              ^^^^^^^^^^^
@@ -63,13 +63,13 @@ LL |     const { &ARR[idx4()] };
    = note: the suggestion might not be applicable in constant blocks
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:54:5
+  --> tests/ui/indexing_slicing_index.rs:74:5
    |
 LL |     y[4];
    |     ^^^^
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:57:5
+  --> tests/ui/indexing_slicing_index.rs:77:5
    |
 LL |     v[0];
    |     ^^^^
@@ -77,7 +77,7 @@ LL |     v[0];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:59:5
+  --> tests/ui/indexing_slicing_index.rs:79:5
    |
 LL |     v[10];
    |     ^^^^^
@@ -85,7 +85,7 @@ LL |     v[10];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:61:5
+  --> tests/ui/indexing_slicing_index.rs:81:5
    |
 LL |     v[1 << 3];
    |     ^^^^^^^^^
@@ -93,13 +93,13 @@ LL |     v[1 << 3];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:69:5
+  --> tests/ui/indexing_slicing_index.rs:89:5
    |
 LL |     x[N];
    |     ^^^^
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:72:5
+  --> tests/ui/indexing_slicing_index.rs:92:5
    |
 LL |     v[N];
    |     ^^^^
@@ -107,7 +107,7 @@ LL |     v[N];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:74:5
+  --> tests/ui/indexing_slicing_index.rs:94:5
    |
 LL |     v[M];
    |     ^^^^
@@ -115,7 +115,7 @@ LL |     v[M];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:78:13
+  --> tests/ui/indexing_slicing_index.rs:98:13
    |
 LL |     let _ = x[4];
    |             ^^^^
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_slice.rs b/src/tools/clippy/tests/ui/indexing_slicing_slice.rs
index fc591021ed6..f37bcc4aa0c 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_slice.rs
+++ b/src/tools/clippy/tests/ui/indexing_slicing_slice.rs
@@ -1,8 +1,111 @@
+//@aux-build: proc_macros.rs
+
 #![warn(clippy::indexing_slicing)]
 // We also check the out_of_bounds_indexing lint here, because it lints similar things and
 // we want to avoid false positives.
 #![warn(clippy::out_of_bounds_indexing)]
-#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::useless_vec)]
+#![allow(
+    clippy::no_effect,
+    clippy::unnecessary_operation,
+    clippy::useless_vec,
+    unused_must_use,
+    unused
+)]
+#![warn(clippy::indexing_slicing)]
+
+extern crate proc_macros;
+use proc_macros::with_span;
+
+use std::ops::Index;
+
+struct BoolMap<T> {
+    false_value: T,
+    true_value: T,
+}
+
+impl<T> Index<bool> for BoolMap<T> {
+    type Output = T;
+    fn index(&self, index: bool) -> &T {
+        if index { &self.true_value } else { &self.false_value }
+    }
+}
+
+struct BoolMapWithGet<T> {
+    false_value: T,
+    true_value: T,
+}
+
+impl<T> Index<bool> for BoolMapWithGet<T> {
+    type Output = T;
+    fn index(&self, index: bool) -> &Self::Output {
+        if index { &self.true_value } else { &self.false_value }
+    }
+}
+
+impl<T> BoolMapWithGet<T> {
+    fn get(&self, index: bool) -> Option<&T> {
+        if index {
+            Some(&self.true_value)
+        } else {
+            Some(&self.false_value)
+        }
+    }
+}
+
+struct S<T>(T);
+impl S<i32> {
+    fn get() -> Option<i32> {
+        unimplemented!()
+    }
+}
+impl<T> Index<i32> for S<T> {
+    type Output = T;
+    fn index(&self, _index: i32) -> &Self::Output {
+        &self.0
+    }
+}
+
+struct Y<T>(T);
+impl Y<i32> {
+    fn get<U>() -> Option<U> {
+        unimplemented!()
+    }
+}
+impl<T> Index<i32> for Y<T> {
+    type Output = T;
+    fn index(&self, _index: i32) -> &Self::Output {
+        &self.0
+    }
+}
+
+struct Z<T>(T);
+impl<T> Z<T> {
+    fn get<T2>() -> T2 {
+        unimplemented!()
+    }
+}
+impl<T> Index<i32> for Z<T> {
+    type Output = T;
+    fn index(&self, _index: i32) -> &Self::Output {
+        &self.0
+    }
+}
+
+with_span!(
+    span
+
+    fn dont_lint_proc_macro() {
+        let x = [1, 2, 3, 4];
+        let index: usize = 1;
+        &x[index..];
+        &x[..10];
+
+        let x = vec![0; 5];
+        let index: usize = 1;
+        &x[index..];
+        &x[..10];
+    }
+);
 
 fn main() {
     let x = [1, 2, 3, 4];
@@ -51,4 +154,28 @@ fn main() {
     //~^ ERROR: slicing may panic
 
     &v[..]; // Ok, should not produce stderr.
+
+    let map = BoolMap {
+        false_value: 2,
+        true_value: 4,
+    };
+
+    map[true]; // Ok, because `get` does not exist (custom indexing)
+
+    let map_with_get = BoolMapWithGet {
+        false_value: 2,
+        true_value: 4,
+    };
+
+    // Lint on this, because `get` does exist with same signature
+    map_with_get[true];
+
+    let s = S::<i32>(1);
+    s[0];
+
+    let y = Y::<i32>(1);
+    y[0];
+
+    let z = Z::<i32>(1);
+    z[0];
 }
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_slice.stderr b/src/tools/clippy/tests/ui/indexing_slicing_slice.stderr
index 790d4a41f5b..1e72506746e 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_slice.stderr
+++ b/src/tools/clippy/tests/ui/indexing_slicing_slice.stderr
@@ -1,5 +1,5 @@
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:12:6
+  --> tests/ui/indexing_slicing_slice.rs:115:6
    |
 LL |     &x[index..];
    |      ^^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     &x[index..];
    = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:14:6
+  --> tests/ui/indexing_slicing_slice.rs:117:6
    |
 LL |     &x[..index];
    |      ^^^^^^^^^^
@@ -17,7 +17,7 @@ LL |     &x[..index];
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:16:6
+  --> tests/ui/indexing_slicing_slice.rs:119:6
    |
 LL |     &x[index_from..index_to];
    |      ^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@ LL |     &x[index_from..index_to];
    = help: consider using `.get(n..m)` or `.get_mut(n..m)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:18:6
+  --> tests/ui/indexing_slicing_slice.rs:121:6
    |
 LL |     &x[index_from..][..index_to];
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     &x[index_from..][..index_to];
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:18:6
+  --> tests/ui/indexing_slicing_slice.rs:121:6
    |
 LL |     &x[index_from..][..index_to];
    |      ^^^^^^^^^^^^^^^
@@ -41,7 +41,7 @@ LL |     &x[index_from..][..index_to];
    = help: consider using `.get(n..)` or .get_mut(n..)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:21:6
+  --> tests/ui/indexing_slicing_slice.rs:124:6
    |
 LL |     &x[5..][..10];
    |      ^^^^^^^^^^^^
@@ -49,7 +49,7 @@ LL |     &x[5..][..10];
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
 error: range is out of bounds
-  --> tests/ui/indexing_slicing_slice.rs:21:8
+  --> tests/ui/indexing_slicing_slice.rs:124:8
    |
 LL |     &x[5..][..10];
    |        ^
@@ -58,7 +58,7 @@ LL |     &x[5..][..10];
    = help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]`
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:25:6
+  --> tests/ui/indexing_slicing_slice.rs:128:6
    |
 LL |     &x[0..][..3];
    |      ^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL |     &x[0..][..3];
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:27:6
+  --> tests/ui/indexing_slicing_slice.rs:130:6
    |
 LL |     &x[1..][..5];
    |      ^^^^^^^^^^^
@@ -74,19 +74,19 @@ LL |     &x[1..][..5];
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
 error: range is out of bounds
-  --> tests/ui/indexing_slicing_slice.rs:35:12
+  --> tests/ui/indexing_slicing_slice.rs:138:12
    |
 LL |     &y[0..=4];
    |            ^
 
 error: range is out of bounds
-  --> tests/ui/indexing_slicing_slice.rs:37:11
+  --> tests/ui/indexing_slicing_slice.rs:140:11
    |
 LL |     &y[..=4];
    |           ^
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:43:6
+  --> tests/ui/indexing_slicing_slice.rs:146:6
    |
 LL |     &v[10..100];
    |      ^^^^^^^^^^
@@ -94,7 +94,7 @@ LL |     &v[10..100];
    = help: consider using `.get(n..m)` or `.get_mut(n..m)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:45:6
+  --> tests/ui/indexing_slicing_slice.rs:148:6
    |
 LL |     &x[10..][..100];
    |      ^^^^^^^^^^^^^^
@@ -102,13 +102,13 @@ LL |     &x[10..][..100];
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
 error: range is out of bounds
-  --> tests/ui/indexing_slicing_slice.rs:45:8
+  --> tests/ui/indexing_slicing_slice.rs:148:8
    |
 LL |     &x[10..][..100];
    |        ^^
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:48:6
+  --> tests/ui/indexing_slicing_slice.rs:151:6
    |
 LL |     &v[10..];
    |      ^^^^^^^
@@ -116,12 +116,36 @@ LL |     &v[10..];
    = help: consider using `.get(n..)` or .get_mut(n..)` instead
 
 error: slicing may panic
-  --> tests/ui/indexing_slicing_slice.rs:50:6
+  --> tests/ui/indexing_slicing_slice.rs:153:6
    |
 LL |     &v[..100];
    |      ^^^^^^^^
    |
    = help: consider using `.get(..n)`or `.get_mut(..n)` instead
 
-error: aborting due to 16 previous errors
+error: indexing may panic
+  --> tests/ui/indexing_slicing_slice.rs:171:5
+   |
+LL |     map_with_get[true];
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+  --> tests/ui/indexing_slicing_slice.rs:174:5
+   |
+LL |     s[0];
+   |     ^^^^
+   |
+   = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+  --> tests/ui/indexing_slicing_slice.rs:177:5
+   |
+LL |     y[0];
+   |     ^^^^
+   |
+   = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: aborting due to 19 previous errors
 
diff --git a/src/tools/clippy/tests/ui/infinite_loops.rs b/src/tools/clippy/tests/ui/infinite_loops.rs
index 52fbbaa8e31..b2d522fa011 100644
--- a/src/tools/clippy/tests/ui/infinite_loops.rs
+++ b/src/tools/clippy/tests/ui/infinite_loops.rs
@@ -137,7 +137,7 @@ fn can_break_both_inner_and_outer(cond: bool) {
 }
 
 fn break_wrong_loop(cond: bool) {
-    // 'inner has statement to break 'outer loop, but it was breaked early by a labeled child loop
+    // 'inner has statement to break 'outer loop, but it was broken out of early by a labeled child loop
     'outer: loop {
         loop {
             //~^ ERROR: infinite loop detected
diff --git a/src/tools/clippy/tests/ui/iter_over_hash_type.rs b/src/tools/clippy/tests/ui/iter_over_hash_type.rs
index 7000c8bf96f..65bae1df421 100644
--- a/src/tools/clippy/tests/ui/iter_over_hash_type.rs
+++ b/src/tools/clippy/tests/ui/iter_over_hash_type.rs
@@ -59,7 +59,7 @@ fn main() {
         let _ = x;
     }
 
-    // shouldnt fire
+    // shouldn't fire
     for x in &vec {
         let _ = x;
     }
diff --git a/src/tools/clippy/tests/ui/manual_pattern_char_comparison.fixed b/src/tools/clippy/tests/ui/manual_pattern_char_comparison.fixed
new file mode 100644
index 00000000000..588226b87e8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_pattern_char_comparison.fixed
@@ -0,0 +1,49 @@
+#![warn(clippy::manual_pattern_char_comparison)]
+
+struct NotStr;
+
+impl NotStr {
+    fn find(&self, _: impl FnMut(char) -> bool) {}
+}
+
+fn main() {
+    let sentence = "Hello, world!";
+    sentence.trim_end_matches(['.', ',', '!', '?']);
+    sentence.split(['\n', 'X']);
+    sentence.split(['\n', 'X']);
+    sentence.splitn(3, 'X');
+    sentence.splitn(3, |c: char| c.is_whitespace() || c == 'X');
+    let char_compare = 'X';
+    sentence.splitn(3, char_compare);
+    sentence.split(['\n', 'X', 'Y']);
+    sentence.splitn(3, 'X');
+    sentence.splitn(3, ['X', 'W']);
+    sentence.find('🎈');
+
+    let not_str = NotStr;
+    not_str.find(|c: char| c == 'X');
+
+    "".find(|c| c == 'a' || c > 'z');
+
+    let x = true;
+    "".find(|c| c == 'a' || x || c == 'b');
+
+    let d = 'd';
+    "".find(|c| c == 'a' || d == 'b');
+
+    "".find(|c| match c {
+        'a' | 'b' => true,
+        _ => c.is_ascii(),
+    });
+
+    "".find(|c| matches!(c, 'a' | 'b' if false));
+
+    "".find(|c| matches!(c, 'a' | '1'..'4'));
+    "".find(|c| c == 'a' || matches!(c, '1'..'4'));
+    macro_rules! m {
+        ($e:expr) => {
+            $e == '?'
+        };
+    }
+    "".find(|c| m!(c));
+}
diff --git a/src/tools/clippy/tests/ui/manual_pattern_char_comparison.rs b/src/tools/clippy/tests/ui/manual_pattern_char_comparison.rs
new file mode 100644
index 00000000000..5078f3ee27f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_pattern_char_comparison.rs
@@ -0,0 +1,49 @@
+#![warn(clippy::manual_pattern_char_comparison)]
+
+struct NotStr;
+
+impl NotStr {
+    fn find(&self, _: impl FnMut(char) -> bool) {}
+}
+
+fn main() {
+    let sentence = "Hello, world!";
+    sentence.trim_end_matches(|c: char| c == '.' || c == ',' || c == '!' || c == '?');
+    sentence.split(|c: char| c == '\n' || c == 'X');
+    sentence.split(|c| c == '\n' || c == 'X');
+    sentence.splitn(3, |c: char| c == 'X');
+    sentence.splitn(3, |c: char| c.is_whitespace() || c == 'X');
+    let char_compare = 'X';
+    sentence.splitn(3, |c: char| c == char_compare);
+    sentence.split(|c: char| matches!(c, '\n' | 'X' | 'Y'));
+    sentence.splitn(3, |c: char| matches!(c, 'X'));
+    sentence.splitn(3, |c: char| matches!(c, 'X' | 'W'));
+    sentence.find(|c| c == '🎈');
+
+    let not_str = NotStr;
+    not_str.find(|c: char| c == 'X');
+
+    "".find(|c| c == 'a' || c > 'z');
+
+    let x = true;
+    "".find(|c| c == 'a' || x || c == 'b');
+
+    let d = 'd';
+    "".find(|c| c == 'a' || d == 'b');
+
+    "".find(|c| match c {
+        'a' | 'b' => true,
+        _ => c.is_ascii(),
+    });
+
+    "".find(|c| matches!(c, 'a' | 'b' if false));
+
+    "".find(|c| matches!(c, 'a' | '1'..'4'));
+    "".find(|c| c == 'a' || matches!(c, '1'..'4'));
+    macro_rules! m {
+        ($e:expr) => {
+            $e == '?'
+        };
+    }
+    "".find(|c| m!(c));
+}
diff --git a/src/tools/clippy/tests/ui/manual_pattern_char_comparison.stderr b/src/tools/clippy/tests/ui/manual_pattern_char_comparison.stderr
new file mode 100644
index 00000000000..b6b51794a11
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_pattern_char_comparison.stderr
@@ -0,0 +1,59 @@
+error: this manual char comparison can be written more succinctly
+  --> tests/ui/manual_pattern_char_comparison.rs:11:31
+   |
+LL |     sentence.trim_end_matches(|c: char| c == '.' || c == ',' || c == '!' || c == '?');
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using an array of `char`: `['.', ',', '!', '?']`
+   |
+   = note: `-D clippy::manual-pattern-char-comparison` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_pattern_char_comparison)]`
+
+error: this manual char comparison can be written more succinctly
+  --> tests/ui/manual_pattern_char_comparison.rs:12:20
+   |
+LL |     sentence.split(|c: char| c == '\n' || c == 'X');
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using an array of `char`: `['\n', 'X']`
+
+error: this manual char comparison can be written more succinctly
+  --> tests/ui/manual_pattern_char_comparison.rs:13:20
+   |
+LL |     sentence.split(|c| c == '\n' || c == 'X');
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using an array of `char`: `['\n', 'X']`
+
+error: this manual char comparison can be written more succinctly
+  --> tests/ui/manual_pattern_char_comparison.rs:14:24
+   |
+LL |     sentence.splitn(3, |c: char| c == 'X');
+   |                        ^^^^^^^^^^^^^^^^^^ help: consider using a `char`: `'X'`
+
+error: this manual char comparison can be written more succinctly
+  --> tests/ui/manual_pattern_char_comparison.rs:17:24
+   |
+LL |     sentence.splitn(3, |c: char| c == char_compare);
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a `char`: `char_compare`
+
+error: this manual char comparison can be written more succinctly
+  --> tests/ui/manual_pattern_char_comparison.rs:18:20
+   |
+LL |     sentence.split(|c: char| matches!(c, '\n' | 'X' | 'Y'));
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using an array of `char`: `['\n', 'X', 'Y']`
+
+error: this manual char comparison can be written more succinctly
+  --> tests/ui/manual_pattern_char_comparison.rs:19:24
+   |
+LL |     sentence.splitn(3, |c: char| matches!(c, 'X'));
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a `char`: `'X'`
+
+error: this manual char comparison can be written more succinctly
+  --> tests/ui/manual_pattern_char_comparison.rs:20:24
+   |
+LL |     sentence.splitn(3, |c: char| matches!(c, 'X' | 'W'));
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using an array of `char`: `['X', 'W']`
+
+error: this manual char comparison can be written more succinctly
+  --> tests/ui/manual_pattern_char_comparison.rs:21:19
+   |
+LL |     sentence.find(|c| c == '🎈');
+   |                   ^^^^^^^^^^^^^ help: consider using a `char`: `'🎈'`
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed b/src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed
index d6e736ba9cc..663de1a5f06 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed
@@ -26,6 +26,12 @@ fn main() {
         Some(x) => x,
         None => &[],
     };
+
+    let x: Result<String, i64> = Ok(String::new());
+    x.unwrap_or_default();
+
+    let x: Result<String, i64> = Ok(String::new());
+    x.unwrap_or_default();
 }
 
 // Issue #12531
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or_default.rs b/src/tools/clippy/tests/ui/manual_unwrap_or_default.rs
index 462d5d90ee7..75ffe09be9d 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or_default.rs
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or_default.rs
@@ -47,6 +47,21 @@ fn main() {
         Some(x) => x,
         None => &[],
     };
+
+    let x: Result<String, i64> = Ok(String::new());
+    match x {
+        //~^ ERROR: match can be simplified with `.unwrap_or_default()`
+        Ok(v) => v,
+        Err(_) => String::new(),
+    };
+
+    let x: Result<String, i64> = Ok(String::new());
+    if let Ok(v) = x {
+        //~^ ERROR: if let can be simplified with `.unwrap_or_default()`
+        v
+    } else {
+        String::new()
+    };
 }
 
 // Issue #12531
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or_default.stderr b/src/tools/clippy/tests/ui/manual_unwrap_or_default.stderr
index 3f1da444301..9e3b1be5cb9 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or_default.stderr
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or_default.stderr
@@ -53,7 +53,28 @@ LL | |     };
    | |_____^ help: replace it with: `x.unwrap_or_default()`
 
 error: match can be simplified with `.unwrap_or_default()`
-  --> tests/ui/manual_unwrap_or_default.rs:56:20
+  --> tests/ui/manual_unwrap_or_default.rs:52:5
+   |
+LL | /     match x {
+LL | |
+LL | |         Ok(v) => v,
+LL | |         Err(_) => String::new(),
+LL | |     };
+   | |_____^ help: replace it with: `x.unwrap_or_default()`
+
+error: if let can be simplified with `.unwrap_or_default()`
+  --> tests/ui/manual_unwrap_or_default.rs:59:5
+   |
+LL | /     if let Ok(v) = x {
+LL | |
+LL | |         v
+LL | |     } else {
+LL | |         String::new()
+LL | |     };
+   | |_____^ help: replace it with: `x.unwrap_or_default()`
+
+error: match can be simplified with `.unwrap_or_default()`
+  --> tests/ui/manual_unwrap_or_default.rs:71:20
    |
 LL |           Some(_) => match *b {
    |  ____________________^
@@ -62,5 +83,5 @@ LL | |             _ => 0,
 LL | |         },
    | |_________^ help: replace it with: `(*b).unwrap_or_default()`
 
-error: aborting due to 6 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.fixed b/src/tools/clippy/tests/ui/match_same_arms2.fixed
index fba0cf33b3c..09e960ddd6a 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.fixed
+++ b/src/tools/clippy/tests/ui/match_same_arms2.fixed
@@ -239,3 +239,20 @@ fn main() {
         _ => false,
     };
 }
+
+// issue #8919, fixed on https://github.com/rust-lang/rust/pull/97312
+mod with_lifetime {
+    enum MaybeStaticStr<'a> {
+        Static(&'static str),
+        Borrowed(&'a str),
+    }
+
+    impl<'a> MaybeStaticStr<'a> {
+        fn get(&self) -> &'a str {
+            match *self {
+                MaybeStaticStr::Borrowed(s) | MaybeStaticStr::Static(s) => s,
+                //~^ ERROR: this match arm has an identical body to another arm
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.rs b/src/tools/clippy/tests/ui/match_same_arms2.rs
index 8a4e3b325bb..cc7425135cc 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms2.rs
@@ -262,3 +262,21 @@ fn main() {
         _ => false,
     };
 }
+
+// issue #8919, fixed on https://github.com/rust-lang/rust/pull/97312
+mod with_lifetime {
+    enum MaybeStaticStr<'a> {
+        Static(&'static str),
+        Borrowed(&'a str),
+    }
+
+    impl<'a> MaybeStaticStr<'a> {
+        fn get(&self) -> &'a str {
+            match *self {
+                MaybeStaticStr::Static(s) => s,
+                MaybeStaticStr::Borrowed(s) => s,
+                //~^ ERROR: this match arm has an identical body to another arm
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.stderr b/src/tools/clippy/tests/ui/match_same_arms2.stderr
index 3d15176ccf9..a5d137c658b 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms2.stderr
@@ -221,5 +221,21 @@ help: and remove this obsolete arm
 LL -         0 => cfg!(not_enable),
    |
 
-error: aborting due to 13 previous errors
+error: this match arm has an identical body to another arm
+  --> tests/ui/match_same_arms2.rs:277:17
+   |
+LL |                 MaybeStaticStr::Borrowed(s) => s,
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try changing either arm body
+help: or try merging the arm patterns
+   |
+LL |                 MaybeStaticStr::Borrowed(s) | MaybeStaticStr::Static(s) => s,
+   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: and remove this obsolete arm
+   |
+LL -                 MaybeStaticStr::Static(s) => s,
+   |
+
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.fixed b/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.fixed
deleted file mode 100644
index de02b2bee31..00000000000
--- a/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.fixed
+++ /dev/null
@@ -1,25 +0,0 @@
-#![warn(clippy::mismatched_target_os)]
-#![allow(unused)]
-
-#[cfg(target_os = "hermit")]
-fn hermit() {}
-
-#[cfg(target_os = "wasi")]
-fn wasi() {}
-
-#[cfg(target_os = "none")]
-fn none() {}
-
-// list with conditions
-#[cfg(all(not(windows), target_os = "wasi"))]
-fn list() {}
-
-// windows is a valid target family, should be ignored
-#[cfg(windows)]
-fn windows() {}
-
-// correct use, should be ignored
-#[cfg(target_os = "hermit")]
-fn correct() {}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.rs b/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.rs
deleted file mode 100644
index a960518751b..00000000000
--- a/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-#![warn(clippy::mismatched_target_os)]
-#![allow(unused)]
-
-#[cfg(hermit)]
-fn hermit() {}
-
-#[cfg(wasi)]
-fn wasi() {}
-
-#[cfg(none)]
-fn none() {}
-
-// list with conditions
-#[cfg(all(not(windows), wasi))]
-fn list() {}
-
-// windows is a valid target family, should be ignored
-#[cfg(windows)]
-fn windows() {}
-
-// correct use, should be ignored
-#[cfg(target_os = "hermit")]
-fn correct() {}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.stderr b/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.stderr
deleted file mode 100644
index 7f7a4e9d6f6..00000000000
--- a/src/tools/clippy/tests/ui/mismatched_target_os_non_unix.stderr
+++ /dev/null
@@ -1,37 +0,0 @@
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_non_unix.rs:4:1
-   |
-LL | #[cfg(hermit)]
-   | ^^^^^^------^^
-   |       |
-   |       help: try: `target_os = "hermit"`
-   |
-   = note: `-D clippy::mismatched-target-os` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::mismatched_target_os)]`
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_non_unix.rs:7:1
-   |
-LL | #[cfg(wasi)]
-   | ^^^^^^----^^
-   |       |
-   |       help: try: `target_os = "wasi"`
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_non_unix.rs:10:1
-   |
-LL | #[cfg(none)]
-   | ^^^^^^----^^
-   |       |
-   |       help: try: `target_os = "none"`
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_non_unix.rs:14:1
-   |
-LL | #[cfg(all(not(windows), wasi))]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^----^^^
-   |                         |
-   |                         help: try: `target_os = "wasi"`
-
-error: aborting due to 4 previous errors
-
diff --git a/src/tools/clippy/tests/ui/mismatched_target_os_unix.fixed b/src/tools/clippy/tests/ui/mismatched_target_os_unix.fixed
deleted file mode 100644
index b945c4d9619..00000000000
--- a/src/tools/clippy/tests/ui/mismatched_target_os_unix.fixed
+++ /dev/null
@@ -1,60 +0,0 @@
-#![warn(clippy::mismatched_target_os)]
-#![allow(unused)]
-
-#[cfg(target_os = "linux")]
-fn linux() {}
-
-#[cfg(target_os = "freebsd")]
-fn freebsd() {}
-
-#[cfg(target_os = "dragonfly")]
-fn dragonfly() {}
-
-#[cfg(target_os = "openbsd")]
-fn openbsd() {}
-
-#[cfg(target_os = "netbsd")]
-fn netbsd() {}
-
-#[cfg(target_os = "macos")]
-fn macos() {}
-
-#[cfg(target_os = "ios")]
-fn ios() {}
-
-#[cfg(target_os = "android")]
-fn android() {}
-
-#[cfg(target_os = "emscripten")]
-fn emscripten() {}
-
-#[cfg(target_os = "fuchsia")]
-fn fuchsia() {}
-
-#[cfg(target_os = "haiku")]
-fn haiku() {}
-
-#[cfg(target_os = "illumos")]
-fn illumos() {}
-
-#[cfg(target_os = "l4re")]
-fn l4re() {}
-
-#[cfg(target_os = "redox")]
-fn redox() {}
-
-#[cfg(target_os = "solaris")]
-fn solaris() {}
-
-#[cfg(target_os = "vxworks")]
-fn vxworks() {}
-
-// list with conditions
-#[cfg(all(not(any(target_os = "solaris", target_os = "linux")), target_os = "freebsd"))]
-fn list() {}
-
-// correct use, should be ignored
-#[cfg(target_os = "freebsd")]
-fn correct() {}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/mismatched_target_os_unix.rs b/src/tools/clippy/tests/ui/mismatched_target_os_unix.rs
deleted file mode 100644
index 34307facd65..00000000000
--- a/src/tools/clippy/tests/ui/mismatched_target_os_unix.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-#![warn(clippy::mismatched_target_os)]
-#![allow(unused)]
-
-#[cfg(linux)]
-fn linux() {}
-
-#[cfg(freebsd)]
-fn freebsd() {}
-
-#[cfg(dragonfly)]
-fn dragonfly() {}
-
-#[cfg(openbsd)]
-fn openbsd() {}
-
-#[cfg(netbsd)]
-fn netbsd() {}
-
-#[cfg(macos)]
-fn macos() {}
-
-#[cfg(ios)]
-fn ios() {}
-
-#[cfg(android)]
-fn android() {}
-
-#[cfg(emscripten)]
-fn emscripten() {}
-
-#[cfg(fuchsia)]
-fn fuchsia() {}
-
-#[cfg(haiku)]
-fn haiku() {}
-
-#[cfg(illumos)]
-fn illumos() {}
-
-#[cfg(l4re)]
-fn l4re() {}
-
-#[cfg(redox)]
-fn redox() {}
-
-#[cfg(solaris)]
-fn solaris() {}
-
-#[cfg(vxworks)]
-fn vxworks() {}
-
-// list with conditions
-#[cfg(all(not(any(solaris, linux)), freebsd))]
-fn list() {}
-
-// correct use, should be ignored
-#[cfg(target_os = "freebsd")]
-fn correct() {}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/mismatched_target_os_unix.stderr b/src/tools/clippy/tests/ui/mismatched_target_os_unix.stderr
deleted file mode 100644
index 3071bad1324..00000000000
--- a/src/tools/clippy/tests/ui/mismatched_target_os_unix.stderr
+++ /dev/null
@@ -1,184 +0,0 @@
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:4:1
-   |
-LL | #[cfg(linux)]
-   | ^^^^^^-----^^
-   |       |
-   |       help: try: `target_os = "linux"`
-   |
-   = help: did you mean `unix`?
-   = note: `-D clippy::mismatched-target-os` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::mismatched_target_os)]`
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:7:1
-   |
-LL | #[cfg(freebsd)]
-   | ^^^^^^-------^^
-   |       |
-   |       help: try: `target_os = "freebsd"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:10:1
-   |
-LL | #[cfg(dragonfly)]
-   | ^^^^^^---------^^
-   |       |
-   |       help: try: `target_os = "dragonfly"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:13:1
-   |
-LL | #[cfg(openbsd)]
-   | ^^^^^^-------^^
-   |       |
-   |       help: try: `target_os = "openbsd"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:16:1
-   |
-LL | #[cfg(netbsd)]
-   | ^^^^^^------^^
-   |       |
-   |       help: try: `target_os = "netbsd"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:19:1
-   |
-LL | #[cfg(macos)]
-   | ^^^^^^-----^^
-   |       |
-   |       help: try: `target_os = "macos"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:22:1
-   |
-LL | #[cfg(ios)]
-   | ^^^^^^---^^
-   |       |
-   |       help: try: `target_os = "ios"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:25:1
-   |
-LL | #[cfg(android)]
-   | ^^^^^^-------^^
-   |       |
-   |       help: try: `target_os = "android"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:28:1
-   |
-LL | #[cfg(emscripten)]
-   | ^^^^^^----------^^
-   |       |
-   |       help: try: `target_os = "emscripten"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:31:1
-   |
-LL | #[cfg(fuchsia)]
-   | ^^^^^^-------^^
-   |       |
-   |       help: try: `target_os = "fuchsia"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:34:1
-   |
-LL | #[cfg(haiku)]
-   | ^^^^^^-----^^
-   |       |
-   |       help: try: `target_os = "haiku"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:37:1
-   |
-LL | #[cfg(illumos)]
-   | ^^^^^^-------^^
-   |       |
-   |       help: try: `target_os = "illumos"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:40:1
-   |
-LL | #[cfg(l4re)]
-   | ^^^^^^----^^
-   |       |
-   |       help: try: `target_os = "l4re"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:43:1
-   |
-LL | #[cfg(redox)]
-   | ^^^^^^-----^^
-   |       |
-   |       help: try: `target_os = "redox"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:46:1
-   |
-LL | #[cfg(solaris)]
-   | ^^^^^^-------^^
-   |       |
-   |       help: try: `target_os = "solaris"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:49:1
-   |
-LL | #[cfg(vxworks)]
-   | ^^^^^^-------^^
-   |       |
-   |       help: try: `target_os = "vxworks"`
-   |
-   = help: did you mean `unix`?
-
-error: operating system used in target family position
-  --> tests/ui/mismatched_target_os_unix.rs:53:1
-   |
-LL | #[cfg(all(not(any(solaris, linux)), freebsd))]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: did you mean `unix`?
-help: try
-   |
-LL | #[cfg(all(not(any(target_os = "solaris", linux)), freebsd))]
-   |                   ~~~~~~~~~~~~~~~~~~~~~
-help: try
-   |
-LL | #[cfg(all(not(any(solaris, target_os = "linux")), freebsd))]
-   |                            ~~~~~~~~~~~~~~~~~~~
-help: try
-   |
-LL | #[cfg(all(not(any(solaris, linux)), target_os = "freebsd"))]
-   |                                     ~~~~~~~~~~~~~~~~~~~~~
-
-error: aborting due to 17 previous errors
-
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs
index 06dbbeb31c0..58e639cc7fd 100644
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs
+++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs
@@ -141,3 +141,33 @@ mod msrv {
         let _ = unsafe { bar.val };
     }
 }
+
+mod issue12677 {
+    pub struct Wrapper {
+        pub strings: Vec<String>,
+    }
+
+    impl Wrapper {
+        #[must_use]
+        pub fn new(strings: Vec<String>) -> Self {
+            Self { strings }
+        }
+
+        #[must_use]
+        pub fn empty() -> Self {
+            Self { strings: Vec::new() }
+        }
+    }
+
+    pub struct Other {
+        pub text: String,
+        pub vec: Vec<String>,
+    }
+
+    impl Other {
+        pub fn new(text: String) -> Self {
+            let vec = Vec::new();
+            Self { text, vec }
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr
index b2cade30563..1c61c3e8713 100644
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr
+++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr
@@ -130,5 +130,30 @@ LL | |         let _ = unsafe { bar.val };
 LL | |     }
    | |_____^
 
-error: aborting due to 14 previous errors
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:152:9
+   |
+LL | /         pub fn new(strings: Vec<String>) -> Self {
+LL | |             Self { strings }
+LL | |         }
+   | |_________^
+
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:157:9
+   |
+LL | /         pub fn empty() -> Self {
+LL | |             Self { strings: Vec::new() }
+LL | |         }
+   | |_________^
+
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:168:9
+   |
+LL | /         pub fn new(text: String) -> Self {
+LL | |             let vec = Vec::new();
+LL | |             Self { text, vec }
+LL | |         }
+   | |_________^
+
+error: aborting due to 17 previous errors
 
diff --git a/src/tools/clippy/tests/ui/missing_fields_in_debug.rs b/src/tools/clippy/tests/ui/missing_fields_in_debug.rs
index e91e8ab7f47..68867ec819d 100644
--- a/src/tools/clippy/tests/ui/missing_fields_in_debug.rs
+++ b/src/tools/clippy/tests/ui/missing_fields_in_debug.rs
@@ -4,6 +4,7 @@
 use std::fmt;
 use std::marker::PhantomData;
 use std::ops::Deref;
+use std::thread::LocalKey;
 
 struct NamedStruct1Ignored {
     data: u8,
@@ -191,4 +192,21 @@ impl fmt::Debug for WithPD {
     }
 }
 
+struct InClosure {
+    a: u8,
+    b: String,
+}
+
+impl fmt::Debug for InClosure {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut d = f.debug_struct("InClosure");
+        d.field("a", &self.a);
+        let mut c = || {
+            d.field("b", &self.b);
+        };
+        c();
+        d.finish()
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/missing_fields_in_debug.stderr b/src/tools/clippy/tests/ui/missing_fields_in_debug.stderr
index 6f8a9abe922..8c1810909dd 100644
--- a/src/tools/clippy/tests/ui/missing_fields_in_debug.stderr
+++ b/src/tools/clippy/tests/ui/missing_fields_in_debug.stderr
@@ -1,5 +1,5 @@
 error: manual `Debug` impl does not include all fields
-  --> tests/ui/missing_fields_in_debug.rs:13:1
+  --> tests/ui/missing_fields_in_debug.rs:14:1
    |
 LL | / impl fmt::Debug for NamedStruct1Ignored {
 LL | |
@@ -11,7 +11,7 @@ LL | | }
    | |_^
    |
 note: this field is unused
-  --> tests/ui/missing_fields_in_debug.rs:10:5
+  --> tests/ui/missing_fields_in_debug.rs:11:5
    |
 LL |     hidden: u32,
    |     ^^^^^^^^^^^
@@ -21,7 +21,7 @@ LL |     hidden: u32,
    = help: to override `-D warnings` add `#[allow(clippy::missing_fields_in_debug)]`
 
 error: manual `Debug` impl does not include all fields
-  --> tests/ui/missing_fields_in_debug.rs:32:1
+  --> tests/ui/missing_fields_in_debug.rs:33:1
    |
 LL | / impl fmt::Debug for NamedStructMultipleIgnored {
 LL | |
@@ -33,17 +33,17 @@ LL | | }
    | |_^
    |
 note: this field is unused
-  --> tests/ui/missing_fields_in_debug.rs:26:5
+  --> tests/ui/missing_fields_in_debug.rs:27:5
    |
 LL |     hidden: u32,
    |     ^^^^^^^^^^^
 note: this field is unused
-  --> tests/ui/missing_fields_in_debug.rs:27:5
+  --> tests/ui/missing_fields_in_debug.rs:28:5
    |
 LL |     hidden2: String,
    |     ^^^^^^^^^^^^^^^
 note: this field is unused
-  --> tests/ui/missing_fields_in_debug.rs:29:5
+  --> tests/ui/missing_fields_in_debug.rs:30:5
    |
 LL |     hidden4: ((((u8), u16), u32), u64),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -51,7 +51,7 @@ LL |     hidden4: ((((u8), u16), u32), u64),
    = help: consider calling `.finish_non_exhaustive()` if you intend to ignore fields
 
 error: manual `Debug` impl does not include all fields
-  --> tests/ui/missing_fields_in_debug.rs:94:1
+  --> tests/ui/missing_fields_in_debug.rs:95:1
    |
 LL | / impl fmt::Debug for MultiExprDebugImpl {
 LL | |
@@ -63,7 +63,7 @@ LL | | }
    | |_^
    |
 note: this field is unused
-  --> tests/ui/missing_fields_in_debug.rs:90:5
+  --> tests/ui/missing_fields_in_debug.rs:91:5
    |
 LL |     b: String,
    |     ^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
index 3059de8f89c..ec63c4fd6a2 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
@@ -131,3 +131,15 @@ fn needless_bool_condition() -> bool {
 
     foo()
 }
+
+fn issue12846() {
+    let a = true;
+    let b = false;
+
+    // parentheses are needed here
+    let _x = (a && b).then(|| todo!());
+    let _x = (a && b) as u8;
+
+    // parentheses are not needed here
+    let _x = a.then(|| todo!());
+}
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.rs b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
index b2cbe86e223..8694aa71590 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.rs
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
@@ -191,3 +191,15 @@ fn needless_bool_condition() -> bool {
 
     foo()
 }
+
+fn issue12846() {
+    let a = true;
+    let b = false;
+
+    // parentheses are needed here
+    let _x = if a && b { true } else { false }.then(|| todo!());
+    let _x = if a && b { true } else { false } as u8;
+
+    // parentheses are not needed here
+    let _x = if a { true } else { false }.then(|| todo!());
+}
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
index 9746e931f50..99b5b998344 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
@@ -191,5 +191,23 @@ error: this if-then-else expression returns a bool literal
 LL |         if unsafe { no(4) } & 1 != 0 { true } else { false }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
 
-error: aborting due to 21 previous errors
+error: this if-then-else expression returns a bool literal
+  --> tests/ui/needless_bool/fixable.rs:200:14
+   |
+LL |     let _x = if a && b { true } else { false }.then(|| todo!());
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(a && b)`
+
+error: this if-then-else expression returns a bool literal
+  --> tests/ui/needless_bool/fixable.rs:201:14
+   |
+LL |     let _x = if a && b { true } else { false } as u8;
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(a && b)`
+
+error: this if-then-else expression returns a bool literal
+  --> tests/ui/needless_bool/fixable.rs:204:14
+   |
+LL |     let _x = if a { true } else { false }.then(|| todo!());
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `a`
+
+error: aborting due to 24 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_character_iteration.fixed b/src/tools/clippy/tests/ui/needless_character_iteration.fixed
new file mode 100644
index 00000000000..f0bf84a41d7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_character_iteration.fixed
@@ -0,0 +1,57 @@
+#![warn(clippy::needless_character_iteration)]
+#![allow(clippy::map_identity, clippy::unnecessary_operation)]
+
+#[derive(Default)]
+struct S {
+    field: &'static str,
+}
+
+impl S {
+    fn field(&self) -> &str {
+        self.field
+    }
+}
+
+fn magic(_: char) {}
+
+fn main() {
+    "foo".is_ascii();
+    //~^ ERROR: checking if a string is ascii using iterators
+    !"foo".is_ascii();
+    //~^ ERROR: checking if a string is ascii using iterators
+    "foo".is_ascii();
+    //~^ ERROR: checking if a string is ascii using iterators
+    !"foo".is_ascii();
+    //~^ ERROR: checking if a string is ascii using iterators
+
+    let s = String::new();
+    s.is_ascii();
+    //~^ ERROR: checking if a string is ascii using iterators
+    !"foo".to_string().is_ascii();
+    //~^ ERROR: checking if a string is ascii using iterators
+
+    "foo".is_ascii();
+    !"foo".is_ascii();
+
+    S::default().field().is_ascii();
+    //~^ ERROR: checking if a string is ascii using iterators
+
+    // Should not lint!
+    "foo".chars().all(|c| {
+        let x = c;
+        magic(x);
+        x.is_ascii()
+    });
+
+    // Should not lint!
+    "foo".chars().all(|c| c.is_ascii() && c.is_alphabetic());
+
+    // Should not lint!
+    "foo".chars().map(|c| c).all(|c| !char::is_ascii(&c));
+
+    // Should not lint!
+    "foo".chars().all(|c| !c.is_ascii());
+
+    // Should not lint!
+    "foo".chars().any(|c| c.is_ascii());
+}
diff --git a/src/tools/clippy/tests/ui/needless_character_iteration.rs b/src/tools/clippy/tests/ui/needless_character_iteration.rs
new file mode 100644
index 00000000000..2805d2438b4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_character_iteration.rs
@@ -0,0 +1,65 @@
+#![warn(clippy::needless_character_iteration)]
+#![allow(clippy::map_identity, clippy::unnecessary_operation)]
+
+#[derive(Default)]
+struct S {
+    field: &'static str,
+}
+
+impl S {
+    fn field(&self) -> &str {
+        self.field
+    }
+}
+
+fn magic(_: char) {}
+
+fn main() {
+    "foo".chars().all(|c| c.is_ascii());
+    //~^ ERROR: checking if a string is ascii using iterators
+    "foo".chars().any(|c| !c.is_ascii());
+    //~^ ERROR: checking if a string is ascii using iterators
+    "foo".chars().all(|c| char::is_ascii(&c));
+    //~^ ERROR: checking if a string is ascii using iterators
+    "foo".chars().any(|c| !char::is_ascii(&c));
+    //~^ ERROR: checking if a string is ascii using iterators
+
+    let s = String::new();
+    s.chars().all(|c| c.is_ascii());
+    //~^ ERROR: checking if a string is ascii using iterators
+    "foo".to_string().chars().any(|c| !c.is_ascii());
+    //~^ ERROR: checking if a string is ascii using iterators
+
+    "foo".chars().all(|c| {
+        //~^ ERROR: checking if a string is ascii using iterators
+        let x = c;
+        x.is_ascii()
+    });
+    "foo".chars().any(|c| {
+        //~^ ERROR: checking if a string is ascii using iterators
+        let x = c;
+        !x.is_ascii()
+    });
+
+    S::default().field().chars().all(|x| x.is_ascii());
+    //~^ ERROR: checking if a string is ascii using iterators
+
+    // Should not lint!
+    "foo".chars().all(|c| {
+        let x = c;
+        magic(x);
+        x.is_ascii()
+    });
+
+    // Should not lint!
+    "foo".chars().all(|c| c.is_ascii() && c.is_alphabetic());
+
+    // Should not lint!
+    "foo".chars().map(|c| c).all(|c| !char::is_ascii(&c));
+
+    // Should not lint!
+    "foo".chars().all(|c| !c.is_ascii());
+
+    // Should not lint!
+    "foo".chars().any(|c| c.is_ascii());
+}
diff --git a/src/tools/clippy/tests/ui/needless_character_iteration.stderr b/src/tools/clippy/tests/ui/needless_character_iteration.stderr
new file mode 100644
index 00000000000..7966033555f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_character_iteration.stderr
@@ -0,0 +1,67 @@
+error: checking if a string is ascii using iterators
+  --> tests/ui/needless_character_iteration.rs:18:5
+   |
+LL |     "foo".chars().all(|c| c.is_ascii());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"foo".is_ascii()`
+   |
+   = note: `-D clippy::needless-character-iteration` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::needless_character_iteration)]`
+
+error: checking if a string is ascii using iterators
+  --> tests/ui/needless_character_iteration.rs:20:5
+   |
+LL |     "foo".chars().any(|c| !c.is_ascii());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!"foo".is_ascii()`
+
+error: checking if a string is ascii using iterators
+  --> tests/ui/needless_character_iteration.rs:22:5
+   |
+LL |     "foo".chars().all(|c| char::is_ascii(&c));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"foo".is_ascii()`
+
+error: checking if a string is ascii using iterators
+  --> tests/ui/needless_character_iteration.rs:24:5
+   |
+LL |     "foo".chars().any(|c| !char::is_ascii(&c));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!"foo".is_ascii()`
+
+error: checking if a string is ascii using iterators
+  --> tests/ui/needless_character_iteration.rs:28:5
+   |
+LL |     s.chars().all(|c| c.is_ascii());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.is_ascii()`
+
+error: checking if a string is ascii using iterators
+  --> tests/ui/needless_character_iteration.rs:30:5
+   |
+LL |     "foo".to_string().chars().any(|c| !c.is_ascii());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!"foo".to_string().is_ascii()`
+
+error: checking if a string is ascii using iterators
+  --> tests/ui/needless_character_iteration.rs:33:5
+   |
+LL | /     "foo".chars().all(|c| {
+LL | |
+LL | |         let x = c;
+LL | |         x.is_ascii()
+LL | |     });
+   | |______^ help: try: `"foo".is_ascii()`
+
+error: checking if a string is ascii using iterators
+  --> tests/ui/needless_character_iteration.rs:38:5
+   |
+LL | /     "foo".chars().any(|c| {
+LL | |
+LL | |         let x = c;
+LL | |         !x.is_ascii()
+LL | |     });
+   | |______^ help: try: `!"foo".is_ascii()`
+
+error: checking if a string is ascii using iterators
+  --> tests/ui/needless_character_iteration.rs:44:5
+   |
+LL |     S::default().field().chars().all(|x| x.is_ascii());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `S::default().field().is_ascii()`
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/needless_maybe_sized.fixed b/src/tools/clippy/tests/ui/needless_maybe_sized.fixed
new file mode 100644
index 00000000000..4d24a7cee61
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_maybe_sized.fixed
@@ -0,0 +1,116 @@
+//@aux-build:proc_macros.rs
+
+#![allow(unused, clippy::multiple_bound_locations)]
+#![warn(clippy::needless_maybe_sized)]
+
+extern crate proc_macros;
+use proc_macros::external;
+
+fn directly<T: Sized>(t: &T) {}
+
+trait A: Sized {}
+trait B: A {}
+
+fn depth_1<T: A>(t: &T) {}
+fn depth_2<T: B>(t: &T) {}
+
+// We only need to show one
+fn multiple_paths<T: A + B>(t: &T) {}
+
+fn in_where<T>(t: &T)
+where
+    T: Sized,
+{
+}
+
+fn mixed_1<T: Sized>(t: &T)
+{
+}
+
+fn mixed_2<T>(t: &T)
+where
+    T: Sized,
+{
+}
+
+fn mixed_3<T>(t: &T)
+where
+    T: Sized,
+{
+}
+
+struct Struct<T: Sized>(T);
+
+impl<T: Sized> Struct<T> {
+    fn method<U: Sized>(&self) {}
+}
+
+enum Enum<T: Sized + 'static> {
+    Variant(&'static T),
+}
+
+union Union<'a, T: Sized> {
+    a: &'a T,
+}
+
+trait Trait<T: Sized> {
+    fn trait_method<U: Sized>() {}
+
+    type GAT<U: Sized>;
+
+    type Assoc: Sized + ?Sized; // False negative
+}
+
+trait SecondInTrait: Send + Sized {}
+fn second_in_trait<T: SecondInTrait>() {}
+
+fn impl_trait(_: &(impl Sized)) {}
+
+trait GenericTrait<T>: Sized {}
+fn in_generic_trait<T: GenericTrait<U>, U>() {}
+
+mod larger_graph {
+    // C1  C2  Sized
+    //  \  /\  /
+    //   B1  B2
+    //    \  /
+    //     A1
+
+    trait C1 {}
+    trait C2 {}
+    trait B1: C1 + C2 {}
+    trait B2: C2 + Sized {}
+    trait A1: B1 + B2 {}
+
+    fn larger_graph<T: A1>() {}
+}
+
+// Should not lint
+
+fn sized<T: Sized>() {}
+fn maybe_sized<T: ?Sized>() {}
+
+struct SeparateBounds<T: ?Sized>(T);
+impl<T: Sized> SeparateBounds<T> {}
+
+trait P {}
+trait Q: P {}
+
+fn ok_depth_1<T: P + ?Sized>() {}
+fn ok_depth_2<T: Q + ?Sized>() {}
+
+external! {
+    fn in_macro<T: Clone + ?Sized>(t: &T) {}
+
+    fn with_local_clone<T: $Clone + ?Sized>(t: &T) {}
+}
+
+#[derive(Clone)]
+struct InDerive<T: ?Sized> {
+    t: T,
+}
+
+struct Refined<T: ?Sized>(T);
+impl<T: Sized> Refined<T> {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_maybe_sized.rs b/src/tools/clippy/tests/ui/needless_maybe_sized.rs
new file mode 100644
index 00000000000..ef66f9a4f2a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_maybe_sized.rs
@@ -0,0 +1,119 @@
+//@aux-build:proc_macros.rs
+
+#![allow(unused, clippy::multiple_bound_locations)]
+#![warn(clippy::needless_maybe_sized)]
+
+extern crate proc_macros;
+use proc_macros::external;
+
+fn directly<T: Sized + ?Sized>(t: &T) {}
+
+trait A: Sized {}
+trait B: A {}
+
+fn depth_1<T: A + ?Sized>(t: &T) {}
+fn depth_2<T: B + ?Sized>(t: &T) {}
+
+// We only need to show one
+fn multiple_paths<T: A + B + ?Sized>(t: &T) {}
+
+fn in_where<T>(t: &T)
+where
+    T: Sized + ?Sized,
+{
+}
+
+fn mixed_1<T: Sized>(t: &T)
+where
+    T: ?Sized,
+{
+}
+
+fn mixed_2<T: ?Sized>(t: &T)
+where
+    T: Sized,
+{
+}
+
+fn mixed_3<T>(t: &T)
+where
+    T: Sized,
+    T: ?Sized,
+{
+}
+
+struct Struct<T: Sized + ?Sized>(T);
+
+impl<T: Sized + ?Sized> Struct<T> {
+    fn method<U: Sized + ?Sized>(&self) {}
+}
+
+enum Enum<T: Sized + ?Sized + 'static> {
+    Variant(&'static T),
+}
+
+union Union<'a, T: Sized + ?Sized> {
+    a: &'a T,
+}
+
+trait Trait<T: Sized + ?Sized> {
+    fn trait_method<U: Sized + ?Sized>() {}
+
+    type GAT<U: Sized + ?Sized>;
+
+    type Assoc: Sized + ?Sized; // False negative
+}
+
+trait SecondInTrait: Send + Sized {}
+fn second_in_trait<T: ?Sized + SecondInTrait>() {}
+
+fn impl_trait(_: &(impl Sized + ?Sized)) {}
+
+trait GenericTrait<T>: Sized {}
+fn in_generic_trait<T: GenericTrait<U> + ?Sized, U>() {}
+
+mod larger_graph {
+    // C1  C2  Sized
+    //  \  /\  /
+    //   B1  B2
+    //    \  /
+    //     A1
+
+    trait C1 {}
+    trait C2 {}
+    trait B1: C1 + C2 {}
+    trait B2: C2 + Sized {}
+    trait A1: B1 + B2 {}
+
+    fn larger_graph<T: A1 + ?Sized>() {}
+}
+
+// Should not lint
+
+fn sized<T: Sized>() {}
+fn maybe_sized<T: ?Sized>() {}
+
+struct SeparateBounds<T: ?Sized>(T);
+impl<T: Sized> SeparateBounds<T> {}
+
+trait P {}
+trait Q: P {}
+
+fn ok_depth_1<T: P + ?Sized>() {}
+fn ok_depth_2<T: Q + ?Sized>() {}
+
+external! {
+    fn in_macro<T: Clone + ?Sized>(t: &T) {}
+
+    fn with_local_clone<T: $Clone + ?Sized>(t: &T) {}
+}
+
+#[derive(Clone)]
+struct InDerive<T: ?Sized> {
+    t: T,
+}
+
+struct Refined<T: ?Sized>(T);
+impl<T: Sized> Refined<T> {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_maybe_sized.stderr b/src/tools/clippy/tests/ui/needless_maybe_sized.stderr
new file mode 100644
index 00000000000..3b1d2b49b06
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_maybe_sized.stderr
@@ -0,0 +1,353 @@
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:9:24
+   |
+LL | fn directly<T: Sized + ?Sized>(t: &T) {}
+   |                        ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:9:16
+   |
+LL | fn directly<T: Sized + ?Sized>(t: &T) {}
+   |                ^^^^^
+   = note: `-D clippy::needless-maybe-sized` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::needless_maybe_sized)]`
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - fn directly<T: Sized + ?Sized>(t: &T) {}
+LL + fn directly<T: Sized>(t: &T) {}
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:14:19
+   |
+LL | fn depth_1<T: A + ?Sized>(t: &T) {}
+   |                   ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:14:15
+   |
+LL | fn depth_1<T: A + ?Sized>(t: &T) {}
+   |               ^
+   = note: ...because `A` has the bound `Sized`
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - fn depth_1<T: A + ?Sized>(t: &T) {}
+LL + fn depth_1<T: A>(t: &T) {}
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:15:19
+   |
+LL | fn depth_2<T: B + ?Sized>(t: &T) {}
+   |                   ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:15:15
+   |
+LL | fn depth_2<T: B + ?Sized>(t: &T) {}
+   |               ^
+   = note: ...because `B` has the bound `A`
+   = note: ...because `A` has the bound `Sized`
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - fn depth_2<T: B + ?Sized>(t: &T) {}
+LL + fn depth_2<T: B>(t: &T) {}
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:18:30
+   |
+LL | fn multiple_paths<T: A + B + ?Sized>(t: &T) {}
+   |                              ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:18:22
+   |
+LL | fn multiple_paths<T: A + B + ?Sized>(t: &T) {}
+   |                      ^
+   = note: ...because `A` has the bound `Sized`
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - fn multiple_paths<T: A + B + ?Sized>(t: &T) {}
+LL + fn multiple_paths<T: A + B>(t: &T) {}
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:22:16
+   |
+LL |     T: Sized + ?Sized,
+   |                ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:22:8
+   |
+LL |     T: Sized + ?Sized,
+   |        ^^^^^
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL -     T: Sized + ?Sized,
+LL +     T: Sized,
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:28:8
+   |
+LL |     T: ?Sized,
+   |        ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:26:15
+   |
+LL | fn mixed_1<T: Sized>(t: &T)
+   |               ^^^^^
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - where
+LL -     T: ?Sized,
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:32:15
+   |
+LL | fn mixed_2<T: ?Sized>(t: &T)
+   |               ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:34:8
+   |
+LL |     T: Sized,
+   |        ^^^^^
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - fn mixed_2<T: ?Sized>(t: &T)
+LL + fn mixed_2<T>(t: &T)
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:41:8
+   |
+LL |     T: ?Sized,
+   |        ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:40:8
+   |
+LL |     T: Sized,
+   |        ^^^^^
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL -     T: Sized,
+LL -     T: ?Sized,
+LL +     T: Sized,
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:45:26
+   |
+LL | struct Struct<T: Sized + ?Sized>(T);
+   |                          ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:45:18
+   |
+LL | struct Struct<T: Sized + ?Sized>(T);
+   |                  ^^^^^
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - struct Struct<T: Sized + ?Sized>(T);
+LL + struct Struct<T: Sized>(T);
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:47:17
+   |
+LL | impl<T: Sized + ?Sized> Struct<T> {
+   |                 ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:47:9
+   |
+LL | impl<T: Sized + ?Sized> Struct<T> {
+   |         ^^^^^
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - impl<T: Sized + ?Sized> Struct<T> {
+LL + impl<T: Sized> Struct<T> {
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:48:26
+   |
+LL |     fn method<U: Sized + ?Sized>(&self) {}
+   |                          ^^^^^^
+   |
+note: `U` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:48:18
+   |
+LL |     fn method<U: Sized + ?Sized>(&self) {}
+   |                  ^^^^^
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL -     fn method<U: Sized + ?Sized>(&self) {}
+LL +     fn method<U: Sized>(&self) {}
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:51:22
+   |
+LL | enum Enum<T: Sized + ?Sized + 'static> {
+   |                      ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:51:14
+   |
+LL | enum Enum<T: Sized + ?Sized + 'static> {
+   |              ^^^^^
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - enum Enum<T: Sized + ?Sized + 'static> {
+LL + enum Enum<T: Sized + 'static> {
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:55:28
+   |
+LL | union Union<'a, T: Sized + ?Sized> {
+   |                            ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:55:20
+   |
+LL | union Union<'a, T: Sized + ?Sized> {
+   |                    ^^^^^
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - union Union<'a, T: Sized + ?Sized> {
+LL + union Union<'a, T: Sized> {
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:59:24
+   |
+LL | trait Trait<T: Sized + ?Sized> {
+   |                        ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:59:16
+   |
+LL | trait Trait<T: Sized + ?Sized> {
+   |                ^^^^^
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - trait Trait<T: Sized + ?Sized> {
+LL + trait Trait<T: Sized> {
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:60:32
+   |
+LL |     fn trait_method<U: Sized + ?Sized>() {}
+   |                                ^^^^^^
+   |
+note: `U` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:60:24
+   |
+LL |     fn trait_method<U: Sized + ?Sized>() {}
+   |                        ^^^^^
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL -     fn trait_method<U: Sized + ?Sized>() {}
+LL +     fn trait_method<U: Sized>() {}
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:62:25
+   |
+LL |     type GAT<U: Sized + ?Sized>;
+   |                         ^^^^^^
+   |
+note: `U` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:62:17
+   |
+LL |     type GAT<U: Sized + ?Sized>;
+   |                 ^^^^^
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL -     type GAT<U: Sized + ?Sized>;
+LL +     type GAT<U: Sized>;
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:68:23
+   |
+LL | fn second_in_trait<T: ?Sized + SecondInTrait>() {}
+   |                       ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:68:32
+   |
+LL | fn second_in_trait<T: ?Sized + SecondInTrait>() {}
+   |                                ^^^^^^^^^^^^^
+   = note: ...because `SecondInTrait` has the bound `Sized`
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - fn second_in_trait<T: ?Sized + SecondInTrait>() {}
+LL + fn second_in_trait<T: SecondInTrait>() {}
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:70:33
+   |
+LL | fn impl_trait(_: &(impl Sized + ?Sized)) {}
+   |                                 ^^^^^^
+   |
+note: `impl Sized + ?Sized` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:70:25
+   |
+LL | fn impl_trait(_: &(impl Sized + ?Sized)) {}
+   |                         ^^^^^
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - fn impl_trait(_: &(impl Sized + ?Sized)) {}
+LL + fn impl_trait(_: &(impl Sized)) {}
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:73:42
+   |
+LL | fn in_generic_trait<T: GenericTrait<U> + ?Sized, U>() {}
+   |                                          ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:73:24
+   |
+LL | fn in_generic_trait<T: GenericTrait<U> + ?Sized, U>() {}
+   |                        ^^^^^^^^^^^^^^^
+   = note: ...because `GenericTrait` has the bound `Sized`
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL - fn in_generic_trait<T: GenericTrait<U> + ?Sized, U>() {}
+LL + fn in_generic_trait<T: GenericTrait<U>, U>() {}
+   |
+
+error: `?Sized` bound is ignored because of a `Sized` requirement
+  --> tests/ui/needless_maybe_sized.rs:88:29
+   |
+LL |     fn larger_graph<T: A1 + ?Sized>() {}
+   |                             ^^^^^^
+   |
+note: `T` cannot be unsized because of the bound
+  --> tests/ui/needless_maybe_sized.rs:88:24
+   |
+LL |     fn larger_graph<T: A1 + ?Sized>() {}
+   |                        ^^
+   = note: ...because `A1` has the bound `B2`
+   = note: ...because `B2` has the bound `Sized`
+help: change the bounds that require `Sized`, or remove the `?Sized` bound
+   |
+LL -     fn larger_graph<T: A1 + ?Sized>() {}
+LL +     fn larger_graph<T: A1>() {}
+   |
+
+error: aborting due to 20 previous errors
+
diff --git a/src/tools/clippy/tests/ui/new_ret_no_self.rs b/src/tools/clippy/tests/ui/new_ret_no_self.rs
index b944f531ef6..175b14d815a 100644
--- a/src/tools/clippy/tests/ui/new_ret_no_self.rs
+++ b/src/tools/clippy/tests/ui/new_ret_no_self.rs
@@ -390,9 +390,7 @@ mod issue7344 {
 
     impl<T> RetImplTraitSelf2<T> {
         // should not trigger lint
-        fn new(t: T) -> impl Trait2<(), Self> {
-            unimplemented!()
-        }
+        fn new(t: T) -> impl Trait2<(), Self> {}
     }
 
     struct RetImplTraitNoSelf2<T>(T);
@@ -401,7 +399,6 @@ mod issue7344 {
         // should trigger lint
         fn new(t: T) -> impl Trait2<(), i32> {
             //~^ ERROR: methods called `new` usually return `Self`
-            unimplemented!()
         }
     }
 
diff --git a/src/tools/clippy/tests/ui/new_ret_no_self.stderr b/src/tools/clippy/tests/ui/new_ret_no_self.stderr
index d440a9f45fc..3597ad65838 100644
--- a/src/tools/clippy/tests/ui/new_ret_no_self.stderr
+++ b/src/tools/clippy/tests/ui/new_ret_no_self.stderr
@@ -96,11 +96,10 @@ LL | |         }
    | |_________^
 
 error: methods called `new` usually return `Self`
-  --> tests/ui/new_ret_no_self.rs:402:9
+  --> tests/ui/new_ret_no_self.rs:400:9
    |
 LL | /         fn new(t: T) -> impl Trait2<(), i32> {
 LL | |
-LL | |             unimplemented!()
 LL | |         }
    | |_________^
 
diff --git a/src/tools/clippy/tests/ui/non_canonical_clone_impl.fixed b/src/tools/clippy/tests/ui/non_canonical_clone_impl.fixed
index 7d1be412e54..11616f28825 100644
--- a/src/tools/clippy/tests/ui/non_canonical_clone_impl.fixed
+++ b/src/tools/clippy/tests/ui/non_canonical_clone_impl.fixed
@@ -1,7 +1,11 @@
+//@aux-build:proc_macro_derive.rs
 #![allow(clippy::clone_on_copy, unused)]
 #![allow(clippy::assigning_clones)]
 #![no_main]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
 // lint
 
 struct A(u32);
@@ -95,3 +99,19 @@ impl<A: Copy> Clone for Uwu<A> {
 }
 
 impl<A: std::fmt::Debug + Copy + Clone> Copy for Uwu<A> {}
+
+// should skip proc macros, see https://github.com/rust-lang/rust-clippy/issues/12788
+#[derive(proc_macro_derive::NonCanonicalClone)]
+pub struct G;
+
+with_span!(
+    span
+
+    #[derive(Copy)]
+    struct H;
+    impl Clone for H {
+        fn clone(&self) -> Self {
+            todo!()
+        }
+    }
+);
diff --git a/src/tools/clippy/tests/ui/non_canonical_clone_impl.rs b/src/tools/clippy/tests/ui/non_canonical_clone_impl.rs
index beae05efb2f..a36c7ed44c2 100644
--- a/src/tools/clippy/tests/ui/non_canonical_clone_impl.rs
+++ b/src/tools/clippy/tests/ui/non_canonical_clone_impl.rs
@@ -1,7 +1,11 @@
+//@aux-build:proc_macro_derive.rs
 #![allow(clippy::clone_on_copy, unused)]
 #![allow(clippy::assigning_clones)]
 #![no_main]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
 // lint
 
 struct A(u32);
@@ -105,3 +109,19 @@ impl<A: Copy> Clone for Uwu<A> {
 }
 
 impl<A: std::fmt::Debug + Copy + Clone> Copy for Uwu<A> {}
+
+// should skip proc macros, see https://github.com/rust-lang/rust-clippy/issues/12788
+#[derive(proc_macro_derive::NonCanonicalClone)]
+pub struct G;
+
+with_span!(
+    span
+
+    #[derive(Copy)]
+    struct H;
+    impl Clone for H {
+        fn clone(&self) -> Self {
+            todo!()
+        }
+    }
+);
diff --git a/src/tools/clippy/tests/ui/non_canonical_clone_impl.stderr b/src/tools/clippy/tests/ui/non_canonical_clone_impl.stderr
index 6bfc99d988b..f7cad58150f 100644
--- a/src/tools/clippy/tests/ui/non_canonical_clone_impl.stderr
+++ b/src/tools/clippy/tests/ui/non_canonical_clone_impl.stderr
@@ -1,5 +1,5 @@
 error: non-canonical implementation of `clone` on a `Copy` type
-  --> tests/ui/non_canonical_clone_impl.rs:10:29
+  --> tests/ui/non_canonical_clone_impl.rs:14:29
    |
 LL |       fn clone(&self) -> Self {
    |  _____________________________^
@@ -11,7 +11,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::non_canonical_clone_impl)]`
 
 error: unnecessary implementation of `clone_from` on a `Copy` type
-  --> tests/ui/non_canonical_clone_impl.rs:14:5
+  --> tests/ui/non_canonical_clone_impl.rs:18:5
    |
 LL | /     fn clone_from(&mut self, source: &Self) {
 LL | |         source.clone();
@@ -20,7 +20,7 @@ LL | |     }
    | |_____^ help: remove it
 
 error: non-canonical implementation of `clone` on a `Copy` type
-  --> tests/ui/non_canonical_clone_impl.rs:81:29
+  --> tests/ui/non_canonical_clone_impl.rs:85:29
    |
 LL |       fn clone(&self) -> Self {
    |  _____________________________^
@@ -29,7 +29,7 @@ LL | |     }
    | |_____^ help: change this to: `{ *self }`
 
 error: unnecessary implementation of `clone_from` on a `Copy` type
-  --> tests/ui/non_canonical_clone_impl.rs:85:5
+  --> tests/ui/non_canonical_clone_impl.rs:89:5
    |
 LL | /     fn clone_from(&mut self, source: &Self) {
 LL | |         source.clone();
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed b/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed
index aba599678e3..cc91ba6ec66 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed
+++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed
@@ -1,5 +1,3 @@
-//@compile-flags: -Zdeduplicate-diagnostics=yes
-
 #![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)]
 #![warn(clippy::nonminimal_bool)]
 
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs b/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs
index 35f22db1d36..c812f6f0ca4 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs
+++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs
@@ -1,5 +1,3 @@
-//@compile-flags: -Zdeduplicate-diagnostics=yes
-
 #![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)]
 #![warn(clippy::nonminimal_bool)]
 
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr b/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr
index 18da4e0d380..d7adc0638b3 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr
+++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr
@@ -1,5 +1,5 @@
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:10:13
+  --> tests/ui/nonminimal_bool_methods.rs:8:13
    |
 LL |     let _ = !a.is_some();
    |             ^^^^^^^^^^^^ help: try: `a.is_none()`
@@ -8,91 +8,91 @@ LL |     let _ = !a.is_some();
    = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:12:13
+  --> tests/ui/nonminimal_bool_methods.rs:10:13
    |
 LL |     let _ = !a.is_none();
    |             ^^^^^^^^^^^^ help: try: `a.is_some()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:14:13
+  --> tests/ui/nonminimal_bool_methods.rs:12:13
    |
 LL |     let _ = !b.is_err();
    |             ^^^^^^^^^^^ help: try: `b.is_ok()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:16:13
+  --> tests/ui/nonminimal_bool_methods.rs:14:13
    |
 LL |     let _ = !b.is_ok();
    |             ^^^^^^^^^^ help: try: `b.is_err()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:18:13
+  --> tests/ui/nonminimal_bool_methods.rs:16:13
    |
 LL |     let _ = !(a.is_some() && !c);
    |             ^^^^^^^^^^^^^^^^^^^^ help: try: `a.is_none() || c`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:19:13
+  --> tests/ui/nonminimal_bool_methods.rs:17:13
    |
 LL |     let _ = !(a.is_some() || !c);
    |             ^^^^^^^^^^^^^^^^^^^^ help: try: `a.is_none() && c`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:20:26
+  --> tests/ui/nonminimal_bool_methods.rs:18:26
    |
 LL |     let _ = !(!c ^ c) || !a.is_some();
    |                          ^^^^^^^^^^^^ help: try: `a.is_none()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:21:25
+  --> tests/ui/nonminimal_bool_methods.rs:19:25
    |
 LL |     let _ = (!c ^ c) || !a.is_some();
    |                         ^^^^^^^^^^^^ help: try: `a.is_none()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:22:23
+  --> tests/ui/nonminimal_bool_methods.rs:20:23
    |
 LL |     let _ = !c ^ c || !a.is_some();
    |                       ^^^^^^^^^^^^ help: try: `a.is_none()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:94:8
+  --> tests/ui/nonminimal_bool_methods.rs:92:8
    |
 LL |     if !res.is_ok() {}
    |        ^^^^^^^^^^^^ help: try: `res.is_err()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:95:8
+  --> tests/ui/nonminimal_bool_methods.rs:93:8
    |
 LL |     if !res.is_err() {}
    |        ^^^^^^^^^^^^^ help: try: `res.is_ok()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:98:8
+  --> tests/ui/nonminimal_bool_methods.rs:96:8
    |
 LL |     if !res.is_some() {}
    |        ^^^^^^^^^^^^^^ help: try: `res.is_none()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:99:8
+  --> tests/ui/nonminimal_bool_methods.rs:97:8
    |
 LL |     if !res.is_none() {}
    |        ^^^^^^^^^^^^^^ help: try: `res.is_some()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:115:8
+  --> tests/ui/nonminimal_bool_methods.rs:113:8
    |
 LL |     if !(a as u64 >= b) {}
    |        ^^^^^^^^^^^^^^^^ help: try: `(a as u64) < b`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:116:8
+  --> tests/ui/nonminimal_bool_methods.rs:114:8
    |
 LL |     if !((a as u64) >= b) {}
    |        ^^^^^^^^^^^^^^^^^^ help: try: `(a as u64) < b`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:117:8
+  --> tests/ui/nonminimal_bool_methods.rs:115:8
    |
 LL |     if !(a as u64 <= b) {}
    |        ^^^^^^^^^^^^^^^^ help: try: `a as u64 > b`
diff --git a/src/tools/clippy/tests/ui/or_fun_call.fixed b/src/tools/clippy/tests/ui/or_fun_call.fixed
index e7ba54864ab..7657ef470c5 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/or_fun_call.fixed
@@ -311,4 +311,11 @@ mod lazy {
     }
 }
 
+fn host_effect() {
+    // #12877 - make sure we don't ICE in type_certainty
+    use std::ops::Add;
+
+    Add::<i32>::add(1, 1).add(i32::MIN);
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/or_fun_call.rs b/src/tools/clippy/tests/ui/or_fun_call.rs
index 196632133d5..97cf496d3ac 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.rs
+++ b/src/tools/clippy/tests/ui/or_fun_call.rs
@@ -311,4 +311,11 @@ mod lazy {
     }
 }
 
+fn host_effect() {
+    // #12877 - make sure we don't ICE in type_certainty
+    use std::ops::Add;
+
+    Add::<i32>::add(1, 1).add(i32::MIN);
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/overly_complex_bool_expr.fixed b/src/tools/clippy/tests/ui/overly_complex_bool_expr.fixed
index e44f6063156..439b1145431 100644
--- a/src/tools/clippy/tests/ui/overly_complex_bool_expr.fixed
+++ b/src/tools/clippy/tests/ui/overly_complex_bool_expr.fixed
@@ -37,3 +37,13 @@ fn check_expect() {
     #[expect(clippy::overly_complex_bool_expr)]
     let _ = a < b && a >= b;
 }
+
+#[allow(clippy::never_loop)]
+fn check_never_type() {
+    loop {
+        _ = (break) || true;
+    }
+    loop {
+        _ = (return) || true;
+    }
+}
diff --git a/src/tools/clippy/tests/ui/overly_complex_bool_expr.rs b/src/tools/clippy/tests/ui/overly_complex_bool_expr.rs
index f010a8537e7..b96fd1adf11 100644
--- a/src/tools/clippy/tests/ui/overly_complex_bool_expr.rs
+++ b/src/tools/clippy/tests/ui/overly_complex_bool_expr.rs
@@ -37,3 +37,13 @@ fn check_expect() {
     #[expect(clippy::overly_complex_bool_expr)]
     let _ = a < b && a >= b;
 }
+
+#[allow(clippy::never_loop)]
+fn check_never_type() {
+    loop {
+        _ = (break) || true;
+    }
+    loop {
+        _ = (return) || true;
+    }
+}
diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn.rs b/src/tools/clippy/tests/ui/panic_in_result_fn.rs
index 41e2f522689..aaaf9a109ac 100644
--- a/src/tools/clippy/tests/ui/panic_in_result_fn.rs
+++ b/src/tools/clippy/tests/ui/panic_in_result_fn.rs
@@ -56,6 +56,11 @@ fn function_result_with_panic() -> Result<bool, String> // should emit lint
     panic!("error");
 }
 
+fn in_closure() -> Result<bool, String> {
+    let c = || panic!();
+    c()
+}
+
 fn todo() {
     println!("something");
 }
diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn.stderr b/src/tools/clippy/tests/ui/panic_in_result_fn.stderr
index cd2234bdfb1..2d49b5ab1b8 100644
--- a/src/tools/clippy/tests/ui/panic_in_result_fn.stderr
+++ b/src/tools/clippy/tests/ui/panic_in_result_fn.stderr
@@ -34,5 +34,21 @@ note: return Err() instead of panicking
 LL |     panic!("error");
    |     ^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: used `panic!()` or assertion in a function that returns `Result`
+  --> tests/ui/panic_in_result_fn.rs:59:1
+   |
+LL | / fn in_closure() -> Result<bool, String> {
+LL | |     let c = || panic!();
+LL | |     c()
+LL | | }
+   | |_^
+   |
+   = help: `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
+note: return Err() instead of panicking
+  --> tests/ui/panic_in_result_fn.rs:60:16
+   |
+LL |     let c = || panic!();
+   |                ^^^^^^^^
+
+error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/search_is_some.rs b/src/tools/clippy/tests/ui/search_is_some.rs
index e8a0920b645..9a9aaba56ad 100644
--- a/src/tools/clippy/tests/ui/search_is_some.rs
+++ b/src/tools/clippy/tests/ui/search_is_some.rs
@@ -1,5 +1,6 @@
 //@aux-build:option_helpers.rs
 #![warn(clippy::search_is_some)]
+#![allow(clippy::manual_pattern_char_comparison)]
 #![allow(clippy::useless_vec)]
 #![allow(dead_code)]
 extern crate option_helpers;
diff --git a/src/tools/clippy/tests/ui/search_is_some.stderr b/src/tools/clippy/tests/ui/search_is_some.stderr
index b5f84d23284..b5ef5534177 100644
--- a/src/tools/clippy/tests/ui/search_is_some.stderr
+++ b/src/tools/clippy/tests/ui/search_is_some.stderr
@@ -1,5 +1,5 @@
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some.rs:15:13
+  --> tests/ui/search_is_some.rs:16:13
    |
 LL |       let _ = v.iter().find(|&x| {
    |  _____________^
@@ -13,7 +13,7 @@ LL | |                    ).is_some();
    = help: to override `-D warnings` add `#[allow(clippy::search_is_some)]`
 
 error: called `is_some()` after searching an `Iterator` with `position`
-  --> tests/ui/search_is_some.rs:21:13
+  --> tests/ui/search_is_some.rs:22:13
    |
 LL |       let _ = v.iter().position(|&x| {
    |  _____________^
@@ -25,7 +25,7 @@ LL | |                    ).is_some();
    = help: this is more succinctly expressed by calling `any()`
 
 error: called `is_some()` after searching an `Iterator` with `rposition`
-  --> tests/ui/search_is_some.rs:27:13
+  --> tests/ui/search_is_some.rs:28:13
    |
 LL |       let _ = v.iter().rposition(|&x| {
    |  _____________^
@@ -37,13 +37,13 @@ LL | |                    ).is_some();
    = help: this is more succinctly expressed by calling `any()`
 
 error: called `is_some()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some.rs:42:20
+  --> tests/ui/search_is_some.rs:43:20
    |
 LL |     let _ = (0..1).find(some_closure).is_some();
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(some_closure)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some.rs:52:13
+  --> tests/ui/search_is_some.rs:53:13
    |
 LL |       let _ = v.iter().find(|&x| {
    |  _____________^
@@ -55,7 +55,7 @@ LL | |                    ).is_none();
    = help: this is more succinctly expressed by calling `any()` with negation
 
 error: called `is_none()` after searching an `Iterator` with `position`
-  --> tests/ui/search_is_some.rs:58:13
+  --> tests/ui/search_is_some.rs:59:13
    |
 LL |       let _ = v.iter().position(|&x| {
    |  _____________^
@@ -67,7 +67,7 @@ LL | |                    ).is_none();
    = help: this is more succinctly expressed by calling `any()` with negation
 
 error: called `is_none()` after searching an `Iterator` with `rposition`
-  --> tests/ui/search_is_some.rs:64:13
+  --> tests/ui/search_is_some.rs:65:13
    |
 LL |       let _ = v.iter().rposition(|&x| {
    |  _____________^
@@ -79,7 +79,7 @@ LL | |                    ).is_none();
    = help: this is more succinctly expressed by calling `any()` with negation
 
 error: called `is_none()` after searching an `Iterator` with `find`
-  --> tests/ui/search_is_some.rs:79:13
+  --> tests/ui/search_is_some.rs:80:13
    |
 LL |     let _ = (0..1).find(some_closure).is_none();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(0..1).any(some_closure)`
diff --git a/src/tools/clippy/tests/ui/single_char_add_str.fixed b/src/tools/clippy/tests/ui/single_char_add_str.fixed
index eafd17f5387..aef15252b1b 100644
--- a/src/tools/clippy/tests/ui/single_char_add_str.fixed
+++ b/src/tools/clippy/tests/ui/single_char_add_str.fixed
@@ -21,6 +21,12 @@ fn main() {
     string.push('\u{0052}');
     string.push('a');
 
+    let c_ref = &'a';
+    string.push(*c_ref);
+    let c = 'a';
+    string.push(c);
+    string.push('a');
+
     get_string!().push('ö');
 
     // `insert_str` tests
@@ -41,5 +47,9 @@ fn main() {
     string.insert(Y, '"');
     string.insert(Y, '\'');
 
+    string.insert(0, *c_ref);
+    string.insert(0, c);
+    string.insert(0, 'a');
+
     get_string!().insert(1, '?');
 }
diff --git a/src/tools/clippy/tests/ui/single_char_add_str.rs b/src/tools/clippy/tests/ui/single_char_add_str.rs
index 5326c7cf24c..7f97250dacd 100644
--- a/src/tools/clippy/tests/ui/single_char_add_str.rs
+++ b/src/tools/clippy/tests/ui/single_char_add_str.rs
@@ -21,6 +21,12 @@ fn main() {
     string.push_str("\u{0052}");
     string.push_str(r##"a"##);
 
+    let c_ref = &'a';
+    string.push_str(&c_ref.to_string());
+    let c = 'a';
+    string.push_str(&c.to_string());
+    string.push_str(&'a'.to_string());
+
     get_string!().push_str("ö");
 
     // `insert_str` tests
@@ -41,5 +47,9 @@ fn main() {
     string.insert_str(Y, r##"""##);
     string.insert_str(Y, r##"'"##);
 
+    string.insert_str(0, &c_ref.to_string());
+    string.insert_str(0, &c.to_string());
+    string.insert_str(0, &'a'.to_string());
+
     get_string!().insert_str(1, "?");
 }
diff --git a/src/tools/clippy/tests/ui/single_char_add_str.stderr b/src/tools/clippy/tests/ui/single_char_add_str.stderr
index 89d75f20f55..7791c67578a 100644
--- a/src/tools/clippy/tests/ui/single_char_add_str.stderr
+++ b/src/tools/clippy/tests/ui/single_char_add_str.stderr
@@ -31,65 +31,101 @@ error: calling `push_str()` using a single-character string literal
 LL |     string.push_str(r##"a"##);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `string.push('a')`
 
+error: calling `push_str()` using a single-character converted to string
+  --> tests/ui/single_char_add_str.rs:25:5
+   |
+LL |     string.push_str(&c_ref.to_string());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` without `to_string()`: `string.push(*c_ref)`
+
+error: calling `push_str()` using a single-character converted to string
+  --> tests/ui/single_char_add_str.rs:27:5
+   |
+LL |     string.push_str(&c.to_string());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` without `to_string()`: `string.push(c)`
+
+error: calling `push_str()` using a single-character converted to string
+  --> tests/ui/single_char_add_str.rs:28:5
+   |
+LL |     string.push_str(&'a'.to_string());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` without `to_string()`: `string.push('a')`
+
 error: calling `push_str()` using a single-character string literal
-  --> tests/ui/single_char_add_str.rs:24:5
+  --> tests/ui/single_char_add_str.rs:30:5
    |
 LL |     get_string!().push_str("ö");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `push` with a character literal: `get_string!().push('ö')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> tests/ui/single_char_add_str.rs:29:5
+  --> tests/ui/single_char_add_str.rs:35:5
    |
 LL |     string.insert_str(0, "R");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, 'R')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> tests/ui/single_char_add_str.rs:30:5
+  --> tests/ui/single_char_add_str.rs:36:5
    |
 LL |     string.insert_str(1, "'");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(1, '\'')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> tests/ui/single_char_add_str.rs:35:5
+  --> tests/ui/single_char_add_str.rs:41:5
    |
 LL |     string.insert_str(0, "\x52");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, '\x52')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> tests/ui/single_char_add_str.rs:36:5
+  --> tests/ui/single_char_add_str.rs:42:5
    |
 LL |     string.insert_str(0, "\u{0052}");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(0, '\u{0052}')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> tests/ui/single_char_add_str.rs:38:5
+  --> tests/ui/single_char_add_str.rs:44:5
    |
 LL |     string.insert_str(x, r##"a"##);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(x, 'a')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> tests/ui/single_char_add_str.rs:40:5
+  --> tests/ui/single_char_add_str.rs:46:5
    |
 LL |     string.insert_str(Y, r##"a"##);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, 'a')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> tests/ui/single_char_add_str.rs:41:5
+  --> tests/ui/single_char_add_str.rs:47:5
    |
 LL |     string.insert_str(Y, r##"""##);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, '"')`
 
 error: calling `insert_str()` using a single-character string literal
-  --> tests/ui/single_char_add_str.rs:42:5
+  --> tests/ui/single_char_add_str.rs:48:5
    |
 LL |     string.insert_str(Y, r##"'"##);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `string.insert(Y, '\'')`
 
+error: calling `insert_str()` using a single-character converted to string
+  --> tests/ui/single_char_add_str.rs:50:5
+   |
+LL |     string.insert_str(0, &c_ref.to_string());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` without `to_string()`: `string.insert(0, *c_ref)`
+
+error: calling `insert_str()` using a single-character converted to string
+  --> tests/ui/single_char_add_str.rs:51:5
+   |
+LL |     string.insert_str(0, &c.to_string());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` without `to_string()`: `string.insert(0, c)`
+
+error: calling `insert_str()` using a single-character converted to string
+  --> tests/ui/single_char_add_str.rs:52:5
+   |
+LL |     string.insert_str(0, &'a'.to_string());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` without `to_string()`: `string.insert(0, 'a')`
+
 error: calling `insert_str()` using a single-character string literal
-  --> tests/ui/single_char_add_str.rs:44:5
+  --> tests/ui/single_char_add_str.rs:54:5
    |
 LL |     get_string!().insert_str(1, "?");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `insert` with a character literal: `get_string!().insert(1, '?')`
 
-error: aborting due to 15 previous errors
+error: aborting due to 21 previous errors
 
diff --git a/src/tools/clippy/tests/ui/str_to_string.fixed b/src/tools/clippy/tests/ui/str_to_string.fixed
new file mode 100644
index 00000000000..52e40b45a8b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/str_to_string.fixed
@@ -0,0 +1,9 @@
+#![warn(clippy::str_to_string)]
+
+fn main() {
+    let hello = "hello world".to_owned();
+    //~^ ERROR: `to_string()` called on a `&str`
+    let msg = &hello[..];
+    msg.to_owned();
+    //~^ ERROR: `to_string()` called on a `&str`
+}
diff --git a/src/tools/clippy/tests/ui/str_to_string.stderr b/src/tools/clippy/tests/ui/str_to_string.stderr
index 13b73622d69..a761d96cd6b 100644
--- a/src/tools/clippy/tests/ui/str_to_string.stderr
+++ b/src/tools/clippy/tests/ui/str_to_string.stderr
@@ -2,9 +2,8 @@ error: `to_string()` called on a `&str`
   --> tests/ui/str_to_string.rs:4:17
    |
 LL |     let hello = "hello world".to_string();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"hello world".to_owned()`
    |
-   = help: consider using `.to_owned()`
    = note: `-D clippy::str-to-string` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::str_to_string)]`
 
@@ -12,9 +11,7 @@ error: `to_string()` called on a `&str`
   --> tests/ui/str_to_string.rs:7:5
    |
 LL |     msg.to_string();
-   |     ^^^^^^^^^^^^^^^
-   |
-   = help: consider using `.to_owned()`
+   |     ^^^^^^^^^^^^^^^ help: try: `msg.to_owned()`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs b/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs
index 0039c805b7d..d325887bfba 100644
--- a/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs
+++ b/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs
@@ -1,5 +1,9 @@
 #![deny(clippy::type_repetition_in_bounds)]
-#![allow(clippy::extra_unused_type_parameters, clippy::multiple_bound_locations)]
+#![allow(
+    clippy::extra_unused_type_parameters,
+    clippy::multiple_bound_locations,
+    clippy::needless_maybe_sized
+)]
 
 use serde::Deserialize;
 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
diff --git a/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr b/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
index e9c6b41aaa8..77944c95045 100644
--- a/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
+++ b/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
@@ -1,5 +1,5 @@
 error: this type has already been used as a bound predicate
-  --> tests/ui/type_repetition_in_bounds.rs:10:5
+  --> tests/ui/type_repetition_in_bounds.rs:14:5
    |
 LL |     T: Clone,
    |     ^^^^^^^^
@@ -12,7 +12,7 @@ LL | #![deny(clippy::type_repetition_in_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this type has already been used as a bound predicate
-  --> tests/ui/type_repetition_in_bounds.rs:28:5
+  --> tests/ui/type_repetition_in_bounds.rs:32:5
    |
 LL |     Self: Copy + Default + Ord,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,7 +20,7 @@ LL |     Self: Copy + Default + Ord,
    = help: consider combining the bounds: `Self: Clone + Copy + Default + Ord`
 
 error: this type has already been used as a bound predicate
-  --> tests/ui/type_repetition_in_bounds.rs:103:5
+  --> tests/ui/type_repetition_in_bounds.rs:107:5
    |
 LL |     T: Clone,
    |     ^^^^^^^^
@@ -28,7 +28,7 @@ LL |     T: Clone,
    = help: consider combining the bounds: `T: ?Sized + Clone`
 
 error: this type has already been used as a bound predicate
-  --> tests/ui/type_repetition_in_bounds.rs:109:5
+  --> tests/ui/type_repetition_in_bounds.rs:113:5
    |
 LL |     T: ?Sized,
    |     ^^^^^^^^^
@@ -36,7 +36,7 @@ LL |     T: ?Sized,
    = help: consider combining the bounds: `T: Clone + ?Sized`
 
 error: this type has already been used as a bound predicate
-  --> tests/ui/type_repetition_in_bounds.rs:135:9
+  --> tests/ui/type_repetition_in_bounds.rs:139:9
    |
 LL |         T: Trait<Option<usize>, Box<[String]>, bool> + 'static,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.rs b/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.rs
index ff960520f5e..9915f8b843e 100644
--- a/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.rs
@@ -5,18 +5,18 @@
 //~^ ERROR: no need to put clippy lints behind a `clippy` cfg
 #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
 //~^ ERROR: no need to put clippy lints behind a `clippy` cfg
-#![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
+#![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
 //~^ ERROR: no need to put clippy lints behind a `clippy` cfg
-#![cfg_attr(clippy, deny(clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
+#![cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
 //~^ ERROR: no need to put clippy lints behind a `clippy` cfg
 
 #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
 //~^ ERROR: no need to put clippy lints behind a `clippy` cfg
 #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
 //~^ ERROR: no need to put clippy lints behind a `clippy` cfg
-#[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
+#[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
 //~^ ERROR: no need to put clippy lints behind a `clippy` cfg
-#[cfg_attr(clippy, deny(clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
+#[cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
 //~^ ERROR: no need to put clippy lints behind a `clippy` cfg
 pub struct Bar;
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr b/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr
index 3d58c9eb5da..16a86165295 100644
--- a/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_clippy_cfg.stderr
@@ -18,16 +18,16 @@ LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
 error: no need to put clippy lints behind a `clippy` cfg
   --> tests/ui/unnecessary_clippy_cfg.rs:17:36
    |
-LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: write instead: `#[deny(clippy::non_minimal_cfg,clippy::maybe_misused_cfg)]`
+   = note: write instead: `#[deny(clippy::non_minimal_cfg)]`
 
 error: no need to put clippy lints behind a `clippy` cfg
   --> tests/ui/unnecessary_clippy_cfg.rs:19:1
    |
-LL | #[cfg_attr(clippy, deny(clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#[deny(clippy::non_minimal_cfg, clippy::maybe_misused_cfg)]`
+LL | #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#[deny(clippy::non_minimal_cfg)]`
 
 error: no need to put clippy lints behind a `clippy` cfg
   --> tests/ui/unnecessary_clippy_cfg.rs:4:1
@@ -46,21 +46,21 @@ LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
 error: no need to put clippy lints behind a `clippy` cfg
   --> tests/ui/unnecessary_clippy_cfg.rs:8:37
    |
-LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
-   |                                     ^^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: write instead: `#![deny(clippy::non_minimal_cfg,clippy::maybe_misused_cfg)]`
+   = note: write instead: `#![deny(clippy::non_minimal_cfg)]`
 
 error: no need to put clippy lints behind a `clippy` cfg
   --> tests/ui/unnecessary_clippy_cfg.rs:10:1
    |
-LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![deny(clippy::non_minimal_cfg, clippy::maybe_misused_cfg)]`
+LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![deny(clippy::non_minimal_cfg)]`
 
 error: duplicated attribute
   --> tests/ui/unnecessary_clippy_cfg.rs:8:26
    |
-LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
+LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
    |                          ^^^^^^^^^
    |
 note: first defined here
@@ -71,7 +71,7 @@ LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
 help: remove this attribute
   --> tests/ui/unnecessary_clippy_cfg.rs:8:26
    |
-LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
+LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
    |                          ^^^^^^^^^
    = note: `-D clippy::duplicated-attributes` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
@@ -79,7 +79,7 @@ LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_
 error: duplicated attribute
   --> tests/ui/unnecessary_clippy_cfg.rs:17:25
    |
-LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
+LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
    |                         ^^^^^^^^^
    |
 note: first defined here
@@ -90,7 +90,7 @@ LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
 help: remove this attribute
   --> tests/ui/unnecessary_clippy_cfg.rs:17:25
    |
-LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg, clippy::maybe_misused_cfg))]
+LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))]
    |                         ^^^^^^^^^
 
 error: aborting due to 10 previous errors
diff --git a/src/tools/clippy/tests/ui/unwrap_in_result.rs b/src/tools/clippy/tests/ui/unwrap_in_result.rs
index a19db46c667..62c6d959c84 100644
--- a/src/tools/clippy/tests/ui/unwrap_in_result.rs
+++ b/src/tools/clippy/tests/ui/unwrap_in_result.rs
@@ -38,6 +38,11 @@ impl A {
         }
         None
     }
+
+    fn in_closure(a: Option<bool>) -> Option<bool> {
+        let c = || a.unwrap();
+        Some(c())
+    }
 }
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/unwrap_in_result.stderr b/src/tools/clippy/tests/ui/unwrap_in_result.stderr
index 29c7a9373aa..752177aaca5 100644
--- a/src/tools/clippy/tests/ui/unwrap_in_result.stderr
+++ b/src/tools/clippy/tests/ui/unwrap_in_result.stderr
@@ -38,5 +38,21 @@ note: potential non-recoverable error(s)
 LL |         let i = i_str.parse::<i32>().expect("not a number");
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: used unwrap or expect in a function that returns result or option
+  --> tests/ui/unwrap_in_result.rs:42:5
+   |
+LL | /     fn in_closure(a: Option<bool>) -> Option<bool> {
+LL | |         let c = || a.unwrap();
+LL | |         Some(c())
+LL | |     }
+   | |_____^
+   |
+   = help: unwrap and expect should not be used in a function that returns result or option
+note: potential non-recoverable error(s)
+  --> tests/ui/unwrap_in_result.rs:43:20
+   |
+LL |         let c = || a.unwrap();
+   |                    ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/useless_conversion_try.rs b/src/tools/clippy/tests/ui/useless_conversion_try.rs
index 803d3b39f37..23edeae12b8 100644
--- a/src/tools/clippy/tests/ui/useless_conversion_try.rs
+++ b/src/tools/clippy/tests/ui/useless_conversion_try.rs
@@ -1,5 +1,9 @@
 #![deny(clippy::useless_conversion)]
-#![allow(clippy::needless_if, clippy::unnecessary_fallible_conversions)]
+#![allow(
+    clippy::needless_if,
+    clippy::unnecessary_fallible_conversions,
+    clippy::manual_unwrap_or_default
+)]
 
 fn test_generic<T: Copy>(val: T) -> T {
     let _ = T::try_from(val).unwrap();
diff --git a/src/tools/clippy/tests/ui/useless_conversion_try.stderr b/src/tools/clippy/tests/ui/useless_conversion_try.stderr
index 11fb8f38ea5..30a43629dbd 100644
--- a/src/tools/clippy/tests/ui/useless_conversion_try.stderr
+++ b/src/tools/clippy/tests/ui/useless_conversion_try.stderr
@@ -1,5 +1,5 @@
 error: useless conversion to the same type: `T`
-  --> tests/ui/useless_conversion_try.rs:5:13
+  --> tests/ui/useless_conversion_try.rs:9:13
    |
 LL |     let _ = T::try_from(val).unwrap();
    |             ^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@ LL | #![deny(clippy::useless_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: useless conversion to the same type: `T`
-  --> tests/ui/useless_conversion_try.rs:7:5
+  --> tests/ui/useless_conversion_try.rs:11:5
    |
 LL |     val.try_into().unwrap()
    |     ^^^^^^^^^^^^^^
@@ -20,7 +20,7 @@ LL |     val.try_into().unwrap()
    = help: consider removing `.try_into()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion_try.rs:30:21
+  --> tests/ui/useless_conversion_try.rs:34:21
    |
 LL |     let _: String = "foo".to_string().try_into().unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -28,7 +28,7 @@ LL |     let _: String = "foo".to_string().try_into().unwrap();
    = help: consider removing `.try_into()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion_try.rs:32:21
+  --> tests/ui/useless_conversion_try.rs:36:21
    |
 LL |     let _: String = TryFrom::try_from("foo".to_string()).unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -36,7 +36,7 @@ LL |     let _: String = TryFrom::try_from("foo".to_string()).unwrap();
    = help: consider removing `TryFrom::try_from()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion_try.rs:34:13
+  --> tests/ui/useless_conversion_try.rs:38:13
    |
 LL |     let _ = String::try_from("foo".to_string()).unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL |     let _ = String::try_from("foo".to_string()).unwrap();
    = help: consider removing `String::try_from()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion_try.rs:36:13
+  --> tests/ui/useless_conversion_try.rs:40:13
    |
 LL |     let _ = String::try_from(format!("A: {:04}", 123)).unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -52,7 +52,7 @@ LL |     let _ = String::try_from(format!("A: {:04}", 123)).unwrap();
    = help: consider removing `String::try_from()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion_try.rs:38:21
+  --> tests/ui/useless_conversion_try.rs:42:21
    |
 LL |     let _: String = format!("Hello {}", "world").try_into().unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -60,7 +60,7 @@ LL |     let _: String = format!("Hello {}", "world").try_into().unwrap();
    = help: consider removing `.try_into()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion_try.rs:40:21
+  --> tests/ui/useless_conversion_try.rs:44:21
    |
 LL |     let _: String = String::new().try_into().unwrap();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -68,7 +68,7 @@ LL |     let _: String = String::new().try_into().unwrap();
    = help: consider removing `.try_into()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion_try.rs:42:27
+  --> tests/ui/useless_conversion_try.rs:46:27
    |
 LL |     let _: String = match String::from("_").try_into() {
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/util/gh-pages/script.js b/src/tools/clippy/util/gh-pages/script.js
index 7fd779fe9a4..7cca298df8e 100644
--- a/src/tools/clippy/util/gh-pages/script.js
+++ b/src/tools/clippy/util/gh-pages/script.js
@@ -397,7 +397,7 @@
             $scope.bySearch = function (lint, index, array) {
                 let searchStr = $scope.search;
                 // It can be `null` I haven't missed this value
-                if (searchStr == null || searchStr.length < 3) {
+                if (searchStr == null) {
                     return true;
                 }
                 searchStr = searchStr.toLowerCase();
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index b0047770564..da7f03441e7 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -582,7 +582,7 @@ impl TargetCfgs {
                         name,
                         Some(
                             value
-                                .strip_suffix("\"")
+                                .strip_suffix('\"')
                                 .expect("key-value pair should be properly quoted"),
                         ),
                     )
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index da0196dad2f..5469b9f1a0a 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -14,6 +14,7 @@ use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
 use crate::header::cfg::parse_cfg_name_directive;
 use crate::header::cfg::MatchOutcome;
 use crate::header::needs::CachedNeedsConditions;
+use crate::util::static_regex;
 use crate::{extract_cdb_version, extract_gdb_version};
 
 mod cfg;
@@ -81,7 +82,7 @@ impl EarlyProps {
             panic!("errors encountered during EarlyProps parsing");
         }
 
-        return props;
+        props
     }
 }
 
@@ -381,7 +382,7 @@ impl TestProps {
                         // Individual flags can be single-quoted to preserve spaces; see
                         // <https://github.com/rust-lang/rust/pull/115948/commits/957c5db6>.
                         flags
-                            .split("'")
+                            .split('\'')
                             .enumerate()
                             .flat_map(|(i, f)| {
                                 if i % 2 == 1 { vec![f] } else { f.split_whitespace().collect() }
@@ -612,7 +613,7 @@ impl TestProps {
 
         for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
             if let Ok(val) = env::var(key) {
-                if self.exec_env.iter().find(|&&(ref x, _)| x == key).is_none() {
+                if !self.exec_env.iter().any(|&(ref x, _)| x == key) {
                     self.exec_env.push(((*key).to_owned(), val))
                 }
             }
@@ -990,7 +991,7 @@ pub(crate) fn check_directive(directive_ln: &str) -> CheckDirectiveResult<'_> {
     let trailing = post.trim().split_once(' ').map(|(pre, _)| pre).unwrap_or(post);
     let trailing_directive = {
         // 1. is the directive name followed by a space? (to exclude `:`)
-        matches!(directive_ln.get(directive_name.len()..), Some(s) if s.starts_with(" "))
+        matches!(directive_ln.get(directive_name.len()..), Some(s) if s.starts_with(' '))
             // 2. is what is after that directive also a directive (ex: "only-x86 only-arm")
             && KNOWN_DIRECTIVE_NAMES.contains(&trailing)
     }
@@ -1022,9 +1023,6 @@ fn iter_header(
     if mode == Mode::CoverageRun {
         let extra_directives: &[&str] = &[
             "needs-profiler-support",
-            // FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
-            // properly. Since we only have GCC on the CI ignore the test for now.
-            "ignore-windows-gnu",
             // FIXME(pietroalbini): this test currently does not work on cross-compiled
             // targets because remote-test is not capable of sending back the *.profraw
             // files generated by the LLVM instrumentation.
@@ -1186,11 +1184,11 @@ impl Config {
         }
     }
 
-    fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(String, String)> {
+    fn parse_custom_normalization(&self, line: &str, prefix: &str) -> Option<(String, String)> {
         if parse_cfg_name_directive(self, line, prefix).outcome == MatchOutcome::Match {
-            let from = parse_normalization_string(&mut line)?;
-            let to = parse_normalization_string(&mut line)?;
-            Some((from, to))
+            let (regex, replacement) = parse_normalize_rule(line)
+                .unwrap_or_else(|| panic!("couldn't parse custom normalization rule: `{line}`"));
+            Some((regex, replacement))
         } else {
             None
         }
@@ -1311,24 +1309,29 @@ fn expand_variables(mut value: String, config: &Config) -> String {
     value
 }
 
-/// Finds the next quoted string `"..."` in `line`, and extract the content from it. Move the `line`
-/// variable after the end of the quoted string.
-///
-/// # Examples
-///
-/// ```
-/// let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits)\".";
-/// let first = parse_normalization_string(&mut s);
-/// assert_eq!(first, Some("something (32 bits)".to_owned()));
-/// assert_eq!(s, " -> \"something ($WORD bits)\".");
+/// Parses the regex and replacement values of a `//@ normalize-*` header,
+/// in the format:
+/// ```text
+/// normalize-*: "REGEX" -> "REPLACEMENT"
 /// ```
-fn parse_normalization_string(line: &mut &str) -> Option<String> {
-    // FIXME support escapes in strings.
-    let begin = line.find('"')? + 1;
-    let end = line[begin..].find('"')? + begin;
-    let result = line[begin..end].to_owned();
-    *line = &line[end + 1..];
-    Some(result)
+fn parse_normalize_rule(header: &str) -> Option<(String, String)> {
+    // FIXME(#126370): A colon after the header name should be mandatory, but
+    // currently is not, and there are many tests that lack the colon.
+    // FIXME: Support escaped double-quotes in strings.
+    let captures = static_regex!(
+        r#"(?x) # (verbose mode regex)
+        ^
+        [^:\s]+:?\s*            # (header name followed by optional colon)
+        "(?<regex>[^"]*)"       # "REGEX"
+        \s+->\s+                # ->
+        "(?<replacement>[^"]*)" # "REPLACEMENT"
+        $
+        "#
+    )
+    .captures(header)?;
+    let regex = captures["regex"].to_owned();
+    let replacement = captures["replacement"].to_owned();
+    Some((regex, replacement))
 }
 
 pub fn extract_llvm_version(version: &str) -> Option<u32> {
@@ -1357,7 +1360,7 @@ pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<u32> {
     }
     let version = String::from_utf8(output.stdout).ok()?;
     for line in version.lines() {
-        if let Some(version) = line.split("LLVM version ").skip(1).next() {
+        if let Some(version) = line.split("LLVM version ").nth(1) {
             return extract_llvm_version(version);
         }
     }
@@ -1388,7 +1391,7 @@ where
 
     let min = parse(min)?;
     let max = match max {
-        Some(max) if max.is_empty() => return None,
+        Some("") => return None,
         Some(max) => parse(max)?,
         _ => min,
     };
@@ -1460,12 +1463,12 @@ pub fn make_test_description<R: Read>(
             decision!(ignore_gdb(config, ln));
             decision!(ignore_lldb(config, ln));
 
-            if config.target == "wasm32-unknown-unknown" {
-                if config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS) {
-                    decision!(IgnoreDecision::Ignore {
-                        reason: "ignored on WASM as the run results cannot be checked there".into(),
-                    });
-                }
+            if config.target == "wasm32-unknown-unknown"
+                && config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS)
+            {
+                decision!(IgnoreDecision::Ignore {
+                    reason: "ignored on WASM as the run results cannot be checked there".into(),
+                });
             }
 
             should_fail |= config.parse_name_directive(ln, "should-fail");
diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs
index 510043e3bfd..522c52b1de2 100644
--- a/src/tools/compiletest/src/header/cfg.rs
+++ b/src/tools/compiletest/src/header/cfg.rs
@@ -58,7 +58,7 @@ pub(super) fn parse_cfg_name_directive<'a>(
 
     // Some of the matchers might be "" depending on what the target information is. To avoid
     // problems we outright reject empty directives.
-    if name == "" {
+    if name.is_empty() {
         return ParsedNameDirective::not_a_directive();
     }
 
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 8a37a4d6d31..61a85b84ad6 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -3,7 +3,7 @@ use std::path::Path;
 use std::str::FromStr;
 
 use crate::common::{Config, Debugger, Mode};
-use crate::header::{parse_normalization_string, EarlyProps, HeadersCache};
+use crate::header::{parse_normalize_rule, EarlyProps, HeadersCache};
 
 use super::iter_header;
 
@@ -32,35 +32,41 @@ fn make_test_description<R: Read>(
 }
 
 #[test]
-fn test_parse_normalization_string() {
-    let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits)\".";
-    let first = parse_normalization_string(&mut s);
-    assert_eq!(first, Some("something (32 bits)".to_owned()));
-    assert_eq!(s, " -> \"something ($WORD bits)\".");
-
-    // Nothing to normalize (No quotes)
-    let mut s = "normalize-stderr-32bit: something (32 bits) -> something ($WORD bits).";
-    let first = parse_normalization_string(&mut s);
-    assert_eq!(first, None);
-    assert_eq!(s, r#"normalize-stderr-32bit: something (32 bits) -> something ($WORD bits)."#);
-
-    // Nothing to normalize (Only a single quote)
-    let mut s = "normalize-stderr-32bit: \"something (32 bits) -> something ($WORD bits).";
-    let first = parse_normalization_string(&mut s);
-    assert_eq!(first, None);
-    assert_eq!(s, "normalize-stderr-32bit: \"something (32 bits) -> something ($WORD bits).");
-
-    // Nothing to normalize (Three quotes)
-    let mut s = "normalize-stderr-32bit: \"something (32 bits)\" -> \"something ($WORD bits).";
-    let first = parse_normalization_string(&mut s);
-    assert_eq!(first, Some("something (32 bits)".to_owned()));
-    assert_eq!(s, " -> \"something ($WORD bits).");
-
-    // Nothing to normalize (No quotes, 16-bit)
-    let mut s = "normalize-stderr-16bit: something (16 bits) -> something ($WORD bits).";
-    let first = parse_normalization_string(&mut s);
-    assert_eq!(first, None);
-    assert_eq!(s, r#"normalize-stderr-16bit: something (16 bits) -> something ($WORD bits)."#);
+fn test_parse_normalize_rule() {
+    let good_data = &[
+        (
+            r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)""#,
+            "something (32 bits)",
+            "something ($WORD bits)",
+        ),
+        // FIXME(#126370): A colon after the header name should be mandatory,
+        // but currently is not, and there are many tests that lack the colon.
+        (
+            r#"normalize-stderr-32bit "something (32 bits)" -> "something ($WORD bits)""#,
+            "something (32 bits)",
+            "something ($WORD bits)",
+        ),
+    ];
+
+    for &(input, expected_regex, expected_replacement) in good_data {
+        let parsed = parse_normalize_rule(input);
+        let parsed =
+            parsed.as_ref().map(|(regex, replacement)| (regex.as_str(), replacement.as_str()));
+        assert_eq!(parsed, Some((expected_regex, expected_replacement)));
+    }
+
+    let bad_data = &[
+        r#"normalize-stderr-16bit: something (16 bits) -> something ($WORD bits)"#,
+        r#"normalize-stderr-32bit: something (32 bits) -> something ($WORD bits)"#,
+        r#"normalize-stderr-32bit: "something (32 bits) -> something ($WORD bits)"#,
+        r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)"#,
+        r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)"."#,
+    ];
+
+    for &input in bad_data {
+        let parsed = parse_normalize_rule(input);
+        assert_eq!(parsed, None);
+    }
 }
 
 #[derive(Default)]
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 62e71e9b59d..0cf05b32e96 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -1147,7 +1147,7 @@ fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> {
 }
 
 fn not_a_digit(c: char) -> bool {
-    !c.is_digit(10)
+    !c.is_ascii_digit()
 }
 
 fn check_overlapping_tests(found_paths: &HashSet<PathBuf>) {
diff --git a/src/tools/compiletest/src/read2.rs b/src/tools/compiletest/src/read2.rs
index 3f1921cb6bd..8c06339f3c3 100644
--- a/src/tools/compiletest/src/read2.rs
+++ b/src/tools/compiletest/src/read2.rs
@@ -6,7 +6,6 @@ mod tests;
 
 pub use self::imp::read2;
 use std::io::{self, Write};
-use std::mem::replace;
 use std::process::{Child, Output};
 
 #[derive(Copy, Clone, Debug)]
@@ -101,10 +100,10 @@ impl ProcOutput {
                     return;
                 }
 
-                let mut head = replace(bytes, Vec::new());
+                let mut head = std::mem::take(bytes);
                 // Don't truncate if this as a whole line.
                 // That should make it less likely that we cut a JSON line in half.
-                if head.last() != Some(&('\n' as u8)) {
+                if head.last() != Some(&b'\n') {
                     head.truncate(MAX_OUT_LEN);
                 }
                 let skipped = new_len - head.len();
diff --git a/src/tools/compiletest/src/read2/tests.rs b/src/tools/compiletest/src/read2/tests.rs
index 5ad2db3cb83..9e052ff069b 100644
--- a/src/tools/compiletest/src/read2/tests.rs
+++ b/src/tools/compiletest/src/read2/tests.rs
@@ -64,9 +64,9 @@ fn test_abbreviate_filterss_are_detected() {
 #[test]
 fn test_abbreviate_filters_avoid_abbreviations() {
     let mut out = ProcOutput::new();
-    let filters = &[std::iter::repeat('a').take(64).collect::<String>()];
+    let filters = &["a".repeat(64)];
 
-    let mut expected = vec![b'.'; MAX_OUT_LEN - FILTERED_PATHS_PLACEHOLDER_LEN as usize];
+    let mut expected = vec![b'.'; MAX_OUT_LEN - FILTERED_PATHS_PLACEHOLDER_LEN];
     expected.extend_from_slice(filters[0].as_bytes());
 
     out.extend(&expected, filters);
@@ -81,7 +81,7 @@ fn test_abbreviate_filters_avoid_abbreviations() {
 #[test]
 fn test_abbreviate_filters_can_still_cause_abbreviations() {
     let mut out = ProcOutput::new();
-    let filters = &[std::iter::repeat('a').take(64).collect::<String>()];
+    let filters = &["a".repeat(64)];
 
     let mut input = vec![b'.'; MAX_OUT_LEN];
     input.extend_from_slice(filters[0].as_bytes());
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index dbe016b8305..72b57d91c23 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -15,7 +15,7 @@ use crate::errors::{self, Error, ErrorKind};
 use crate::header::TestProps;
 use crate::json;
 use crate::read2::{read2_abbreviated, Truncated};
-use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, PathBufExt};
+use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, static_regex, PathBufExt};
 use crate::ColorConfig;
 use colored::Colorize;
 use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
@@ -48,14 +48,6 @@ use debugger::DebuggerCommands;
 #[cfg(test)]
 mod tests;
 
-macro_rules! static_regex {
-    ($re:literal) => {{
-        static RE: ::std::sync::OnceLock<::regex::Regex> = ::std::sync::OnceLock::new();
-        RE.get_or_init(|| ::regex::Regex::new($re).unwrap())
-    }};
-}
-use static_regex;
-
 const FAKE_SRC_BASE: &str = "fake-test-src-base";
 
 #[cfg(windows)]
@@ -382,11 +374,11 @@ impl<'test> TestCx<'test> {
 
         // if a test does not crash, consider it an error
         if proc_res.status.success() || matches!(proc_res.status.code(), Some(1 | 0)) {
-            self.fatal(&format!(
+            self.fatal(
                 "test no longer crashes/triggers ICE! Please give it a mearningful name, \
             add a doc-comment to the start of the test explaining why it exists and \
-            move it to tests/ui or wherever you see fit."
-            ));
+            move it to tests/ui or wherever you see fit.",
+            );
         }
     }
 
@@ -705,10 +697,10 @@ impl<'test> TestCx<'test> {
             // since it is extensively used in the testsuite.
             check_cfg.push_str("cfg(FALSE");
             for revision in &self.props.revisions {
-                check_cfg.push_str(",");
-                check_cfg.push_str(&normalize_revision(&revision));
+                check_cfg.push(',');
+                check_cfg.push_str(&normalize_revision(revision));
             }
-            check_cfg.push_str(")");
+            check_cfg.push(')');
 
             cmd.args(&["--check-cfg", &check_cfg]);
         }
@@ -826,7 +818,7 @@ impl<'test> TestCx<'test> {
         // Append the other `cdb-command:`s
         for line in &dbg_cmds.commands {
             script_str.push_str(line);
-            script_str.push_str("\n");
+            script_str.push('\n');
         }
 
         script_str.push_str("qq\n"); // Quit the debugger (including remote debugger, if any)
@@ -1208,7 +1200,7 @@ impl<'test> TestCx<'test> {
         // Append the other commands
         for line in &dbg_cmds.commands {
             script_str.push_str(line);
-            script_str.push_str("\n");
+            script_str.push('\n');
         }
 
         // Finally, quit the debugger
@@ -1258,7 +1250,7 @@ impl<'test> TestCx<'test> {
         // Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS.
         let options_to_remove = ["-O".to_owned(), "-g".to_owned(), "--debuginfo".to_owned()];
 
-        options.iter().filter(|x| !options_to_remove.contains(x)).map(|x| x.clone()).collect()
+        options.iter().filter(|x| !options_to_remove.contains(x)).cloned().collect()
     }
 
     fn maybe_add_external_args(&self, cmd: &mut Command, args: &Vec<String>) {
@@ -2512,8 +2504,8 @@ impl<'test> TestCx<'test> {
             // This works with both `--emit asm` (as default output name for the assembly)
             // and `ptx-linker` because the latter can write output at requested location.
             let output_path = self.output_base_name().with_extension(extension);
-            let output_file = TargetLocation::ThisFile(output_path.clone());
-            output_file
+
+            TargetLocation::ThisFile(output_path.clone())
         }
     }
 
@@ -2760,7 +2752,7 @@ impl<'test> TestCx<'test> {
             for entry in walkdir::WalkDir::new(dir) {
                 let entry = entry.expect("failed to read file");
                 if entry.file_type().is_file()
-                    && entry.path().extension().and_then(|p| p.to_str()) == Some("html".into())
+                    && entry.path().extension().and_then(|p| p.to_str()) == Some("html")
                 {
                     let status =
                         Command::new("tidy").args(&tidy_args).arg(entry.path()).status().unwrap();
@@ -2791,8 +2783,7 @@ impl<'test> TestCx<'test> {
             &compare_dir,
             self.config.verbose,
             |file_type, extension| {
-                file_type.is_file()
-                    && (extension == Some("html".into()) || extension == Some("js".into()))
+                file_type.is_file() && (extension == Some("html") || extension == Some("js"))
             },
         ) {
             return;
@@ -2838,11 +2829,11 @@ impl<'test> TestCx<'test> {
                 }
                 match String::from_utf8(line.clone()) {
                     Ok(line) => {
-                        if line.starts_with("+") {
+                        if line.starts_with('+') {
                             write!(&mut out, "{}", line.green()).unwrap();
-                        } else if line.starts_with("-") {
+                        } else if line.starts_with('-') {
                             write!(&mut out, "{}", line.red()).unwrap();
-                        } else if line.starts_with("@") {
+                        } else if line.starts_with('@') {
                             write!(&mut out, "{}", line.blue()).unwrap();
                         } else {
                             out.write_all(line.as_bytes()).unwrap();
@@ -2915,7 +2906,7 @@ impl<'test> TestCx<'test> {
                     && line.ends_with(';')
                 {
                     if let Some(ref mut other_files) = other_files {
-                        other_files.push(line.rsplit("mod ").next().unwrap().replace(";", ""));
+                        other_files.push(line.rsplit("mod ").next().unwrap().replace(';', ""));
                     }
                     None
                 } else {
@@ -3147,7 +3138,7 @@ impl<'test> TestCx<'test> {
             let mut string = String::new();
             for cgu in cgus {
                 string.push_str(&cgu[..]);
-                string.push_str(" ");
+                string.push(' ');
             }
 
             string
@@ -3180,10 +3171,7 @@ impl<'test> TestCx<'test> {
         // CGUs joined with "--". This function splits such composite CGU names
         // and handles each component individually.
         fn remove_crate_disambiguators_from_set_of_cgu_names(cgus: &str) -> String {
-            cgus.split("--")
-                .map(|cgu| remove_crate_disambiguator_from_cgu(cgu))
-                .collect::<Vec<_>>()
-                .join("--")
+            cgus.split("--").map(remove_crate_disambiguator_from_cgu).collect::<Vec<_>>().join("--")
         }
     }
 
@@ -3365,7 +3353,7 @@ impl<'test> TestCx<'test> {
             //   endif
         }
 
-        if self.config.target.contains("msvc") && self.config.cc != "" {
+        if self.config.target.contains("msvc") && !self.config.cc.is_empty() {
             // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe`
             // and that `lib.exe` lives next to it.
             let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe");
@@ -3551,6 +3539,10 @@ impl<'test> TestCx<'test> {
             .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
             .env("LLVM_COMPONENTS", &self.config.llvm_components);
 
+        // In test code we want to be very pedantic about values being silently discarded that are
+        // annotated with `#[must_use]`.
+        cmd.arg("-Dunused_must_use");
+
         if std::env::var_os("COMPILETEST_FORCE_STAGE0").is_some() {
             let mut stage0_sysroot = build_root.clone();
             stage0_sysroot.push("stage0-sysroot");
@@ -3643,7 +3635,7 @@ impl<'test> TestCx<'test> {
             //   endif
         }
 
-        if self.config.target.contains("msvc") && self.config.cc != "" {
+        if self.config.target.contains("msvc") && !self.config.cc.is_empty() {
             // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe`
             // and that `lib.exe` lives next to it.
             let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe");
@@ -3834,7 +3826,7 @@ impl<'test> TestCx<'test> {
             && !self.props.dont_check_compiler_stderr
         {
             self.fatal_proc_rec(
-                &format!("compiler output got truncated, cannot compare with reference file"),
+                "compiler output got truncated, cannot compare with reference file",
                 &proc_res,
             );
         }
@@ -4015,8 +4007,8 @@ impl<'test> TestCx<'test> {
                     crate_name.to_str().expect("crate name implies file name must be valid UTF-8");
                 // replace `a.foo` -> `a__foo` for crate name purposes.
                 // replace `revision-name-with-dashes` -> `revision_name_with_underscore`
-                let crate_name = crate_name.replace(".", "__");
-                let crate_name = crate_name.replace("-", "_");
+                let crate_name = crate_name.replace('.', "__");
+                let crate_name = crate_name.replace('-', "_");
                 rustc.arg("--crate-name");
                 rustc.arg(crate_name);
             }
@@ -4064,7 +4056,7 @@ impl<'test> TestCx<'test> {
     fn check_mir_dump(&self, test_info: MiroptTest) {
         let test_dir = self.testpaths.file.parent().unwrap();
         let test_crate =
-            self.testpaths.file.file_stem().unwrap().to_str().unwrap().replace("-", "_");
+            self.testpaths.file.file_stem().unwrap().to_str().unwrap().replace('-', "_");
 
         let MiroptTest { run_filecheck, suffix, files, passes: _ } = test_info;
 
diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs
index 8bd7c7e808d..6ee147da5a9 100644
--- a/src/tools/compiletest/src/runtest/coverage.rs
+++ b/src/tools/compiletest/src/runtest/coverage.rs
@@ -7,7 +7,8 @@ use std::process::Command;
 use glob::glob;
 
 use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP};
-use crate::runtest::{static_regex, Emit, ProcRes, TestCx, WillExecute};
+use crate::runtest::{Emit, ProcRes, TestCx, WillExecute};
+use crate::util::static_regex;
 
 impl<'test> TestCx<'test> {
     fn coverage_dump_path(&self) -> &Path {
diff --git a/src/tools/compiletest/src/runtest/debugger.rs b/src/tools/compiletest/src/runtest/debugger.rs
index eebe5f3580b..ed6cc97a8ab 100644
--- a/src/tools/compiletest/src/runtest/debugger.rs
+++ b/src/tools/compiletest/src/runtest/debugger.rs
@@ -148,5 +148,5 @@ fn check_single_line(line: &str, check_line: &str) -> bool {
         rest = &rest[pos + current_fragment.len()..];
     }
 
-    if !can_end_anywhere && !rest.is_empty() { false } else { true }
+    can_end_anywhere || rest.is_empty()
 }
diff --git a/src/tools/compiletest/src/tests.rs b/src/tools/compiletest/src/tests.rs
index e6725dba260..4292f234adc 100644
--- a/src/tools/compiletest/src/tests.rs
+++ b/src/tools/compiletest/src/tests.rs
@@ -58,11 +58,11 @@ fn test_extract_lldb_version() {
 
 #[test]
 fn is_test_test() {
-    assert_eq!(true, is_test(&OsString::from("a_test.rs")));
-    assert_eq!(false, is_test(&OsString::from(".a_test.rs")));
-    assert_eq!(false, is_test(&OsString::from("a_cat.gif")));
-    assert_eq!(false, is_test(&OsString::from("#a_dog_gif")));
-    assert_eq!(false, is_test(&OsString::from("~a_temp_file")));
+    assert!(is_test(&OsString::from("a_test.rs")));
+    assert!(!is_test(&OsString::from(".a_test.rs")));
+    assert!(!is_test(&OsString::from("a_cat.gif")));
+    assert!(!is_test(&OsString::from("#a_dog_gif")));
+    assert!(!is_test(&OsString::from("~a_temp_file")));
 }
 
 #[test]
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index ec20bda8c18..cdec49a51d7 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -90,3 +90,11 @@ pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> std::io::Re
     }
     Ok(())
 }
+
+macro_rules! static_regex {
+    ($re:literal) => {{
+        static RE: ::std::sync::OnceLock<::regex::Regex> = ::std::sync::OnceLock::new();
+        RE.get_or_init(|| ::regex::Regex::new($re).unwrap())
+    }};
+}
+pub(crate) use static_regex;
diff --git a/src/tools/generate-windows-sys/Cargo.toml b/src/tools/generate-windows-sys/Cargo.toml
index 8b971d6efe7..ebf3082fb4f 100644
--- a/src/tools/generate-windows-sys/Cargo.toml
+++ b/src/tools/generate-windows-sys/Cargo.toml
@@ -4,4 +4,4 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies.windows-bindgen]
-version = "0.56.0"
+version = "0.57.0"
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index 5e35ce242fe..1713a4d812c 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -418,15 +418,13 @@ impl<'a> Validator<'a> {
             } else {
                 self.fail_expecting(id, expected);
             }
-        } else {
-            if !self.missing_ids.contains(id) {
-                self.missing_ids.insert(id);
+        } else if !self.missing_ids.contains(id) {
+            self.missing_ids.insert(id);
 
-                let sels = json_find::find_selector(&self.krate_json, &Value::String(id.0.clone()));
-                assert_ne!(sels.len(), 0);
+            let sels = json_find::find_selector(&self.krate_json, &Value::String(id.0.clone()));
+            assert_ne!(sels.len(), 0);
 
-                self.fail(id, ErrorKind::NotFound(sels))
-            }
+            self.fail(id, ErrorKind::NotFound(sels))
         }
     }
 
diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs
index 73f5738469e..f246d71d499 100644
--- a/src/tools/lint-docs/src/groups.rs
+++ b/src/tools/lint-docs/src/groups.rs
@@ -121,13 +121,13 @@ impl<'a> LintExtractor<'a> {
             };
             to_link.extend(group_lints);
             let brackets: Vec<_> = group_lints.iter().map(|l| format!("[{}]", l)).collect();
-            write!(result, "| {} | {} | {} |\n", group_name, description, brackets.join(", "))
+            writeln!(result, "| {} | {} | {} |", group_name, description, brackets.join(", "))
                 .unwrap();
         }
         result.push('\n');
         result.push_str("[warn-by-default]: listing/warn-by-default.md\n");
         for lint_name in to_link {
-            let lint_def = match lints.iter().find(|l| l.name == lint_name.replace("-", "_")) {
+            let lint_def = match lints.iter().find(|l| l.name == lint_name.replace('-', "_")) {
                 Some(def) => def,
                 None => {
                     let msg = format!(
@@ -144,9 +144,9 @@ impl<'a> LintExtractor<'a> {
                     }
                 }
             };
-            write!(
+            writeln!(
                 result,
-                "[{}]: listing/{}#{}\n",
+                "[{}]: listing/{}#{}",
                 lint_name,
                 lint_def.level.doc_filename(),
                 lint_name
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index c79b377727a..72d6a495e7e 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -84,8 +84,8 @@ impl Lint {
         for &expected in &["### Example", "### Explanation", "{{produces}}"] {
             if expected == "{{produces}}" && self.is_ignored() {
                 if self.doc_contains("{{produces}}") {
-                    return Err(format!(
-                        "the lint example has `ignore`, but also contains the {{{{produces}}}} marker\n\
+                    return Err(
+                        "the lint example has `ignore`, but also contains the {{produces}} marker\n\
                         \n\
                         The documentation generator cannot generate the example output when the \
                         example is ignored.\n\
@@ -111,7 +111,7 @@ impl Lint {
                         Replacing the output with the text of the example you \
                         compiled manually yourself.\n\
                         "
-                    ).into());
+                    .into());
                 }
                 continue;
             }
@@ -519,11 +519,11 @@ impl<'a> LintExtractor<'a> {
         let mut these_lints: Vec<_> = lints.iter().filter(|lint| lint.level == level).collect();
         these_lints.sort_unstable_by_key(|lint| &lint.name);
         for lint in &these_lints {
-            write!(result, "* [`{}`](#{})\n", lint.name, lint.name.replace("_", "-")).unwrap();
+            writeln!(result, "* [`{}`](#{})", lint.name, lint.name.replace('_', "-")).unwrap();
         }
         result.push('\n');
         for lint in &these_lints {
-            write!(result, "## {}\n\n", lint.name.replace("_", "-")).unwrap();
+            write!(result, "## {}\n\n", lint.name.replace('_', "-")).unwrap();
             for line in &lint.doc {
                 result.push_str(line);
                 result.push('\n');
@@ -583,7 +583,7 @@ fn add_rename_redirect(level: Level, output: &mut String) {
             let filename = level.doc_filename().replace(".md", ".html");
             output.push_str(RENAME_START);
             for (from, to) in *names {
-                write!(output, "        \"#{from}\": \"{filename}#{to}\",\n").unwrap();
+                writeln!(output, "        \"#{from}\": \"{filename}#{to}\",").unwrap();
             }
             output.push_str(RENAME_END);
         }
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index c437619a76e..4b4f2f83062 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -151,6 +151,21 @@ platform. For example `cargo miri test --target s390x-unknown-linux-gnu`
 will run your test suite on a big-endian target, which is useful for testing
 endian-sensitive code.
 
+### Testing multiple different executions
+
+Certain parts of the execution are picked randomly by Miri, such as the exact base address
+allocations are stored at and the interleaving of concurrently executing threads. Sometimes, it can
+be useful to explore multiple different execution, e.g. to make sure that your code does not depend
+on incidental "super-alignment" of new allocations and to test different thread interleavings.
+This can be done with the `--many-seeds` flag:
+
+```
+cargo miri test --many-seeds # tries the seeds in 0..64
+cargo miri test --many-seeds=0..16
+```
+
+The default of 64 different seeds is quite slow, so you probably want to specify a smaller range.
+
 ### Running Miri on CI
 
 When running Miri on CI, use the following snippet to install a nightly toolchain with the Miri
@@ -183,23 +198,6 @@ Here is an example job for GitHub Actions:
 The explicit `cargo miri setup` helps to keep the output of the actual test step
 clean.
 
-### Testing for alignment issues
-
-Miri can sometimes miss misaligned accesses since allocations can "happen to be"
-aligned just right. You can use `-Zmiri-symbolic-alignment-check` to definitely
-catch all such issues, but that flag will also cause false positives when code
-does manual pointer arithmetic to account for alignment. Another alternative is
-to call Miri with various values for `-Zmiri-seed`; that will alter the
-randomness that is used to determine allocation base addresses. The following
-snippet calls Miri in a loop with different values for the seed:
-
-```
-for SEED in $(seq 0 255); do
-  echo "Trying seed: $SEED"
-  MIRIFLAGS=-Zmiri-seed=$SEED cargo miri test || { echo "Failing seed: $SEED"; break; };
-done
-```
-
 ### Supported targets
 
 Miri does not support all targets supported by Rust. The good news, however, is
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index e2fc2a0c277..3c36f606d84 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -1,10 +1,10 @@
 //! Implements the various phases of `cargo miri run/test`.
 
-use std::env;
 use std::fs::{self, File};
-use std::io::BufReader;
+use std::io::{BufReader, Write};
 use std::path::{Path, PathBuf};
 use std::process::Command;
+use std::{env, thread};
 
 use rustc_version::VersionMeta;
 
@@ -34,6 +34,8 @@ Examples:
 
 ";
 
+const DEFAULT_MANY_SEEDS: &str = "0..64";
+
 fn show_help() {
     println!("{CARGO_MIRI_HELP}");
 }
@@ -119,7 +121,7 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
     // <https://github.com/rust-lang/miri/pull/1540#issuecomment-693553191> describes an alternative
     // approach that uses `cargo check`, making that part easier but target and binary handling
     // harder.
-    let cargo_miri_path = std::env::current_exe()
+    let cargo_miri_path = env::current_exe()
         .expect("current executable path invalid")
         .into_os_string()
         .into_string()
@@ -163,14 +165,22 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
     let target_dir = get_target_dir(&metadata);
     cmd.arg("--target-dir").arg(target_dir);
 
+    // Store many-seeds argument.
+    let mut many_seeds = None;
     // *After* we set all the flags that need setting, forward everything else. Make sure to skip
-    // `--target-dir` (which would otherwise be set twice).
+    // `--target-dir` (which would otherwise be set twice) and `--many-seeds` (which is our flag, not cargo's).
     for arg in
         ArgSplitFlagValue::from_string_iter(&mut args, "--target-dir").filter_map(Result::err)
     {
-        cmd.arg(arg);
+        if arg == "--many-seeds" {
+            many_seeds = Some(DEFAULT_MANY_SEEDS.to_owned());
+        } else if let Some(val) = arg.strip_prefix("--many-seeds=") {
+            many_seeds = Some(val.to_owned());
+        } else {
+            cmd.arg(arg);
+        }
     }
-    // Forward all further arguments (not consumed by `ArgSplitFlagValue`) to cargo.
+    // Forward all further arguments after `--` (not consumed by `ArgSplitFlagValue`) to cargo.
     cmd.args(args);
 
     // Set `RUSTC_WRAPPER` to ourselves.  Cargo will prepend that binary to its usual invocation,
@@ -222,6 +232,9 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
     // Forward some crucial information to our own re-invocations.
     cmd.env("MIRI_SYSROOT", miri_sysroot);
     cmd.env("MIRI_LOCAL_CRATES", local_crates(&metadata));
+    if let Some(many_seeds) = many_seeds {
+        cmd.env("MIRI_MANY_SEEDS", many_seeds);
+    }
     if verbose > 0 {
         cmd.env("MIRI_VERBOSE", verbose.to_string()); // This makes the other phases verbose.
     }
@@ -309,7 +322,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
         }
     }
 
-    let verbose = std::env::var("MIRI_VERBOSE")
+    let verbose = env::var("MIRI_VERBOSE")
         .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer"));
     let target_crate = is_target_crate();
 
@@ -489,7 +502,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
         // This is a host crate.
         // When we're running `cargo-miri` from `x.py` we need to pass the sysroot explicitly
         // due to bootstrap complications.
-        if let Some(sysroot) = std::env::var_os("MIRI_HOST_SYSROOT") {
+        if let Some(sysroot) = env::var_os("MIRI_HOST_SYSROOT") {
             cmd.arg("--sysroot").arg(sysroot);
         }
 
@@ -532,7 +545,7 @@ pub enum RunnerPhase {
 }
 
 pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: RunnerPhase) {
-    let verbose = std::env::var("MIRI_VERBOSE")
+    let verbose = env::var("MIRI_VERBOSE")
         .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer"));
 
     let binary = binary_args.next().unwrap();
@@ -541,6 +554,7 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
             "file {:?} not found or `cargo-miri` invoked incorrectly; please only invoke this binary through `cargo miri`", binary
         ));
     let file = BufReader::new(file);
+    let binary_args = binary_args.collect::<Vec<_>>();
 
     let info = serde_json::from_reader(file).unwrap_or_else(|_| {
         show_error!("file {:?} contains outdated or invalid JSON; try `cargo clean`", binary)
@@ -555,84 +569,114 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
         }
     };
 
-    let mut cmd = miri();
-
-    // Set missing env vars. We prefer build-time env vars over run-time ones; see
-    // <https://github.com/rust-lang/miri/issues/1661> for the kind of issue that fixes.
-    for (name, val) in info.env {
-        // `CARGO_MAKEFLAGS` contains information about how to reach the jobserver, but by the time
-        // the program is being run, that jobserver no longer exists (cargo only runs the jobserver
-        // for the build portion of `cargo run`/`cargo test`). Hence we shouldn't forward this.
-        // Also see <https://github.com/rust-lang/rust/pull/113730>.
-        if name == "CARGO_MAKEFLAGS" {
-            continue;
-        }
-        if let Some(old_val) = env::var_os(&name) {
-            if old_val == val {
-                // This one did not actually change, no need to re-set it.
-                // (This keeps the `debug_cmd` below more manageable.)
+    let many_seeds = env::var("MIRI_MANY_SEEDS");
+    run_many_seeds(many_seeds.ok(), |seed| {
+        let mut cmd = miri();
+
+        // Set missing env vars. We prefer build-time env vars over run-time ones; see
+        // <https://github.com/rust-lang/miri/issues/1661> for the kind of issue that fixes.
+        for (name, val) in &info.env {
+            // `CARGO_MAKEFLAGS` contains information about how to reach the jobserver, but by the time
+            // the program is being run, that jobserver no longer exists (cargo only runs the jobserver
+            // for the build portion of `cargo run`/`cargo test`). Hence we shouldn't forward this.
+            // Also see <https://github.com/rust-lang/rust/pull/113730>.
+            if name == "CARGO_MAKEFLAGS" {
                 continue;
-            } else if verbose > 0 {
-                eprintln!(
-                    "[cargo-miri runner] Overwriting run-time env var {name:?}={old_val:?} with build-time value {val:?}"
-                );
             }
+            if let Some(old_val) = env::var_os(name) {
+                if *old_val == *val {
+                    // This one did not actually change, no need to re-set it.
+                    // (This keeps the `debug_cmd` below more manageable.)
+                    continue;
+                } else if verbose > 0 {
+                    eprintln!(
+                        "[cargo-miri runner] Overwriting run-time env var {name:?}={old_val:?} with build-time value {val:?}"
+                    );
+                }
+            }
+            cmd.env(name, val);
         }
-        cmd.env(name, val);
-    }
 
-    if phase != RunnerPhase::Rustdoc {
-        // Set the sysroot. Not necessary in rustdoc, where we already set the sysroot in
-        // `phase_rustdoc`. rustdoc will forward that flag when invoking rustc (i.e., us), so the
-        // flag is present in `info.args`.
-        cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
-    }
-    // Forward rustc arguments.
-    // We need to patch "--extern" filenames because we forced a check-only
-    // build without cargo knowing about that: replace `.rlib` suffix by
-    // `.rmeta`.
-    // We also need to remove `--error-format` as cargo specifies that to be JSON,
-    // but when we run here, cargo does not interpret the JSON any more. `--json`
-    // then also needs to be dropped.
-    let mut args = info.args.into_iter();
-    while let Some(arg) = args.next() {
-        if arg == "--extern" {
-            forward_patched_extern_arg(&mut args, &mut cmd);
-        } else if let Some(suffix) = arg.strip_prefix("--error-format") {
-            assert!(suffix.starts_with('='));
-            // Drop this argument.
-        } else if let Some(suffix) = arg.strip_prefix("--json") {
-            assert!(suffix.starts_with('='));
-            // Drop this argument.
-        } else {
-            cmd.arg(arg);
+        if phase != RunnerPhase::Rustdoc {
+            // Set the sysroot. Not necessary in rustdoc, where we already set the sysroot in
+            // `phase_rustdoc`. rustdoc will forward that flag when invoking rustc (i.e., us), so the
+            // flag is present in `info.args`.
+            cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
+        }
+        // Forward rustc arguments.
+        // We need to patch "--extern" filenames because we forced a check-only
+        // build without cargo knowing about that: replace `.rlib` suffix by
+        // `.rmeta`.
+        // We also need to remove `--error-format` as cargo specifies that to be JSON,
+        // but when we run here, cargo does not interpret the JSON any more. `--json`
+        // then also needs to be dropped.
+        let mut args = info.args.iter();
+        while let Some(arg) = args.next() {
+            if arg == "--extern" {
+                forward_patched_extern_arg(&mut (&mut args).cloned(), &mut cmd);
+            } else if let Some(suffix) = arg.strip_prefix("--error-format") {
+                assert!(suffix.starts_with('='));
+                // Drop this argument.
+            } else if let Some(suffix) = arg.strip_prefix("--json") {
+                assert!(suffix.starts_with('='));
+                // Drop this argument.
+            } else {
+                cmd.arg(arg);
+            }
+        }
+        // Respect `MIRIFLAGS`.
+        if let Ok(a) = env::var("MIRIFLAGS") {
+            let args = flagsplit(&a);
+            cmd.args(args);
+        }
+        // Set the current seed.
+        if let Some(seed) = seed {
+            eprintln!("Trying seed: {seed}");
+            cmd.arg(format!("-Zmiri-seed={seed}"));
         }
-    }
-    // Respect `MIRIFLAGS`.
-    if let Ok(a) = env::var("MIRIFLAGS") {
-        let args = flagsplit(&a);
-        cmd.args(args);
-    }
-
-    // Then pass binary arguments.
-    cmd.arg("--");
-    cmd.args(binary_args);
-
-    // Make sure we use the build-time working directory for interpreting Miri/rustc arguments.
-    // But then we need to switch to the run-time one, which we instruct Miri to do by setting `MIRI_CWD`.
-    cmd.current_dir(info.current_dir);
-    cmd.env("MIRI_CWD", env::current_dir().unwrap());
 
-    // Run it.
-    debug_cmd("[cargo-miri runner]", verbose, &cmd);
-    match phase {
-        RunnerPhase::Rustdoc => exec_with_pipe(cmd, &info.stdin, format!("{binary}.stdin")),
-        RunnerPhase::Cargo => exec(cmd),
-    }
+        // Then pass binary arguments.
+        cmd.arg("--");
+        cmd.args(&binary_args);
+
+        // Make sure we use the build-time working directory for interpreting Miri/rustc arguments.
+        // But then we need to switch to the run-time one, which we instruct Miri to do by setting `MIRI_CWD`.
+        cmd.current_dir(&info.current_dir);
+        cmd.env("MIRI_CWD", env::current_dir().unwrap());
+
+        // Run it.
+        debug_cmd("[cargo-miri runner]", verbose, &cmd);
+
+        match phase {
+            RunnerPhase::Rustdoc => {
+                cmd.stdin(std::process::Stdio::piped());
+                let mut child = cmd.spawn().expect("failed to spawn process");
+                let child_stdin = child.stdin.take().unwrap();
+                // Write stdin in a background thread, as it may block.
+                let exit_status = thread::scope(|s| {
+                    s.spawn(|| {
+                        let mut child_stdin = child_stdin;
+                        // Ignore failure, it is most likely due to the process having terminated.
+                        let _ = child_stdin.write_all(&info.stdin);
+                    });
+                    child.wait().expect("failed to run command")
+                });
+                if !exit_status.success() {
+                    std::process::exit(exit_status.code().unwrap_or(-1));
+                }
+            }
+            RunnerPhase::Cargo => {
+                let exit_status = cmd.status().expect("failed to run command");
+                if !exit_status.success() {
+                    std::process::exit(exit_status.code().unwrap_or(-1));
+                }
+            }
+        }
+    });
 }
 
 pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
-    let verbose = std::env::var("MIRI_VERBOSE")
+    let verbose = env::var("MIRI_VERBOSE")
         .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer"));
 
     // phase_cargo_miri sets the RUSTDOC env var to ourselves, and puts a backup
@@ -681,7 +725,7 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
     cmd.arg("--cfg").arg("miri");
 
     // Make rustdoc call us back.
-    let cargo_miri_path = std::env::current_exe().expect("current executable path invalid");
+    let cargo_miri_path = env::current_exe().expect("current executable path invalid");
     cmd.arg("--test-builder").arg(&cargo_miri_path); // invoked by forwarding most arguments
     cmd.arg("--runtool").arg(&cargo_miri_path); // invoked with just a single path argument
 
diff --git a/src/tools/miri/cargo-miri/src/util.rs b/src/tools/miri/cargo-miri/src/util.rs
index f36cff1f798..5f2794e2244 100644
--- a/src/tools/miri/cargo-miri/src/util.rs
+++ b/src/tools/miri/cargo-miri/src/util.rs
@@ -171,11 +171,16 @@ where
         drop(path); // We don't need the path, we can pipe the bytes directly
         cmd.stdin(std::process::Stdio::piped());
         let mut child = cmd.spawn().expect("failed to spawn process");
-        {
-            let stdin = child.stdin.as_mut().expect("failed to open stdin");
-            stdin.write_all(input).expect("failed to write out test source");
-        }
-        let exit_status = child.wait().expect("failed to run command");
+        let child_stdin = child.stdin.take().unwrap();
+        // Write stdin in a background thread, as it may block.
+        let exit_status = std::thread::scope(|s| {
+            s.spawn(|| {
+                let mut child_stdin = child_stdin;
+                // Ignore failure, it is most likely due to the process having terminated.
+                let _ = child_stdin.write_all(input);
+            });
+            child.wait().expect("failed to run command")
+        });
         std::process::exit(exit_status.code().unwrap_or(-1))
     }
 }
@@ -317,3 +322,24 @@ pub fn clean_target_dir(meta: &Metadata) {
 
     remove_dir_all_idem(&target_dir).unwrap_or_else(|err| show_error!("{}", err))
 }
+
+/// Run `f` according to the many-seeds argument. In single-seed mode, `f` will only
+/// be called once, with `None`.
+pub fn run_many_seeds(many_seeds: Option<String>, f: impl Fn(Option<u32>)) {
+    let Some(many_seeds) = many_seeds else {
+        return f(None);
+    };
+    let (from, to) = many_seeds
+        .split_once("..")
+        .unwrap_or_else(|| show_error!("invalid format for `--many-seeds`: expected `from..to`"));
+    let from: u32 = if from.is_empty() {
+        0
+    } else {
+        from.parse().unwrap_or_else(|_| show_error!("invalid `from` in `--many-seeds=from..to"))
+    };
+    let to: u32 =
+        to.parse().unwrap_or_else(|_| show_error!("invalid `to` in `--many-seeds=from..to"));
+    for seed in from..to {
+        f(Some(seed));
+    }
+}
diff --git a/src/tools/miri/miri-script/src/main.rs b/src/tools/miri/miri-script/src/main.rs
index d436ef0c5aa..c4f0d808d93 100644
--- a/src/tools/miri/miri-script/src/main.rs
+++ b/src/tools/miri/miri-script/src/main.rs
@@ -98,7 +98,7 @@ Build miri, set up a sysroot and then run the test suite.
 Build miri, set up a sysroot and then run the driver with the given <flags>.
 (Also respects MIRIFLAGS environment variable.)
 If `--many-seeds` is present, Miri is run many times in parallel with different seeds.
-The range defaults to `0..256`.
+The range defaults to `0..64`.
 
 ./miri fmt <flags>:
 Format all sources and tests. <flags> are passed to `rustfmt`.
@@ -180,17 +180,16 @@ fn main() -> Result<()> {
                     dep = true;
                 } else if args.get_long_flag("verbose")? || args.get_short_flag('v')? {
                     verbose = true;
-                } else if let Some(val) = args.get_long_opt_with_default("many-seeds", "0..256")? {
+                } else if let Some(val) = args.get_long_opt_with_default("many-seeds", "0..64")? {
                     let (from, to) = val.split_once("..").ok_or_else(|| {
-                        anyhow!("invalid format for `--many-seeds-range`: expected `from..to`")
+                        anyhow!("invalid format for `--many-seeds`: expected `from..to`")
                     })?;
                     let from: u32 = if from.is_empty() {
                         0
                     } else {
-                        from.parse().context("invalid `from` in `--many-seeds-range=from..to")?
+                        from.parse().context("invalid `from` in `--many-seeds=from..to")?
                     };
-                    let to: u32 =
-                        to.parse().context("invalid `to` in `--many-seeds-range=from..to")?;
+                    let to: u32 = to.parse().context("invalid `to` in `--many-seeds=from..to")?;
                     many_seeds = Some(from..to);
                 } else if let Some(val) = args.get_long_opt("target")? {
                     target = Some(val);
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 0f738653b14..e49680ba75a 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-565cadb514d35e7b851540edbc172af0f606014f
+f6b4b71ef10307201b52c17b0f9dcf9557cd90ba
diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs
index 76a045c4dc1..91865a2192c 100644
--- a/src/tools/miri/src/concurrency/sync.rs
+++ b/src/tools/miri/src/concurrency/sync.rs
@@ -45,7 +45,7 @@ macro_rules! declare_id {
                 // We use 0 as a sentinel value (see the comment above) and,
                 // therefore, need to shift by one when converting from an index
                 // into a vector.
-                let shifted_idx = u32::try_from(idx).unwrap().checked_add(1).unwrap();
+                let shifted_idx = u32::try_from(idx).unwrap().strict_add(1);
                 $name(std::num::NonZero::new(shifted_idx).unwrap())
             }
             fn index(self) -> usize {
@@ -350,7 +350,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         } else {
             mutex.owner = Some(thread);
         }
-        mutex.lock_count = mutex.lock_count.checked_add(1).unwrap();
+        mutex.lock_count = mutex.lock_count.strict_add(1);
         if let Some(data_race) = &this.machine.data_race {
             data_race.acquire_clock(&mutex.clock, &this.machine.threads);
         }
@@ -370,9 +370,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 return Ok(None);
             }
             let old_lock_count = mutex.lock_count;
-            mutex.lock_count = old_lock_count
-                .checked_sub(1)
-                .expect("invariant violation: lock_count == 0 iff the thread is unlocked");
+            mutex.lock_count = old_lock_count.strict_sub(1);
             if mutex.lock_count == 0 {
                 mutex.owner = None;
                 // The mutex is completely unlocked. Try transferring ownership
@@ -450,7 +448,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         trace!("rwlock_reader_lock: {:?} now also held (one more time) by {:?}", id, thread);
         let rwlock = &mut this.machine.sync.rwlocks[id];
         let count = rwlock.readers.entry(thread).or_insert(0);
-        *count = count.checked_add(1).expect("the reader counter overflowed");
+        *count = count.strict_add(1);
         if let Some(data_race) = &this.machine.data_race {
             data_race.acquire_clock(&rwlock.clock_unlocked, &this.machine.threads);
         }
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 87b53d87ac8..843aff02495 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -7,7 +7,7 @@ use std::time::Duration;
 
 use rand::RngCore;
 
-use rustc_apfloat::ieee::{Double, Single};
+use rustc_apfloat::ieee::{Double, Half, Quad, Single};
 use rustc_apfloat::Float;
 use rustc_hir::{
     def::{DefKind, Namespace},
@@ -1201,12 +1201,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         };
 
         let (val, status) = match fty {
-            FloatTy::F16 => unimplemented!("f16_f128"),
+            FloatTy::F16 =>
+                float_to_int_inner::<Half>(this, src.to_scalar().to_f16()?, cast_to, round),
             FloatTy::F32 =>
                 float_to_int_inner::<Single>(this, src.to_scalar().to_f32()?, cast_to, round),
             FloatTy::F64 =>
                 float_to_int_inner::<Double>(this, src.to_scalar().to_f64()?, cast_to, round),
-            FloatTy::F128 => unimplemented!("f16_f128"),
+            FloatTy::F128 =>
+                float_to_int_inner::<Quad>(this, src.to_scalar().to_f128()?, cast_to, round),
         };
 
         if status.intersects(
diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs
index c3b34f0c0c6..a5afd029b65 100644
--- a/src/tools/miri/src/intrinsics/simd.rs
+++ b/src/tools/miri/src/intrinsics/simd.rs
@@ -643,10 +643,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 assert_eq!(index_len as u64, dest_len);
 
                 for i in 0..dest_len {
-                    let src_index: u64 = index[usize::try_from(i).unwrap()]
-                        .unwrap_leaf()
-                        .to_u32()
-                        .into();
+                    let src_index: u64 =
+                        index[usize::try_from(i).unwrap()].unwrap_leaf().to_u32().into();
                     let dest = this.project_index(&dest, i)?;
 
                     let val = if src_index < left_len {
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 11cbbde06aa..f8410db4dd0 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -13,6 +13,7 @@
 #![feature(lint_reasons)]
 #![feature(trait_upcasting)]
 #![feature(strict_overflow_ops)]
+#![feature(is_none_or)]
 // Configure clippy and other lints
 #![allow(
     clippy::collapsible_else_if,
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 898fc111fd4..911958e558c 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -396,12 +396,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     // If the newly promised alignment is bigger than the native alignment of this
                     // allocation, and bigger than the previously promised alignment, then set it.
                     if align > alloc_align
-                        && !this
+                        && this
                             .machine
                             .symbolic_alignment
                             .get_mut()
                             .get(&alloc_id)
-                            .is_some_and(|&(_, old_align)| align <= old_align)
+                            .is_none_or(|&(_, old_align)| align > old_align)
                     {
                         this.machine.symbolic_alignment.get_mut().insert(alloc_id, (offset, align));
                     }
diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs
index 68eca5a3a0f..533992e35ab 100644
--- a/src/tools/miri/src/shims/os_str.rs
+++ b/src/tools/miri/src/shims/os_str.rs
@@ -142,7 +142,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         os_str: &OsStr,
         memkind: MemoryKind,
     ) -> InterpResult<'tcx, Pointer> {
-        let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0` terminator.
+        let size = u64::try_from(os_str.len()).unwrap().strict_add(1); // Make space for `0` terminator.
         let this = self.eval_context_mut();
 
         let arg_type = Ty::new_array(this.tcx.tcx, this.tcx.types.u8, size);
@@ -158,7 +158,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         os_str: &OsStr,
         memkind: MemoryKind,
     ) -> InterpResult<'tcx, Pointer> {
-        let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0x0000` terminator.
+        let size = u64::try_from(os_str.len()).unwrap().strict_add(1); // Make space for `0x0000` terminator.
         let this = self.eval_context_mut();
 
         let arg_type = Ty::new_array(this.tcx.tcx, this.tcx.types.u16, size);
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index c8805f054ec..262e71756c6 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -893,7 +893,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
                 let dirent64_layout = this.libc_ty_layout("dirent64");
                 let d_name_offset = dirent64_layout.fields.offset(4 /* d_name */).bytes();
-                let size = d_name_offset.checked_add(name_len).unwrap();
+                let size = d_name_offset.strict_add(name_len);
 
                 let entry = this.allocate_ptr(
                     Size::from_bytes(size),
@@ -994,7 +994,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     name_place.ptr(),
                     name_place.layout.size.bytes(),
                 )?;
-                let file_name_len = file_name_buf_len.checked_sub(1).unwrap();
+                let file_name_len = file_name_buf_len.strict_sub(1);
                 if !name_fits {
                     throw_unsup_format!(
                         "a directory entry had a name too large to fit in libc::dirent"
diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs
index aa4dc982870..a5661460e95 100644
--- a/src/tools/miri/src/shims/unix/linux/epoll.rs
+++ b/src/tools/miri/src/shims/unix/linux/epoll.rs
@@ -57,10 +57,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let flags = this.read_scalar(flags)?.to_i32()?;
 
         let epoll_cloexec = this.eval_libc_i32("EPOLL_CLOEXEC");
-        if flags == epoll_cloexec {
-            // Miri does not support exec, so this flag has no effect.
-        } else if flags != 0 {
-            throw_unsup_format!("epoll_create1 flags {flags} are not implemented");
+
+        // Miri does not support exec, so EPOLL_CLOEXEC flag has no effect.
+        if flags != epoll_cloexec && flags != 0 {
+            throw_unsup_format!(
+                "epoll_create1: flag {:#x} is unsupported, only 0 or EPOLL_CLOEXEC are allowed",
+                flags
+            );
         }
 
         let fd = this.machine.fds.insert_fd(FileDescriptor::new(Epoll::default()));
diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs
index 97bf6348f0b..c639ea2f846 100644
--- a/src/tools/miri/src/shims/unix/socket.rs
+++ b/src/tools/miri/src/shims/unix/socket.rs
@@ -1,15 +1,38 @@
+use std::cell::RefCell;
+use std::collections::VecDeque;
 use std::io;
+use std::io::{Error, ErrorKind, Read};
+use std::rc::{Rc, Weak};
 
 use crate::shims::unix::*;
-use crate::*;
+use crate::{concurrency::VClock, *};
 
 use self::fd::FileDescriptor;
 
+/// The maximum capacity of the socketpair buffer in bytes.
+/// This number is arbitrary as the value can always
+/// be configured in the real system.
+const MAX_SOCKETPAIR_BUFFER_CAPACITY: usize = 212992;
+
 /// Pair of connected sockets.
-///
-/// We currently don't allow sending any data through this pair, so this can be just a dummy.
 #[derive(Debug)]
-struct SocketPair;
+struct SocketPair {
+    // By making the write link weak, a `write` can detect when all readers are
+    // gone, and trigger EPIPE as appropriate.
+    writebuf: Weak<RefCell<Buffer>>,
+    readbuf: Rc<RefCell<Buffer>>,
+    is_nonblock: bool,
+}
+
+#[derive(Debug)]
+struct Buffer {
+    buf: VecDeque<u8>,
+    clock: VClock,
+    /// Indicates if there is at least one active writer to this buffer.
+    /// If all writers of this buffer are dropped, buf_has_writer becomes false and we
+    /// indicate EOF instead of blocking.
+    buf_has_writer: bool,
+}
 
 impl FileDescription for SocketPair {
     fn name(&self) -> &'static str {
@@ -20,17 +43,102 @@ impl FileDescription for SocketPair {
         self: Box<Self>,
         _communicate_allowed: bool,
     ) -> InterpResult<'tcx, io::Result<()>> {
+        // This is used to signal socketfd of other side that there is no writer to its readbuf.
+        // If the upgrade fails, there is no need to update as all read ends have been dropped.
+        if let Some(writebuf) = self.writebuf.upgrade() {
+            writebuf.borrow_mut().buf_has_writer = false;
+        };
         Ok(Ok(()))
     }
+
+    fn read<'tcx>(
+        &mut self,
+        _communicate_allowed: bool,
+        bytes: &mut [u8],
+        ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx, io::Result<usize>> {
+        let request_byte_size = bytes.len();
+        let mut readbuf = self.readbuf.borrow_mut();
+
+        // Always succeed on read size 0.
+        if request_byte_size == 0 {
+            return Ok(Ok(0));
+        }
+
+        if readbuf.buf.is_empty() {
+            if !readbuf.buf_has_writer {
+                // Socketpair with no writer and empty buffer.
+                // 0 bytes successfully read indicates end-of-file.
+                return Ok(Ok(0));
+            } else {
+                if self.is_nonblock {
+                    // Non-blocking socketpair with writer and empty buffer.
+                    // https://linux.die.net/man/2/read
+                    // EAGAIN or EWOULDBLOCK can be returned for socket,
+                    // POSIX.1-2001 allows either error to be returned for this case.
+                    // Since there is no ErrorKind for EAGAIN, WouldBlock is used.
+                    return Ok(Err(Error::from(ErrorKind::WouldBlock)));
+                } else {
+                    // Blocking socketpair with writer and empty buffer.
+                    // FIXME: blocking is currently not supported
+                    throw_unsup_format!("socketpair read: blocking isn't supported yet");
+                }
+            }
+        }
+
+        // Synchronize with all previous writes to this buffer.
+        // FIXME: this over-synchronizes; a more precise approach would be to
+        // only sync with the writes whose data we will read.
+        ecx.acquire_clock(&readbuf.clock);
+        // Do full read / partial read based on the space available.
+        // Conveniently, `read` exists on `VecDeque` and has exactly the desired behavior.
+        let actual_read_size = readbuf.buf.read(bytes).unwrap();
+        return Ok(Ok(actual_read_size));
+    }
+
+    fn write<'tcx>(
+        &mut self,
+        _communicate_allowed: bool,
+        bytes: &[u8],
+        ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx, io::Result<usize>> {
+        let write_size = bytes.len();
+        // Always succeed on write size 0.
+        // ("If count is zero and fd refers to a file other than a regular file, the results are not specified.")
+        if write_size == 0 {
+            return Ok(Ok(0));
+        }
+
+        let Some(writebuf) = self.writebuf.upgrade() else {
+            // If the upgrade from Weak to Rc fails, it indicates that all read ends have been
+            // closed.
+            return Ok(Err(Error::from(ErrorKind::BrokenPipe)));
+        };
+        let mut writebuf = writebuf.borrow_mut();
+        let data_size = writebuf.buf.len();
+        let available_space = MAX_SOCKETPAIR_BUFFER_CAPACITY.checked_sub(data_size).unwrap();
+        if available_space == 0 {
+            if self.is_nonblock {
+                // Non-blocking socketpair with a full buffer.
+                return Ok(Err(Error::from(ErrorKind::WouldBlock)));
+            } else {
+                // Blocking socketpair with a full buffer.
+                throw_unsup_format!("socketpair write: blocking isn't supported yet");
+            }
+        }
+        // Remember this clock so `read` can synchronize with us.
+        if let Some(clock) = &ecx.release_clock() {
+            writebuf.clock.join(clock);
+        }
+        // Do full write / partial write based on the space available.
+        let actual_write_size = write_size.min(available_space);
+        writebuf.buf.extend(&bytes[..actual_write_size]);
+        return Ok(Ok(actual_write_size));
+    }
 }
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
-    /// Currently this function this function is a stub. Eventually we need to
-    /// properly implement an FD type for sockets and have this function create
-    /// two sockets and associated FDs such that writing to one will produce
-    /// data that can be read from the other.
-    ///
     /// For more information on the arguments see the socketpair manpage:
     /// <https://linux.die.net/man/2/socketpair>
     fn socketpair(
@@ -42,17 +150,80 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     ) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
-        let _domain = this.read_scalar(domain)?.to_i32()?;
-        let _type_ = this.read_scalar(type_)?.to_i32()?;
-        let _protocol = this.read_scalar(protocol)?.to_i32()?;
+        let domain = this.read_scalar(domain)?.to_i32()?;
+        let mut type_ = this.read_scalar(type_)?.to_i32()?;
+        let protocol = this.read_scalar(protocol)?.to_i32()?;
         let sv = this.deref_pointer(sv)?;
 
-        // FIXME: fail on unsupported inputs
+        let mut is_sock_nonblock = false;
+
+        // Parse and remove the type flags that we support. If type != 0 after removing,
+        // unsupported flags are used.
+        if type_ & this.eval_libc_i32("SOCK_STREAM") == this.eval_libc_i32("SOCK_STREAM") {
+            type_ &= !(this.eval_libc_i32("SOCK_STREAM"));
+        }
+
+        // SOCK_NONBLOCK only exists on Linux.
+        if this.tcx.sess.target.os == "linux" {
+            if type_ & this.eval_libc_i32("SOCK_NONBLOCK") == this.eval_libc_i32("SOCK_NONBLOCK") {
+                is_sock_nonblock = true;
+                type_ &= !(this.eval_libc_i32("SOCK_NONBLOCK"));
+            }
+            if type_ & this.eval_libc_i32("SOCK_CLOEXEC") == this.eval_libc_i32("SOCK_CLOEXEC") {
+                type_ &= !(this.eval_libc_i32("SOCK_CLOEXEC"));
+            }
+        }
+
+        // Fail on unsupported input.
+        // AF_UNIX and AF_LOCAL are synonyms, so we accept both in case
+        // their values differ.
+        if domain != this.eval_libc_i32("AF_UNIX") && domain != this.eval_libc_i32("AF_LOCAL") {
+            throw_unsup_format!(
+                "socketpair: domain {:#x} is unsupported, only AF_UNIX \
+                                 and AF_LOCAL are allowed",
+                domain
+            );
+        } else if type_ != 0 {
+            throw_unsup_format!(
+                "socketpair: type {:#x} is unsupported, only SOCK_STREAM, \
+                                 SOCK_CLOEXEC and SOCK_NONBLOCK are allowed",
+                type_
+            );
+        } else if protocol != 0 {
+            throw_unsup_format!(
+                "socketpair: socket protocol {protocol} is unsupported, \
+                                 only 0 is allowed",
+            );
+        }
+
+        let buffer1 = Rc::new(RefCell::new(Buffer {
+            buf: VecDeque::new(),
+            clock: VClock::default(),
+            buf_has_writer: true,
+        }));
+
+        let buffer2 = Rc::new(RefCell::new(Buffer {
+            buf: VecDeque::new(),
+            clock: VClock::default(),
+            buf_has_writer: true,
+        }));
+
+        let socketpair_0 = SocketPair {
+            writebuf: Rc::downgrade(&buffer1),
+            readbuf: Rc::clone(&buffer2),
+            is_nonblock: is_sock_nonblock,
+        };
+
+        let socketpair_1 = SocketPair {
+            writebuf: Rc::downgrade(&buffer2),
+            readbuf: Rc::clone(&buffer1),
+            is_nonblock: is_sock_nonblock,
+        };
 
         let fds = &mut this.machine.fds;
-        let sv0 = fds.insert_fd(FileDescriptor::new(SocketPair));
+        let sv0 = fds.insert_fd(FileDescriptor::new(socketpair_0));
         let sv0 = Scalar::from_int(sv0, sv.layout.size);
-        let sv1 = fds.insert_fd(FileDescriptor::new(SocketPair));
+        let sv1 = fds.insert_fd(FileDescriptor::new(socketpair_1));
         let sv1 = Scalar::from_int(sv1, sv.layout.size);
 
         this.write_scalar(sv0, &sv)?;
diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs
index 07d737e0663..0d2977b7b6f 100644
--- a/src/tools/miri/src/shims/x86/avx.rs
+++ b/src/tools/miri/src/shims/x86/avx.rs
@@ -176,8 +176,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     // of 4.
                     let chunk_base = i & !0b11;
                     let src_i = u64::from(this.read_scalar(&control)?.to_u32()? & 0b11)
-                        .checked_add(chunk_base)
-                        .unwrap();
+                        .strict_add(chunk_base);
 
                     this.copy_op(
                         &this.project_index(&data, src_i)?,
@@ -210,9 +209,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     // second instead of the first, ask Intel). To read the value from the current
                     // chunk, add the destination index truncated to a multiple of 2.
                     let chunk_base = i & !1;
-                    let src_i = ((this.read_scalar(&control)?.to_u64()? >> 1) & 1)
-                        .checked_add(chunk_base)
-                        .unwrap();
+                    let src_i =
+                        ((this.read_scalar(&control)?.to_u64()? >> 1) & 1).strict_add(chunk_base);
 
                     this.copy_op(
                         &this.project_index(&data, src_i)?,
diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs
index f2d120df21c..b71aec02166 100644
--- a/src/tools/miri/src/shims/x86/mod.rs
+++ b/src/tools/miri/src/shims/x86/mod.rs
@@ -18,6 +18,7 @@ mod sse;
 mod sse2;
 mod sse3;
 mod sse41;
+mod sse42;
 mod ssse3;
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
@@ -137,6 +138,11 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     this, link_name, abi, args, dest,
                 );
             }
+            name if name.starts_with("sse42.") => {
+                return sse42::EvalContextExt::emulate_x86_sse42_intrinsic(
+                    this, link_name, abi, args, dest,
+                );
+            }
             name if name.starts_with("aesni.") => {
                 return aesni::EvalContextExt::emulate_x86_aesni_intrinsic(
                     this, link_name, abi, args, dest,
diff --git a/src/tools/miri/src/shims/x86/sse42.rs b/src/tools/miri/src/shims/x86/sse42.rs
new file mode 100644
index 00000000000..4e50d5e5dcf
--- /dev/null
+++ b/src/tools/miri/src/shims/x86/sse42.rs
@@ -0,0 +1,500 @@
+use rustc_middle::mir;
+use rustc_middle::ty::layout::LayoutOf as _;
+use rustc_middle::ty::Ty;
+use rustc_span::Symbol;
+use rustc_target::abi::Size;
+use rustc_target::spec::abi::Abi;
+
+use crate::*;
+
+/// A bitmask constant for scrutinizing the immediate byte provided
+/// to the string comparison intrinsics. It distinuishes between
+/// 16-bit integers and 8-bit integers. See [`compare_strings`]
+/// for more details about the immediate byte.
+const USE_WORDS: u8 = 1;
+
+/// A bitmask constant for scrutinizing the immediate byte provided
+/// to the string comparison intrinsics. It distinuishes between
+/// signed integers and unsigned integers. See [`compare_strings`]
+/// for more details about the immediate byte.
+const USE_SIGNED: u8 = 2;
+
+/// The main worker for the string comparison intrinsics, where the given
+/// strings are analyzed according to the given immediate byte.
+///
+/// # Arguments
+///
+/// * `str1` - The first string argument. It is always a length 16 array of bytes
+///   or a length 8 array of two-byte words.
+/// * `str2` - The second string argument. It is always a length 16 array of bytes
+///   or a length 8 array of two-byte words.
+/// * `len` is the length values of the supplied strings. It is distinct from the operand length
+///   in that it describes how much of `str1` and `str2` will be used for the calculation and may
+///   be smaller than the array length of `str1` and `str2`. The string length is counted in bytes
+///   if using byte operands and in two-byte words when using two-byte word operands.
+///   If the value is `None`, the length of a string is determined by the first
+///   null value inside the string.
+/// * `imm` is the immediate byte argument supplied to the intrinsic. The byte influences
+///   the operation as follows:
+///
+///   ```text
+///   0babccddef
+///     || | |||- Use of bytes vs use of two-byte words inside the operation.
+///     || | ||
+///     || | ||- Use of signed values versus use of unsigned values.
+///     || | |
+///     || | |- The comparison operation performed. A total of four operations are available.
+///     || |    * Equal any: Checks which characters of `str2` are inside `str1`.
+///     || |    * String ranges: Check if characters in `str2` are inside the provided character ranges.
+///     || |      Adjacent characters in `str1` constitute one range.
+///     || |    * String comparison: Mark positions where `str1` and `str2` have the same character.
+///     || |    * Substring search: Mark positions where `str1` is a substring in `str2`.
+///     || |
+///     || |- Result Polarity. The result bits may be subjected to a bitwise complement
+///     ||    if these bits are set.
+///     ||
+///     ||- Output selection. This bit has two meanings depending on the instruction.
+///     |   If the instruction is generating a mask, it distinguishes between a bit mask
+///     |   and a byte mask. Otherwise it distinguishes between the most significand bit
+///     |   and the least significand bit when generating an index.
+///     |
+///     |- This bit is ignored. It is expected that this bit is set to zero, but it is
+///        not a requirement.
+///   ```
+///
+/// # Returns
+///
+/// A result mask. The bit at index `i` inside the mask is set if 'str2' starting at `i`
+/// fulfills the test as defined inside the immediate byte.
+/// The mask may be negated if negation flags inside the immediate byte are set.
+///
+/// For more information, see the Intel Software Developer's Manual, Vol. 2b, Chapter 4.1.
+#[allow(clippy::arithmetic_side_effects)]
+fn compare_strings<'tcx>(
+    this: &mut MiriInterpCx<'tcx>,
+    str1: &OpTy<'tcx>,
+    str2: &OpTy<'tcx>,
+    len: Option<(u64, u64)>,
+    imm: u8,
+) -> InterpResult<'tcx, i32> {
+    let default_len = default_len::<u64>(imm);
+    let (len1, len2) = if let Some(t) = len {
+        t
+    } else {
+        let len1 = implicit_len(this, str1, imm)?.unwrap_or(default_len);
+        let len2 = implicit_len(this, str2, imm)?.unwrap_or(default_len);
+        (len1, len2)
+    };
+
+    let mut result = 0;
+    match (imm >> 2) & 3 {
+        0 => {
+            // Equal any: Checks which characters of `str2` are inside `str1`.
+            for i in 0..len2 {
+                let ch2 = this.read_immediate(&this.project_index(str2, i)?)?;
+
+                for j in 0..len1 {
+                    let ch1 = this.read_immediate(&this.project_index(str1, j)?)?;
+
+                    let eq = this.binary_op(mir::BinOp::Eq, &ch1, &ch2)?;
+                    if eq.to_scalar().to_bool()? {
+                        result |= 1 << i;
+                        break;
+                    }
+                }
+            }
+        }
+        1 => {
+            // String ranges: Check if characters in `str2` are inside the provided character ranges.
+            // Adjacent characters in `str1` constitute one range.
+            let len1 = len1 - (len1 & 1);
+            let get_ch = |ch: Scalar| -> InterpResult<'tcx, i32> {
+                let result = match (imm & USE_WORDS != 0, imm & USE_SIGNED != 0) {
+                    (true, true) => i32::from(ch.to_i16()?),
+                    (true, false) => i32::from(ch.to_u16()?),
+                    (false, true) => i32::from(ch.to_i8()?),
+                    (false, false) => i32::from(ch.to_u8()?),
+                };
+                Ok(result)
+            };
+
+            for i in 0..len2 {
+                for j in (0..len1).step_by(2) {
+                    let ch2 = get_ch(this.read_scalar(&this.project_index(str2, i)?)?)?;
+                    let ch1_1 = get_ch(this.read_scalar(&this.project_index(str1, j)?)?)?;
+                    let ch1_2 = get_ch(this.read_scalar(&this.project_index(str1, j + 1)?)?)?;
+
+                    if ch1_1 <= ch2 && ch2 <= ch1_2 {
+                        result |= 1 << i;
+                    }
+                }
+            }
+        }
+        2 => {
+            // String comparison: Mark positions where `str1` and `str2` have the same character.
+            result = (1 << default_len) - 1;
+            result ^= (1 << len1.max(len2)) - 1;
+
+            for i in 0..len1.min(len2) {
+                let ch1 = this.read_immediate(&this.project_index(str1, i)?)?;
+                let ch2 = this.read_immediate(&this.project_index(str2, i)?)?;
+                let eq = this.binary_op(mir::BinOp::Eq, &ch1, &ch2)?;
+                result |= i32::from(eq.to_scalar().to_bool()?) << i;
+            }
+        }
+        3 => {
+            // Substring search: Mark positions where `str1` is a substring in `str2`.
+            if len1 == 0 {
+                result = (1 << default_len) - 1;
+            } else if len1 <= len2 {
+                for i in 0..len2 {
+                    if len1 > len2 - i {
+                        break;
+                    }
+
+                    result |= 1 << i;
+
+                    for j in 0..len1 {
+                        let k = i + j;
+
+                        if k >= default_len {
+                            break;
+                        } else {
+                            let ch1 = this.read_immediate(&this.project_index(str1, j)?)?;
+                            let ch2 = this.read_immediate(&this.project_index(str2, k)?)?;
+                            let ne = this.binary_op(mir::BinOp::Ne, &ch1, &ch2)?;
+
+                            if ne.to_scalar().to_bool()? {
+                                result &= !(1 << i);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        _ => unreachable!(),
+    }
+
+    // Polarity: Possibly perform a bitwise complement on the result.
+    match (imm >> 4) & 3 {
+        3 => result ^= (1 << len1) - 1,
+        1 => result ^= (1 << default_len) - 1,
+        _ => (),
+    }
+
+    Ok(result)
+}
+
+/// Obtain the arguments of the intrinsic based on its name.
+/// The result is a tuple with the following values:
+/// * The first string argument.
+/// * The second string argument.
+/// * The string length values, if the intrinsic requires them.
+/// * The immediate instruction byte.
+///
+/// The string arguments will be transmuted into arrays of bytes
+/// or two-byte words, depending on the value of the immediate byte.
+/// Originally, they are [__m128i](https://doc.rust-lang.org/stable/core/arch/x86_64/struct.__m128i.html) values
+/// corresponding to the x86 128-bit integer SIMD type.
+fn deconstruct_args<'tcx>(
+    unprefixed_name: &str,
+    this: &mut MiriInterpCx<'tcx>,
+    link_name: Symbol,
+    abi: Abi,
+    args: &[OpTy<'tcx>],
+) -> InterpResult<'tcx, (OpTy<'tcx>, OpTy<'tcx>, Option<(u64, u64)>, u8)> {
+    let array_layout_fn = |this: &mut MiriInterpCx<'tcx>, imm: u8| {
+        if imm & USE_WORDS != 0 {
+            this.layout_of(Ty::new_array(this.tcx.tcx, this.tcx.types.u16, 8))
+        } else {
+            this.layout_of(Ty::new_array(this.tcx.tcx, this.tcx.types.u8, 16))
+        }
+    };
+
+    // The fourth letter of each string comparison intrinsic is either 'e' for "explicit" or 'i' for "implicit".
+    // The distinction will correspond to the intrinsics type signature. In this constext, "explicit" and "implicit"
+    // refer to the way the string length is determined. The length is either passed explicitly in the "explicit"
+    // case or determined by a null terminator in the "implicit" case.
+    let is_explicit = match unprefixed_name.as_bytes().get(4) {
+        Some(&b'e') => true,
+        Some(&b'i') => false,
+        _ => unreachable!(),
+    };
+
+    if is_explicit {
+        let [str1, len1, str2, len2, imm] =
+            this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+        let imm = this.read_scalar(imm)?.to_u8()?;
+
+        let default_len = default_len::<u32>(imm);
+        let len1 = u64::from(this.read_scalar(len1)?.to_u32()?.min(default_len));
+        let len2 = u64::from(this.read_scalar(len2)?.to_u32()?.min(default_len));
+
+        let array_layout = array_layout_fn(this, imm)?;
+        let str1 = str1.transmute(array_layout, this)?;
+        let str2 = str2.transmute(array_layout, this)?;
+
+        Ok((str1, str2, Some((len1, len2)), imm))
+    } else {
+        let [str1, str2, imm] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+        let imm = this.read_scalar(imm)?.to_u8()?;
+
+        let array_layout = array_layout_fn(this, imm)?;
+        let str1 = str1.transmute(array_layout, this)?;
+        let str2 = str2.transmute(array_layout, this)?;
+
+        Ok((str1, str2, None, imm))
+    }
+}
+
+/// Calculate the c-style string length for a given string `str`.
+/// The string is either a length 16 array of bytes a length 8 array of two-byte words.
+fn implicit_len<'tcx>(
+    this: &mut MiriInterpCx<'tcx>,
+    str: &OpTy<'tcx>,
+    imm: u8,
+) -> InterpResult<'tcx, Option<u64>> {
+    let mut result = None;
+    let zero = ImmTy::from_int(0, str.layout.field(this, 0));
+
+    for i in 0..default_len::<u64>(imm) {
+        let ch = this.read_immediate(&this.project_index(str, i)?)?;
+        let is_zero = this.binary_op(mir::BinOp::Eq, &ch, &zero)?;
+        if is_zero.to_scalar().to_bool()? {
+            result = Some(i);
+            break;
+        }
+    }
+    Ok(result)
+}
+
+#[inline]
+fn default_len<T: From<u8>>(imm: u8) -> T {
+    if imm & USE_WORDS != 0 { T::from(8u8) } else { T::from(16u8) }
+}
+
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
+    fn emulate_x86_sse42_intrinsic(
+        &mut self,
+        link_name: Symbol,
+        abi: Abi,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
+    ) -> InterpResult<'tcx, EmulateItemResult> {
+        let this = self.eval_context_mut();
+        this.expect_target_feature_for_intrinsic(link_name, "sse4.2")?;
+        // Prefix should have already been checked.
+        let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse42.").unwrap();
+
+        match unprefixed_name {
+            // Used to implement the `_mm_cmpestrm` and the `_mm_cmpistrm` functions.
+            // These functions compare the input strings and return the resulting mask.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=1044,922
+            "pcmpistrm128" | "pcmpestrm128" => {
+                let (str1, str2, len, imm) =
+                    deconstruct_args(unprefixed_name, this, link_name, abi, args)?;
+                let mask = compare_strings(this, &str1, &str2, len, imm)?;
+
+                // The sixth bit inside the immediate byte distiguishes
+                // between a bit mask or a byte mask when generating a mask.
+                if imm & 0b100_0000 != 0 {
+                    let (array_layout, size) = if imm & USE_WORDS != 0 {
+                        (this.layout_of(Ty::new_array(this.tcx.tcx, this.tcx.types.u16, 8))?, 2)
+                    } else {
+                        (this.layout_of(Ty::new_array(this.tcx.tcx, this.tcx.types.u8, 16))?, 1)
+                    };
+                    let size = Size::from_bytes(size);
+                    let dest = dest.transmute(array_layout, this)?;
+
+                    for i in 0..default_len::<u64>(imm) {
+                        let result = helpers::bool_to_simd_element(mask & (1 << i) != 0, size);
+                        this.write_scalar(result, &this.project_index(&dest, i)?)?;
+                    }
+                } else {
+                    let layout = this.layout_of(this.tcx.types.i128)?;
+                    let dest = dest.transmute(layout, this)?;
+                    this.write_scalar(Scalar::from_i128(i128::from(mask)), &dest)?;
+                }
+            }
+
+            // Used to implement the `_mm_cmpestra` and the `_mm_cmpistra` functions.
+            // These functions compare the input strings and return `1` if the end of the second
+            // input string is not reached and the resulting mask is zero, and `0` otherwise.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=919,1041
+            "pcmpistria128" | "pcmpestria128" => {
+                let (str1, str2, len, imm) =
+                    deconstruct_args(unprefixed_name, this, link_name, abi, args)?;
+                let result = if compare_strings(this, &str1, &str2, len, imm)? != 0 {
+                    false
+                } else if let Some((_, len)) = len {
+                    len >= default_len::<u64>(imm)
+                } else {
+                    implicit_len(this, &str1, imm)?.is_some()
+                };
+
+                this.write_scalar(Scalar::from_i32(i32::from(result)), dest)?;
+            }
+
+            // Used to implement the `_mm_cmpestri` and the `_mm_cmpistri` functions.
+            // These functions compare the input strings and return the bit index
+            // for most significant or least significant bit of the resulting mask.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=921,1043
+            "pcmpistri128" | "pcmpestri128" => {
+                let (str1, str2, len, imm) =
+                    deconstruct_args(unprefixed_name, this, link_name, abi, args)?;
+                let mask = compare_strings(this, &str1, &str2, len, imm)?;
+
+                let len = default_len::<u32>(imm);
+                // The sixth bit inside the immediate byte distiguishes between the least
+                // significant bit and the most significant bit when generating an index.
+                let result = if imm & 0b100_0000 != 0 {
+                    // most significant bit
+                    31u32.wrapping_sub(mask.leading_zeros()).min(len)
+                } else {
+                    // least significant bit
+                    mask.trailing_zeros().min(len)
+                };
+                this.write_scalar(Scalar::from_i32(i32::try_from(result).unwrap()), dest)?;
+            }
+
+            // Used to implement the `_mm_cmpestro` and the `_mm_cmpistro` functions.
+            // These functions compare the input strings and return the lowest bit of the
+            // resulting mask.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=923,1045
+            "pcmpistrio128" | "pcmpestrio128" => {
+                let (str1, str2, len, imm) =
+                    deconstruct_args(unprefixed_name, this, link_name, abi, args)?;
+                let mask = compare_strings(this, &str1, &str2, len, imm)?;
+                this.write_scalar(Scalar::from_i32(mask & 1), dest)?;
+            }
+
+            // Used to implement the `_mm_cmpestrc` and the `_mm_cmpistrc` functions.
+            // These functions compare the input strings and return `1` if the resulting
+            // mask was non-zero, and `0` otherwise.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=920,1042
+            "pcmpistric128" | "pcmpestric128" => {
+                let (str1, str2, len, imm) =
+                    deconstruct_args(unprefixed_name, this, link_name, abi, args)?;
+                let mask = compare_strings(this, &str1, &str2, len, imm)?;
+                this.write_scalar(Scalar::from_i32(i32::from(mask != 0)), dest)?;
+            }
+
+            // Used to implement the `_mm_cmpistrz` and the `_mm_cmpistrs` functions.
+            // These functions return `1` if the string end has been reached and `0` otherwise.
+            // Since these functions define the string length implicitly, it is equal to a
+            // search for a null terminator (see `deconstruct_args` for more details).
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=924,925
+            "pcmpistriz128" | "pcmpistris128" => {
+                let [str1, str2, imm] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let imm = this.read_scalar(imm)?.to_u8()?;
+
+                let str = if unprefixed_name == "pcmpistris128" { str1 } else { str2 };
+                let array_layout = if imm & USE_WORDS != 0 {
+                    this.layout_of(Ty::new_array(this.tcx.tcx, this.tcx.types.u16, 8))?
+                } else {
+                    this.layout_of(Ty::new_array(this.tcx.tcx, this.tcx.types.u8, 16))?
+                };
+                let str = str.transmute(array_layout, this)?;
+                let result = implicit_len(this, &str, imm)?.is_some();
+
+                this.write_scalar(Scalar::from_i32(i32::from(result)), dest)?;
+            }
+
+            // Used to implement the `_mm_cmpestrz` and the `_mm_cmpestrs` functions.
+            // These functions return 1 if the explicitly passed string length is smaller
+            // than 16 for byte-sized operands or 8 for word-sized operands.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=1046,1047
+            "pcmpestriz128" | "pcmpestris128" => {
+                let [_, len1, _, len2, imm] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let len = if unprefixed_name == "pcmpestris128" { len1 } else { len2 };
+                let len = this.read_scalar(len)?.to_i32()?;
+                let imm = this.read_scalar(imm)?.to_u8()?;
+                this.write_scalar(
+                    Scalar::from_i32(i32::from(len < default_len::<i32>(imm))),
+                    dest,
+                )?;
+            }
+
+            // Used to implement the `_mm_crc32_u{8, 16, 32, 64}` functions.
+            // These functions calculate a 32-bit CRC using `0x11EDC6F41`
+            // as the polynomial, also known as CRC32C.
+            // https://datatracker.ietf.org/doc/html/rfc3720#section-12.1
+            "crc32.32.8" | "crc32.32.16" | "crc32.32.32" | "crc32.64.64" => {
+                let bit_size = match unprefixed_name {
+                    "crc32.32.8" => 8,
+                    "crc32.32.16" => 16,
+                    "crc32.32.32" => 32,
+                    "crc32.64.64" => 64,
+                    _ => unreachable!(),
+                };
+
+                if bit_size == 64 && this.tcx.sess.target.arch != "x86_64" {
+                    return Ok(EmulateItemResult::NotSupported);
+                }
+
+                let [left, right] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let left = this.read_scalar(left)?;
+                let right = this.read_scalar(right)?;
+
+                let crc = if bit_size == 64 {
+                    // The 64-bit version will only consider the lower 32 bits,
+                    // while the upper 32 bits get discarded.
+                    #[allow(clippy::cast_possible_truncation)]
+                    u128::from((left.to_u64()? as u32).reverse_bits())
+                } else {
+                    u128::from(left.to_u32()?.reverse_bits())
+                };
+                let v = match bit_size {
+                    8 => u128::from(right.to_u8()?.reverse_bits()),
+                    16 => u128::from(right.to_u16()?.reverse_bits()),
+                    32 => u128::from(right.to_u32()?.reverse_bits()),
+                    64 => u128::from(right.to_u64()?.reverse_bits()),
+                    _ => unreachable!(),
+                };
+
+                // Perform polynomial division modulo 2.
+                // The algorithm for the division is an adapted version of the
+                // schoolbook division algorithm used for normal integer or polynomial
+                // division. In this context, the quotient is not calculated, since
+                // only the remainder is needed.
+                //
+                // The algorithm works as follows:
+                // 1. Pull down digits until division can be performed. In the context of division
+                //    modulo 2 it means locating the most significant digit of the dividend and shifting
+                //    the divisor such that the position of the divisors most significand digit and the
+                //    dividends most significand digit match.
+                // 2. Perform a division and determine the remainder. Since it is arithmetic modulo 2,
+                //    this operation is a simple bitwise exclusive or.
+                // 3. Repeat steps 1. and 2. until the full remainder is calculated. This is the case
+                //    once the degree of the remainder polynomial is smaller than the degree of the
+                //    divisor polynomial. In other words, the number of leading zeros of the remainder
+                //    is larger than the number of leading zeros of the divisor. It is important to
+                //    note that standard arithmetic comparison is not applicable here:
+                //    0b10011 / 0b11111 = 0b01100 is a valid division, even though the dividend is
+                //    smaller than the divisor.
+                let mut dividend = (crc << bit_size) ^ (v << 32);
+                const POLYNOMIAL: u128 = 0x11EDC6F41;
+                while dividend.leading_zeros() <= POLYNOMIAL.leading_zeros() {
+                    dividend ^=
+                        (POLYNOMIAL << POLYNOMIAL.leading_zeros()) >> dividend.leading_zeros();
+                }
+
+                let result = u32::try_from(dividend).unwrap().reverse_bits();
+                let result = if bit_size == 64 {
+                    Scalar::from_u64(u64::from(result))
+                } else {
+                    Scalar::from_u32(result)
+                };
+
+                this.write_scalar(result, dest)?;
+            }
+            _ => return Ok(EmulateItemResult::NotSupported),
+        }
+        Ok(EmulateItemResult::NeedsReturn)
+    }
+}
diff --git a/src/tools/miri/tests/fail-dep/libc/socketpair_read_blocking.rs b/src/tools/miri/tests/fail-dep/libc/socketpair_read_blocking.rs
new file mode 100644
index 00000000000..c28a6d966fe
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/libc/socketpair_read_blocking.rs
@@ -0,0 +1,12 @@
+//@ignore-target-windows: no libc socketpair on Windows
+
+// This is temporarily here because blocking on fd is not supported yet.
+// When blocking is eventually supported, this will be moved to pass-dep/libc/libc-socketpair
+
+fn main() {
+    let mut fds = [-1, -1];
+    let _ = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
+    // The read below will be blocked because the buffer is empty.
+    let mut buf: [u8; 3] = [0; 3];
+    let _res = unsafe { libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; //~ERROR: blocking isn't supported
+}
diff --git a/src/tools/miri/tests/fail-dep/libc/socketpair_read_blocking.stderr b/src/tools/miri/tests/fail-dep/libc/socketpair_read_blocking.stderr
new file mode 100644
index 00000000000..b5ed72d9f1b
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/libc/socketpair_read_blocking.stderr
@@ -0,0 +1,14 @@
+error: unsupported operation: socketpair read: blocking isn't supported yet
+  --> $DIR/socketpair_read_blocking.rs:LL:CC
+   |
+LL |     let _res = unsafe { libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) };
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ socketpair read: blocking isn't supported yet
+   |
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/socketpair_read_blocking.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail-dep/libc/socketpair_write_blocking.rs b/src/tools/miri/tests/fail-dep/libc/socketpair_write_blocking.rs
new file mode 100644
index 00000000000..e2fbc0ae4b4
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/libc/socketpair_write_blocking.rs
@@ -0,0 +1,16 @@
+//@ignore-target-windows: no libc socketpair on Windows
+// This is temporarily here because blocking on fd is not supported yet.
+// When blocking is eventually supported, this will be moved to pass-dep/libc/libc-socketpair
+fn main() {
+    let mut fds = [-1, -1];
+    let _ = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
+    // Write size > buffer capacity
+    // Used up all the space in the buffer.
+    let arr1: [u8; 212992] = [1; 212992];
+    let _ = unsafe { libc::write(fds[0], arr1.as_ptr() as *const libc::c_void, 212992) };
+    let data = "abc".as_bytes().as_ptr();
+    // The write below will be blocked as the buffer is full.
+    let _ = unsafe { libc::write(fds[0], data as *const libc::c_void, 3) }; //~ERROR: blocking isn't supported
+    let mut buf: [u8; 3] = [0; 3];
+    let _res = unsafe { libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) };
+}
diff --git a/src/tools/miri/tests/fail-dep/libc/socketpair_write_blocking.stderr b/src/tools/miri/tests/fail-dep/libc/socketpair_write_blocking.stderr
new file mode 100644
index 00000000000..7b3a0d27636
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/libc/socketpair_write_blocking.stderr
@@ -0,0 +1,14 @@
+error: unsupported operation: socketpair write: blocking isn't supported yet
+  --> $DIR/socketpair_write_blocking.rs:LL:CC
+   |
+LL |     let _ = unsafe { libc::write(fds[0], data as *const libc::c_void, 3) };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ socketpair write: blocking isn't supported yet
+   |
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/socketpair_write_blocking.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/validity/invalid_enum_cast.rs b/src/tools/miri/tests/fail/validity/invalid_enum_cast.rs
index faf5fb699a6..ed451a435b9 100644
--- a/src/tools/miri/tests/fail/validity/invalid_enum_cast.rs
+++ b/src/tools/miri/tests/fail/validity/invalid_enum_cast.rs
@@ -3,11 +3,17 @@
 
 #[derive(Copy, Clone)]
 #[allow(unused)]
-enum E {A, B, C }
+enum E {
+    A,
+    B,
+    C,
+}
 
-fn cast(ptr: *const E) { unsafe {
-    let _val = *ptr as u32; //~ERROR: enum value has invalid tag
-}}
+fn cast(ptr: *const E) {
+    unsafe {
+        let _val = *ptr as u32; //~ERROR: enum value has invalid tag
+    }
+}
 
 pub fn main() {
     let v = u32::MAX;
diff --git a/src/tools/miri/tests/fail/validity/invalid_enum_cast.stderr b/src/tools/miri/tests/fail/validity/invalid_enum_cast.stderr
index d8988876045..30afb5e8087 100644
--- a/src/tools/miri/tests/fail/validity/invalid_enum_cast.stderr
+++ b/src/tools/miri/tests/fail/validity/invalid_enum_cast.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: enum value has invalid tag: 0xff
   --> $DIR/invalid_enum_cast.rs:LL:CC
    |
-LL |     let _val = *ptr as u32;
-   |                ^^^^^^^^^^^ enum value has invalid tag: 0xff
+LL |         let _val = *ptr as u32;
+   |                    ^^^^^^^^^^^ enum value has invalid tag: 0xff
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs
new file mode 100644
index 00000000000..324c0127ee9
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs
@@ -0,0 +1,124 @@
+//@ignore-target-windows: No libc socketpair on Windows
+// test_race depends on a deterministic schedule.
+//@compile-flags: -Zmiri-preemption-rate=0
+use std::thread;
+fn main() {
+    test_socketpair();
+    test_socketpair_threaded();
+    test_race();
+}
+
+fn test_socketpair() {
+    let mut fds = [-1, -1];
+    let mut res =
+        unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
+    assert_eq!(res, 0);
+
+    // Read size == data available in buffer.
+    let data = "abcde".as_bytes().as_ptr();
+    res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() };
+    assert_eq!(res, 5);
+    let mut buf: [u8; 5] = [0; 5];
+    res = unsafe {
+        libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap()
+    };
+    assert_eq!(res, 5);
+    assert_eq!(buf, "abcde".as_bytes());
+
+    // Read size > data available in buffer.
+    let data = "abc".as_bytes().as_ptr();
+    res = unsafe { libc::write(fds[0], data as *const libc::c_void, 3).try_into().unwrap() };
+    assert_eq!(res, 3);
+    let mut buf2: [u8; 5] = [0; 5];
+    res = unsafe {
+        libc::read(fds[1], buf2.as_mut_ptr().cast(), buf2.len() as libc::size_t).try_into().unwrap()
+    };
+    assert_eq!(res, 3);
+    assert_eq!(&buf2[0..3], "abc".as_bytes());
+
+    // Test read and write from another direction.
+    // Read size == data available in buffer.
+    let data = "12345".as_bytes().as_ptr();
+    res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5).try_into().unwrap() };
+    assert_eq!(res, 5);
+    let mut buf3: [u8; 5] = [0; 5];
+    res = unsafe {
+        libc::read(fds[0], buf3.as_mut_ptr().cast(), buf3.len() as libc::size_t).try_into().unwrap()
+    };
+    assert_eq!(res, 5);
+    assert_eq!(buf3, "12345".as_bytes());
+
+    // Read size > data available in buffer.
+    let data = "123".as_bytes().as_ptr();
+    res = unsafe { libc::write(fds[1], data as *const libc::c_void, 3).try_into().unwrap() };
+    assert_eq!(res, 3);
+    let mut buf4: [u8; 5] = [0; 5];
+    res = unsafe {
+        libc::read(fds[0], buf4.as_mut_ptr().cast(), buf4.len() as libc::size_t).try_into().unwrap()
+    };
+    assert_eq!(res, 3);
+    assert_eq!(&buf4[0..3], "123".as_bytes());
+}
+
+fn test_socketpair_threaded() {
+    let mut fds = [-1, -1];
+    let mut res =
+        unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
+    assert_eq!(res, 0);
+
+    let data = "abcde".as_bytes().as_ptr();
+    res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() };
+    assert_eq!(res, 5);
+    let thread1 = thread::spawn(move || {
+        let mut buf: [u8; 5] = [0; 5];
+        let res: i64 = unsafe {
+            libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t)
+                .try_into()
+                .unwrap()
+        };
+        assert_eq!(res, 5);
+        assert_eq!(buf, "abcde".as_bytes());
+    });
+    thread1.join().unwrap();
+
+    // Read and write from different direction
+    let thread2 = thread::spawn(move || {
+        let data = "12345".as_bytes().as_ptr();
+        let res: i64 =
+            unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() };
+        assert_eq!(res, 5);
+    });
+    thread2.join().unwrap();
+    let mut buf: [u8; 5] = [0; 5];
+    res = unsafe {
+        libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap()
+    };
+    assert_eq!(res, 5);
+    assert_eq!(buf, "12345".as_bytes());
+}
+fn test_race() {
+    static mut VAL: u8 = 0;
+    let mut fds = [-1, -1];
+    let mut res =
+        unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
+    assert_eq!(res, 0);
+    let thread1 = thread::spawn(move || {
+        let mut buf: [u8; 1] = [0; 1];
+        // write() from the main thread will occur before the read() here
+        // because preemption is disabled and the main thread yields after write().
+        let res: i32 = unsafe {
+            libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t)
+                .try_into()
+                .unwrap()
+        };
+        assert_eq!(res, 1);
+        assert_eq!(buf, "a".as_bytes());
+        unsafe { assert_eq!(VAL, 1) };
+    });
+    unsafe { VAL = 1 };
+    let data = "a".as_bytes().as_ptr();
+    res = unsafe { libc::write(fds[0], data as *const libc::c_void, 1).try_into().unwrap() };
+    assert_eq!(res, 1);
+    thread::yield_now();
+    thread1.join().unwrap();
+}
diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs
index 8aea9b3e6f9..5464627fa14 100644
--- a/src/tools/miri/tests/pass/float.rs
+++ b/src/tools/miri/tests/pass/float.rs
@@ -1,6 +1,8 @@
 #![feature(stmt_expr_attributes)]
 #![feature(float_gamma)]
 #![feature(core_intrinsics)]
+#![feature(f128)]
+#![feature(f16)]
 #![allow(arithmetic_overflow)]
 
 use std::fmt::Debug;
@@ -41,103 +43,23 @@ trait FloatToInt<Int>: Copy {
     unsafe fn cast_unchecked(self) -> Int;
 }
 
-impl FloatToInt<i8> for f32 {
-    fn cast(self) -> i8 {
-        self as _
-    }
-    unsafe fn cast_unchecked(self) -> i8 {
-        self.to_int_unchecked()
-    }
-}
-impl FloatToInt<i32> for f32 {
-    fn cast(self) -> i32 {
-        self as _
-    }
-    unsafe fn cast_unchecked(self) -> i32 {
-        self.to_int_unchecked()
-    }
-}
-impl FloatToInt<u32> for f32 {
-    fn cast(self) -> u32 {
-        self as _
-    }
-    unsafe fn cast_unchecked(self) -> u32 {
-        self.to_int_unchecked()
-    }
-}
-impl FloatToInt<i64> for f32 {
-    fn cast(self) -> i64 {
-        self as _
-    }
-    unsafe fn cast_unchecked(self) -> i64 {
-        self.to_int_unchecked()
-    }
-}
-impl FloatToInt<u64> for f32 {
-    fn cast(self) -> u64 {
-        self as _
-    }
-    unsafe fn cast_unchecked(self) -> u64 {
-        self.to_int_unchecked()
-    }
+macro_rules! float_to_int {
+    ($fty:ty => $($ity:ty),+ $(,)?) => {
+        $(
+            impl FloatToInt<$ity> for $fty {
+                fn cast(self) -> $ity {
+                    self as _
+                }
+                unsafe fn cast_unchecked(self) -> $ity {
+                    self.to_int_unchecked()
+                }
+            }
+        )*
+    };
 }
 
-impl FloatToInt<i8> for f64 {
-    fn cast(self) -> i8 {
-        self as _
-    }
-    unsafe fn cast_unchecked(self) -> i8 {
-        self.to_int_unchecked()
-    }
-}
-impl FloatToInt<i32> for f64 {
-    fn cast(self) -> i32 {
-        self as _
-    }
-    unsafe fn cast_unchecked(self) -> i32 {
-        self.to_int_unchecked()
-    }
-}
-impl FloatToInt<u32> for f64 {
-    fn cast(self) -> u32 {
-        self as _
-    }
-    unsafe fn cast_unchecked(self) -> u32 {
-        self.to_int_unchecked()
-    }
-}
-impl FloatToInt<i64> for f64 {
-    fn cast(self) -> i64 {
-        self as _
-    }
-    unsafe fn cast_unchecked(self) -> i64 {
-        self.to_int_unchecked()
-    }
-}
-impl FloatToInt<u64> for f64 {
-    fn cast(self) -> u64 {
-        self as _
-    }
-    unsafe fn cast_unchecked(self) -> u64 {
-        self.to_int_unchecked()
-    }
-}
-impl FloatToInt<i128> for f64 {
-    fn cast(self) -> i128 {
-        self as _
-    }
-    unsafe fn cast_unchecked(self) -> i128 {
-        self.to_int_unchecked()
-    }
-}
-impl FloatToInt<u128> for f64 {
-    fn cast(self) -> u128 {
-        self as _
-    }
-    unsafe fn cast_unchecked(self) -> u128 {
-        self.to_int_unchecked()
-    }
-}
+float_to_int!(f32 => i8, u8, i16, u16, i32, u32, i64, u64, i128, u128);
+float_to_int!(f64 => i8, u8, i16, u16, i32, u32, i64, u64, i128, u128);
 
 /// Test this cast both via `as` and via `approx_unchecked` (i.e., it must not saturate).
 #[track_caller]
@@ -153,18 +75,29 @@ where
 
 fn basic() {
     // basic arithmetic
+    assert_eq(6.0_f16 * 6.0_f16, 36.0_f16);
     assert_eq(6.0_f32 * 6.0_f32, 36.0_f32);
     assert_eq(6.0_f64 * 6.0_f64, 36.0_f64);
+    assert_eq(6.0_f128 * 6.0_f128, 36.0_f128);
+    assert_eq(-{ 5.0_f16 }, -5.0_f16);
     assert_eq(-{ 5.0_f32 }, -5.0_f32);
     assert_eq(-{ 5.0_f64 }, -5.0_f64);
+    assert_eq(-{ 5.0_f128 }, -5.0_f128);
+
     // infinities, NaN
+    // FIXME(f16_f128): add when constants and `is_infinite` are available
     assert!((5.0_f32 / 0.0).is_infinite());
     assert_ne!({ 5.0_f32 / 0.0 }, { -5.0_f32 / 0.0 });
     assert!((5.0_f64 / 0.0).is_infinite());
     assert_ne!({ 5.0_f64 / 0.0 }, { 5.0_f64 / -0.0 });
     assert_ne!(f32::NAN, f32::NAN);
     assert_ne!(f64::NAN, f64::NAN);
+
     // negative zero
+    let posz = 0.0f16;
+    let negz = -0.0f16;
+    assert_eq(posz, negz);
+    assert_ne!(posz.to_bits(), negz.to_bits());
     let posz = 0.0f32;
     let negz = -0.0f32;
     assert_eq(posz, negz);
@@ -173,15 +106,30 @@ fn basic() {
     let negz = -0.0f64;
     assert_eq(posz, negz);
     assert_ne!(posz.to_bits(), negz.to_bits());
+    let posz = 0.0f128;
+    let negz = -0.0f128;
+    assert_eq(posz, negz);
+    assert_ne!(posz.to_bits(), negz.to_bits());
+
     // byte-level transmute
-    let x: u64 = unsafe { std::mem::transmute(42.0_f64) };
-    let y: f64 = unsafe { std::mem::transmute(x) };
-    assert_eq(y, 42.0_f64);
+    let x: u16 = unsafe { std::mem::transmute(42.0_f16) };
+    let y: f16 = unsafe { std::mem::transmute(x) };
+    assert_eq(y, 42.0_f16);
     let x: u32 = unsafe { std::mem::transmute(42.0_f32) };
     let y: f32 = unsafe { std::mem::transmute(x) };
     assert_eq(y, 42.0_f32);
+    let x: u64 = unsafe { std::mem::transmute(42.0_f64) };
+    let y: f64 = unsafe { std::mem::transmute(x) };
+    assert_eq(y, 42.0_f64);
+    let x: u128 = unsafe { std::mem::transmute(42.0_f128) };
+    let y: f128 = unsafe { std::mem::transmute(x) };
+    assert_eq(y, 42.0_f128);
 
     // `%` sign behavior, some of this used to be buggy
+    assert!((black_box(1.0f16) % 1.0).is_sign_positive());
+    assert!((black_box(1.0f16) % -1.0).is_sign_positive());
+    assert!((black_box(-1.0f16) % 1.0).is_sign_negative());
+    assert!((black_box(-1.0f16) % -1.0).is_sign_negative());
     assert!((black_box(1.0f32) % 1.0).is_sign_positive());
     assert!((black_box(1.0f32) % -1.0).is_sign_positive());
     assert!((black_box(-1.0f32) % 1.0).is_sign_negative());
@@ -190,7 +138,12 @@ fn basic() {
     assert!((black_box(1.0f64) % -1.0).is_sign_positive());
     assert!((black_box(-1.0f64) % 1.0).is_sign_negative());
     assert!((black_box(-1.0f64) % -1.0).is_sign_negative());
+    assert!((black_box(1.0f128) % 1.0).is_sign_positive());
+    assert!((black_box(1.0f128) % -1.0).is_sign_positive());
+    assert!((black_box(-1.0f128) % 1.0).is_sign_negative());
+    assert!((black_box(-1.0f128) % -1.0).is_sign_negative());
 
+    // FIXME(f16_f128): add when `abs` is available
     assert_eq!((-1.0f32).abs(), 1.0f32);
     assert_eq!(34.2f64.abs(), 34.2f64);
 }
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse42.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse42.rs
new file mode 100644
index 00000000000..3ac53ea8b93
--- /dev/null
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse42.rs
@@ -0,0 +1,443 @@
+// Ignore everything except x86 and x86_64
+// Any new targets that are added to CI should be ignored here.
+// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.)
+//@ignore-target-aarch64
+//@ignore-target-arm
+//@ignore-target-avr
+//@ignore-target-s390x
+//@ignore-target-thumbv7em
+//@ignore-target-wasm32
+//@compile-flags: -C target-feature=+sse4.2
+
+#[cfg(target_arch = "x86")]
+use std::arch::x86::*;
+#[cfg(target_arch = "x86_64")]
+use std::arch::x86_64::*;
+use std::mem::transmute;
+
+fn main() {
+    assert!(is_x86_feature_detected!("sse4.2"));
+
+    unsafe {
+        test_sse42();
+    }
+}
+
+#[target_feature(enable = "sse4.2")]
+unsafe fn test_sse42() {
+    // Mostly copied from library/stdarch/crates/core_arch/src/x86/sse42.rs
+
+    test_crc();
+    test_cmp();
+    test_str();
+}
+
+#[target_feature(enable = "sse4.2")]
+unsafe fn test_crc() {
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_crc32_u8() {
+        let crc = 0x2aa1e72b;
+        let v = 0x2a;
+        let i = _mm_crc32_u8(crc, v);
+        assert_eq!(i, 0xf24122e4);
+
+        let crc = 0x61343ec4;
+        let v = 0xef;
+        let i = _mm_crc32_u8(crc, v);
+        assert_eq!(i, 0xb95511db);
+
+        let crc = 0xbadeafe;
+        let v = 0xc0;
+        let i = _mm_crc32_u8(crc, v);
+        assert_eq!(i, 0x9c905b7c);
+    }
+    test_mm_crc32_u8();
+
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_crc32_u16() {
+        let crc = 0x8ecec3b5;
+        let v = 0x22b;
+        let i = _mm_crc32_u16(crc, v);
+        assert_eq!(i, 0x13bb2fb);
+
+        let crc = 0x150bc664;
+        let v = 0xa6c0;
+        let i = _mm_crc32_u16(crc, v);
+        assert_eq!(i, 0xab04fe4e);
+
+        let crc = 0xbadeafe;
+        let v = 0xc0fe;
+        let i = _mm_crc32_u16(crc, v);
+        assert_eq!(i, 0x4b5fad4b);
+    }
+    test_mm_crc32_u16();
+
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_crc32_u32() {
+        let crc = 0xae2912c8;
+        let v = 0x845fed;
+        let i = _mm_crc32_u32(crc, v);
+        assert_eq!(i, 0xffae2ed1);
+
+        let crc = 0x1a198fe3;
+        let v = 0x885585c2;
+        let i = _mm_crc32_u32(crc, v);
+        assert_eq!(i, 0x22443a7b);
+
+        let crc = 0xbadeafe;
+        let v = 0xc0febeef;
+        let i = _mm_crc32_u32(crc, v);
+        assert_eq!(i, 0xb309502f);
+    }
+    test_mm_crc32_u32();
+
+    #[cfg(target_arch = "x86_64")]
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_crc32_u64() {
+        let crc = 0x7819dccd3e824;
+        let v = 0x2a22b845fed;
+        let i = _mm_crc32_u64(crc, v);
+        assert_eq!(i, 0xbb6cdc6c);
+
+        let crc = 0x6dd960387fe13819;
+        let v = 0x1a7ea8fb571746b0;
+        let i = _mm_crc32_u64(crc, v);
+        assert_eq!(i, 0x315b4f6);
+
+        let crc = 0xbadeafe;
+        let v = 0xc0febeefdadafefe;
+        let i = _mm_crc32_u64(crc, v);
+        assert_eq!(i, 0x5b44f54f);
+    }
+    #[cfg(not(target_arch = "x86_64"))]
+    unsafe fn test_mm_crc32_u64() {}
+    test_mm_crc32_u64();
+}
+
+#[target_feature(enable = "sse4.2")]
+unsafe fn test_cmp() {
+    let a = _mm_set_epi64x(0x2a, 0);
+    let b = _mm_set1_epi64x(0x00);
+    let i = _mm_cmpgt_epi64(a, b);
+    assert_eq_m128i(i, _mm_set_epi64x(0xffffffffffffffffu64 as i64, 0x00));
+}
+
+#[target_feature(enable = "sse4.2")]
+unsafe fn test_str() {
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn str_to_m128i(s: &[u8]) -> __m128i {
+        assert!(s.len() <= 16);
+        let slice = &mut [0u8; 16];
+        std::ptr::copy_nonoverlapping(s.as_ptr(), slice.as_mut_ptr(), s.len());
+        _mm_loadu_si128(slice.as_ptr() as *const _)
+    }
+
+    // Test the `_mm_cmpistrm` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpistrm() {
+        let a = str_to_m128i(b"Hello! Good-Bye!");
+        let b = str_to_m128i(b"hello! good-bye!");
+        let i = _mm_cmpistrm::<_SIDD_UNIT_MASK>(a, b);
+        #[rustfmt::skip]
+        let res = _mm_setr_epi8(
+            0x00, !0, !0, !0, !0, !0, !0, 0x00,
+            !0, !0, !0, !0, 0x00, !0, !0, !0,
+        );
+        assert_eq_m128i(i, res);
+    }
+    test_mm_cmpistrm();
+
+    // Test the `_mm_cmpistri` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpistri() {
+        let a = str_to_m128i(b"Hello");
+        let b = str_to_m128i(b"   Hello        ");
+        let i = _mm_cmpistri::<_SIDD_CMP_EQUAL_ORDERED>(a, b);
+        assert_eq!(3, i);
+    }
+    test_mm_cmpistri();
+
+    // Test the `_mm_cmpistrz` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpistrz() {
+        let a = str_to_m128i(b"");
+        let b = str_to_m128i(b"Hello");
+        let i = _mm_cmpistrz::<_SIDD_CMP_EQUAL_ORDERED>(a, b);
+        assert_eq!(1, i);
+    }
+    test_mm_cmpistrz();
+
+    // Test the `_mm_cmpistrc` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpistrc() {
+        let a = str_to_m128i(b"                ");
+        let b = str_to_m128i(b"       !        ");
+        let i = _mm_cmpistrc::<_SIDD_UNIT_MASK>(a, b);
+        assert_eq!(1, i);
+    }
+    test_mm_cmpistrc();
+
+    // Test the `_mm_cmpistrs` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpistrs() {
+        let a = str_to_m128i(b"Hello");
+        let b = str_to_m128i(b"");
+        let i = _mm_cmpistrs::<_SIDD_CMP_EQUAL_ORDERED>(a, b);
+        assert_eq!(1, i);
+    }
+    test_mm_cmpistrs();
+
+    // Test the `_mm_cmpistro` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpistro() {
+        #[rustfmt::skip]
+        let a_bytes = _mm_setr_epi8(
+            0x00, 0x47, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c,
+            0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        );
+        #[rustfmt::skip]
+        let b_bytes = _mm_setr_epi8(
+            0x00, 0x48, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c,
+            0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        );
+        let a = a_bytes;
+        let b = b_bytes;
+        let i = _mm_cmpistro::<{ _SIDD_UWORD_OPS | _SIDD_UNIT_MASK }>(a, b);
+        assert_eq!(0, i);
+    }
+    test_mm_cmpistro();
+
+    // Test the `_mm_cmpistra` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpistra() {
+        let a = str_to_m128i(b"");
+        let b = str_to_m128i(b"Hello!!!!!!!!!!!");
+        let i = _mm_cmpistra::<_SIDD_UNIT_MASK>(a, b);
+        assert_eq!(1, i);
+    }
+    test_mm_cmpistra();
+
+    // Test the `_mm_cmpestrm` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpestrm() {
+        let a = str_to_m128i(b"Hello!");
+        let b = str_to_m128i(b"Hello.");
+        let i = _mm_cmpestrm::<_SIDD_UNIT_MASK>(a, 5, b, 5);
+        #[rustfmt::skip]
+        let r = _mm_setr_epi8(
+            !0, !0, !0, !0, !0, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        );
+        assert_eq_m128i(i, r);
+    }
+    test_mm_cmpestrm();
+
+    // Test the `_mm_cmpestri` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpestri() {
+        let a = str_to_m128i(b"bar - garbage");
+        let b = str_to_m128i(b"foobar");
+        let i = _mm_cmpestri::<_SIDD_CMP_EQUAL_ORDERED>(a, 3, b, 6);
+        assert_eq!(3, i);
+    }
+    test_mm_cmpestri();
+
+    // Test the `_mm_cmpestrz` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpestrz() {
+        let a = str_to_m128i(b"");
+        let b = str_to_m128i(b"Hello");
+        let i = _mm_cmpestrz::<_SIDD_CMP_EQUAL_ORDERED>(a, 16, b, 6);
+        assert_eq!(1, i);
+    }
+    test_mm_cmpestrz();
+
+    // Test the `_mm_cmpestrs` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpestrc() {
+        let va = str_to_m128i(b"!!!!!!!!");
+        let vb = str_to_m128i(b"        ");
+        let i = _mm_cmpestrc::<_SIDD_UNIT_MASK>(va, 7, vb, 7);
+        assert_eq!(0, i);
+    }
+    test_mm_cmpestrc();
+
+    // Test the `_mm_cmpestrs` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpestrs() {
+        #[rustfmt::skip]
+        let a_bytes = _mm_setr_epi8(
+            0x00, 0x48, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c,
+            0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        );
+        let a = a_bytes;
+        let b = _mm_set1_epi8(0x00);
+        let i = _mm_cmpestrs::<_SIDD_UWORD_OPS>(a, 8, b, 0);
+        assert_eq!(0, i);
+    }
+    test_mm_cmpestrs();
+
+    // Test the `_mm_cmpestro` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpestro() {
+        let a = str_to_m128i(b"Hello");
+        let b = str_to_m128i(b"World");
+        let i = _mm_cmpestro::<_SIDD_UBYTE_OPS>(a, 5, b, 5);
+        assert_eq!(0, i);
+    }
+    test_mm_cmpestro();
+
+    // Test the `_mm_cmpestra` intrinsic.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_mm_cmpestra() {
+        let a = str_to_m128i(b"Cannot match a");
+        let b = str_to_m128i(b"Null after 14");
+        let i = _mm_cmpestra::<{ _SIDD_CMP_EQUAL_EACH | _SIDD_UNIT_MASK }>(a, 14, b, 16);
+        assert_eq!(1, i);
+    }
+    test_mm_cmpestra();
+
+    // Additional tests not inside the standard library.
+
+    // Test the subset functionality of the intrinsic.
+    unsafe fn test_subset() {
+        let a = str_to_m128i(b"ABCDEFG");
+        let b = str_to_m128i(b"ABC UVW XYZ EFG");
+
+        let i = _mm_cmpistrm::<{ _SIDD_CMP_EQUAL_ANY | _SIDD_UNIT_MASK }>(a, b);
+        #[rustfmt::skip]
+        let res = _mm_setr_epi8(
+            !0, !0, !0, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, !0, !0, !0, 0x00,
+        );
+        assert_eq_m128i(i, res);
+    }
+    test_subset();
+
+    // Properly test index generation.
+    unsafe fn test_index() {
+        let a = str_to_m128i(b"Hello");
+        let b = str_to_m128i(b"Hello Hello H");
+
+        let i = _mm_cmpistri::<{ _SIDD_CMP_EQUAL_EACH | _SIDD_LEAST_SIGNIFICANT }>(a, b);
+        assert_eq!(i, 0);
+
+        let i = _mm_cmpistri::<{ _SIDD_CMP_EQUAL_EACH | _SIDD_MOST_SIGNIFICANT }>(a, b);
+        assert_eq!(i, 15);
+
+        let a = str_to_m128i(b"Hello");
+        let b = str_to_m128i(b"                ");
+        let i = _mm_cmpistri::<{ _SIDD_CMP_EQUAL_EACH | _SIDD_MOST_SIGNIFICANT }>(a, b);
+        assert_eq!(i, 16);
+    }
+    test_index();
+
+    // Properly test the substring functionality of the intrinsics.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_substring() {
+        let a = str_to_m128i(b"Hello");
+        let b = str_to_m128i(b"Hello Hello H");
+
+        let i = _mm_cmpistrm::<{ _SIDD_CMP_EQUAL_ORDERED | _SIDD_UNIT_MASK }>(a, b);
+        #[rustfmt::skip]
+        let res = _mm_setr_epi8(
+            !0, 0x00, 0x00, 0x00, 0x00, 0x00, !0, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        );
+        assert_eq_m128i(i, res);
+    }
+    test_substring();
+
+    // Test the range functionality of the intrinsics.
+    // Will also test signed values and word-sized values.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_ranges() {
+        let a = _mm_setr_epi16(0, 1, 7, 8, 0, 0, -100, 100);
+        let b = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8);
+
+        let i =
+            _mm_cmpestrm::<{ _SIDD_SWORD_OPS | _SIDD_CMP_RANGES | _SIDD_UNIT_MASK }>(a, 2, b, 8);
+        let res = _mm_setr_epi16(!0, 0, 0, 0, 0, 0, 0, 0);
+        assert_eq_m128i(i, res);
+
+        let i =
+            _mm_cmpestrm::<{ _SIDD_SWORD_OPS | _SIDD_CMP_RANGES | _SIDD_UNIT_MASK }>(a, 3, b, 8);
+        let res = _mm_setr_epi16(!0, 0, 0, 0, 0, 0, 0, 0);
+        assert_eq_m128i(i, res);
+
+        let i =
+            _mm_cmpestrm::<{ _SIDD_SWORD_OPS | _SIDD_CMP_RANGES | _SIDD_UNIT_MASK }>(a, 4, b, 8);
+        let res = _mm_setr_epi16(!0, 0, 0, 0, 0, 0, !0, !0);
+        assert_eq_m128i(i, res);
+
+        let i =
+            _mm_cmpestrm::<{ _SIDD_SWORD_OPS | _SIDD_CMP_RANGES | _SIDD_UNIT_MASK }>(a, 6, b, 8);
+        let res = _mm_setr_epi16(!0, 0, 0, 0, 0, 0, !0, !0);
+        assert_eq_m128i(i, res);
+
+        let i =
+            _mm_cmpestrm::<{ _SIDD_SWORD_OPS | _SIDD_CMP_RANGES | _SIDD_UNIT_MASK }>(a, 8, b, 8);
+        let res = _mm_setr_epi16(!0, !0, !0, !0, !0, !0, !0, !0);
+        assert_eq_m128i(i, res);
+    }
+    test_ranges();
+
+    // Confirm that the polarity bits work as indended.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_polarity() {
+        let a = str_to_m128i(b"Hello!");
+        let b = str_to_m128i(b"hello?");
+
+        let i = _mm_cmpistrm::<
+            { (_SIDD_MASKED_NEGATIVE_POLARITY ^ _SIDD_NEGATIVE_POLARITY) | _SIDD_UNIT_MASK },
+        >(a, b);
+        #[rustfmt::skip]
+        let res = _mm_setr_epi8(
+            0x00, !0, !0, !0, !0, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        );
+        assert_eq_m128i(i, res);
+
+        let i = _mm_cmpistrm::<{ _SIDD_MASKED_NEGATIVE_POLARITY | _SIDD_UNIT_MASK }>(a, b);
+        #[rustfmt::skip]
+        let res = _mm_setr_epi8(
+            !0, 0x00, 0x00, 0x00, 0x00, !0, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        );
+        assert_eq_m128i(i, res);
+
+        let i = _mm_cmpistrm::<{ _SIDD_NEGATIVE_POLARITY | _SIDD_UNIT_MASK }>(a, b);
+        #[rustfmt::skip]
+        let res = _mm_setr_epi8(
+            !0, 0x00, 0x00, 0x00, 0x00, !0, !0, !0,
+            !0, !0, !0, !0, !0, !0, !0, !0,
+        );
+        assert_eq_m128i(i, res);
+    }
+    test_polarity();
+
+    // Test the code path in which the intrinsic is supposed to
+    // return a bit mask instead of a byte mask.
+    #[target_feature(enable = "sse4.2")]
+    unsafe fn test_bitmask() {
+        let a = str_to_m128i(b"Hello! Good-Bye!");
+        let b = str_to_m128i(b"hello! good-bye!");
+
+        let i = _mm_cmpistrm::<0>(a, b);
+        #[rustfmt::skip]
+        let res = _mm_setr_epi32(0b11101111_01111110, 0, 0, 0);
+        assert_eq_m128i(i, res);
+
+        let i = _mm_cmpistrm::<_SIDD_MASKED_NEGATIVE_POLARITY>(a, b);
+        #[rustfmt::skip]
+        let res = _mm_setr_epi32(0b00010000_10000001, 0, 0, 0);
+        assert_eq_m128i(i, res);
+    }
+    test_bitmask();
+}
+
+#[track_caller]
+#[target_feature(enable = "sse2")]
+pub unsafe fn assert_eq_m128i(a: __m128i, b: __m128i) {
+    assert_eq!(transmute::<_, [u64; 2]>(a), transmute::<_, [u64; 2]>(b))
+}
diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs
index 89f4d8957c8..1237951b3f0 100644
--- a/src/tools/opt-dist/src/training.rs
+++ b/src/tools/opt-dist/src/training.rs
@@ -216,11 +216,9 @@ pub fn gather_bolt_profiles(
     log::info!("Profile file count: {}", profiles.len());
 
     // Delete the gathered profiles
-    for profile in glob::glob(&format!("{profile_prefix}*"))?.into_iter() {
-        if let Ok(profile) = profile {
-            if let Err(error) = std::fs::remove_file(&profile) {
-                log::error!("Cannot delete BOLT profile {}: {error:?}", profile.display());
-            }
+    for profile in glob::glob(&format!("{profile_prefix}*"))?.flatten() {
+        if let Err(error) = std::fs::remove_file(&profile) {
+            log::error!("Cannot delete BOLT profile {}: {error:?}", profile.display());
         }
     }
 
diff --git a/src/tools/remote-test-client/src/main.rs b/src/tools/remote-test-client/src/main.rs
index 590c735596e..dd2c09c430b 100644
--- a/src/tools/remote-test-client/src/main.rs
+++ b/src/tools/remote-test-client/src/main.rs
@@ -317,13 +317,11 @@ fn run(support_lib_count: usize, exe: String, all_args: Vec<String>) {
                 t!(io::copy(&mut (&mut client).take(amt), &mut stdout));
                 t!(stdout.flush());
             }
+        } else if amt == 0 {
+            stderr_done = true;
         } else {
-            if amt == 0 {
-                stderr_done = true;
-            } else {
-                t!(io::copy(&mut (&mut client).take(amt), &mut stderr));
-                t!(stderr.flush());
-            }
+            t!(io::copy(&mut (&mut client).take(amt), &mut stderr));
+            t!(stderr.flush());
         }
     }
 
diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs
index 68d7aa56c43..79f96c50223 100644
--- a/src/tools/remote-test-server/src/main.rs
+++ b/src/tools/remote-test-server/src/main.rs
@@ -282,7 +282,7 @@ fn handle_run(socket: TcpStream, work: &Path, tmp: &Path, lock: &Mutex<()>, conf
     cmd.env(library_path, env::join_paths(paths).unwrap());
 
     // Some tests assume RUST_TEST_TMPDIR exists
-    cmd.env("RUST_TEST_TMPDIR", tmp.to_owned());
+    cmd.env("RUST_TEST_TMPDIR", tmp);
 
     let socket = Arc::new(Mutex::new(reader.into_inner()));
 
diff --git a/src/tools/run-make-support/CHANGELOG.md b/src/tools/run-make-support/CHANGELOG.md
index a37de9fda80..c1b7b618a92 100644
--- a/src/tools/run-make-support/CHANGELOG.md
+++ b/src/tools/run-make-support/CHANGELOG.md
@@ -10,6 +10,22 @@ changes to the support library).
 This support library will probably never reach 1.0. Please bump the minor version in `Cargo.toml` if
 you make any breaking changes or other significant changes, or bump the patch version for bug fixes.
 
+## [0.2.0] - 2024-06-11
+
+### Added
+
+- Added `fs_wrapper` module which provides panic-on-fail helpers for their respective `std::fs`
+  counterparts, the motivation is to:
+    - Reduce littering `.unwrap()` or `.expect()` everywhere for fs operations
+    - Help the test writer avoid forgetting to check fs results (even though enforced by
+      `-Dunused_must_use`)
+    - Provide better panic messages by default
+- Added `path()` helper which creates a `Path` relative to `cwd()` (but is less noisy).
+
+### Changed
+
+- Marked many functions with `#[must_use]`, and rmake.rs are now compiled with `-Dunused_must_use`.
+
 ## [0.1.0] - 2024-06-09
 
 ### Changed
diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml
index 5450620e7f0..2f7f51442f1 100644
--- a/src/tools/run-make-support/Cargo.toml
+++ b/src/tools/run-make-support/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "run_make_support"
-version = "0.1.0"
+version = "0.2.0"
 edition = "2021"
 
 [dependencies]
diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs
index 8694740cfc3..31b9e8a23b8 100644
--- a/src/tools/run-make-support/src/cc.rs
+++ b/src/tools/run-make-support/src/cc.rs
@@ -15,6 +15,7 @@ pub fn cc() -> Cc {
 /// A platform-specific C compiler invocation builder. The specific C compiler used is
 /// passed down from compiletest.
 #[derive(Debug)]
+#[must_use]
 pub struct Cc {
     cmd: Command,
 }
diff --git a/src/tools/run-make-support/src/clang.rs b/src/tools/run-make-support/src/clang.rs
index a31004659c1..c23e41ebe21 100644
--- a/src/tools/run-make-support/src/clang.rs
+++ b/src/tools/run-make-support/src/clang.rs
@@ -11,6 +11,7 @@ pub fn clang() -> Clang {
 
 /// A `clang` invocation builder.
 #[derive(Debug)]
+#[must_use]
 pub struct Clang {
     cmd: Command,
 }
diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs
index d689dc2f979..dab18dca2ff 100644
--- a/src/tools/run-make-support/src/command.rs
+++ b/src/tools/run-make-support/src/command.rs
@@ -6,7 +6,7 @@ use std::path::Path;
 use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
 
 use crate::drop_bomb::DropBomb;
-use crate::{assert_not_contains, handle_failed_output};
+use crate::{assert_contains, assert_not_contains, handle_failed_output};
 
 /// This is a custom command wrapper that simplifies working with commands and makes it easier to
 /// ensure that we check the exit status of executed processes.
@@ -148,14 +148,17 @@ pub struct CompletedProcess {
 }
 
 impl CompletedProcess {
+    #[must_use]
     pub fn stdout_utf8(&self) -> String {
         String::from_utf8(self.output.stdout.clone()).expect("stdout is not valid UTF-8")
     }
 
+    #[must_use]
     pub fn stderr_utf8(&self) -> String {
         String::from_utf8(self.output.stderr.clone()).expect("stderr is not valid UTF-8")
     }
 
+    #[must_use]
     pub fn status(&self) -> ExitStatus {
         self.output.status
     }
@@ -168,6 +171,12 @@ impl CompletedProcess {
     }
 
     #[track_caller]
+    pub fn assert_stdout_contains<S: AsRef<str>>(self, needle: S) -> Self {
+        assert_contains(&self.stdout_utf8(), needle.as_ref());
+        self
+    }
+
+    #[track_caller]
     pub fn assert_stdout_not_contains<S: AsRef<str>>(&self, needle: S) -> &Self {
         assert_not_contains(&self.stdout_utf8(), needle.as_ref());
         self
@@ -182,7 +191,7 @@ impl CompletedProcess {
 
     #[track_caller]
     pub fn assert_stderr_contains<S: AsRef<str>>(&self, needle: S) -> &Self {
-        assert!(self.stderr_utf8().contains(needle.as_ref()));
+        assert_contains(&self.stderr_utf8(), needle.as_ref());
         self
     }
 
diff --git a/src/tools/run-make-support/src/diff/mod.rs b/src/tools/run-make-support/src/diff/mod.rs
index 0fb6fec9d58..3e0bdc1c6f6 100644
--- a/src/tools/run-make-support/src/diff/mod.rs
+++ b/src/tools/run-make-support/src/diff/mod.rs
@@ -1,8 +1,9 @@
 use regex::Regex;
 use similar::TextDiff;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 
 use crate::drop_bomb::DropBomb;
+use crate::fs_wrapper;
 
 #[cfg(test)]
 mod tests;
@@ -13,9 +14,11 @@ pub fn diff() -> Diff {
 }
 
 #[derive(Debug)]
+#[must_use]
 pub struct Diff {
     expected: Option<String>,
     expected_name: Option<String>,
+    expected_file: Option<PathBuf>,
     actual: Option<String>,
     actual_name: Option<String>,
     normalizers: Vec<(String, String)>,
@@ -29,6 +32,7 @@ impl Diff {
         Self {
             expected: None,
             expected_name: None,
+            expected_file: None,
             actual: None,
             actual_name: None,
             normalizers: Vec::new(),
@@ -39,9 +43,10 @@ impl Diff {
     /// Specify the expected output for the diff from a file.
     pub fn expected_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         let path = path.as_ref();
-        let content = std::fs::read_to_string(path).expect("failed to read file");
+        let content = fs_wrapper::read_to_string(path);
         let name = path.to_string_lossy().to_string();
 
+        self.expected_file = Some(path.into());
         self.expected = Some(content);
         self.expected_name = Some(name);
         self
@@ -57,10 +62,7 @@ impl Diff {
     /// Specify the actual output for the diff from a file.
     pub fn actual_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         let path = path.as_ref();
-        let content = match std::fs::read_to_string(path) {
-            Ok(c) => c,
-            Err(e) => panic!("failed to read `{}`: {:?}", path.display(), e),
-        };
+        let content = fs_wrapper::read_to_string(path);
         let name = path.to_string_lossy().to_string();
 
         self.actual = Some(content);
@@ -103,6 +105,15 @@ impl Diff {
             .to_string();
 
         if !output.is_empty() {
+            // If we can bless (meaning we have a file to write into and the `RUSTC_BLESS_TEST`
+            // environment variable set), then we write into the file and return.
+            if let Some(ref expected_file) = self.expected_file {
+                if std::env::var("RUSTC_BLESS_TEST").is_ok() {
+                    println!("Blessing `{}`", expected_file.display());
+                    fs_wrapper::write(expected_file, actual);
+                    return;
+                }
+            }
             panic!(
                 "test failed: `{}` is different from `{}`\n\n{}",
                 expected_name, actual_name, output
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index b920f9a07db..ba4524c150c 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -9,7 +9,7 @@ mod command;
 pub mod diff;
 mod drop_bomb;
 pub mod fs_wrapper;
-pub mod llvm_readobj;
+pub mod llvm;
 pub mod run;
 pub mod rustc;
 pub mod rustdoc;
@@ -29,12 +29,15 @@ pub use wasmparser;
 pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
 pub use clang::{clang, Clang};
 pub use diff::{diff, Diff};
-pub use llvm_readobj::{llvm_readobj, LlvmReadobj};
-pub use run::{cmd, run, run_fail};
+pub use llvm::{
+    llvm_filecheck, llvm_profdata, llvm_readobj, LlvmFilecheck, LlvmProfdata, LlvmReadobj,
+};
+pub use run::{cmd, run, run_fail, run_with_args};
 pub use rustc::{aux_build, rustc, Rustc};
 pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
 
 #[track_caller]
+#[must_use]
 pub fn env_var(name: &str) -> String {
     match env::var(name) {
         Ok(v) => v,
@@ -43,6 +46,7 @@ pub fn env_var(name: &str) -> String {
 }
 
 #[track_caller]
+#[must_use]
 pub fn env_var_os(name: &str) -> OsString {
     match env::var_os(name) {
         Some(v) => v,
@@ -51,32 +55,38 @@ pub fn env_var_os(name: &str) -> OsString {
 }
 
 /// `TARGET`
+#[must_use]
 pub fn target() -> String {
     env_var("TARGET")
 }
 
 /// Check if target is windows-like.
+#[must_use]
 pub fn is_windows() -> bool {
     target().contains("windows")
 }
 
 /// Check if target uses msvc.
+#[must_use]
 pub fn is_msvc() -> bool {
     target().contains("msvc")
 }
 
 /// Check if target uses macOS.
+#[must_use]
 pub fn is_darwin() -> bool {
     target().contains("darwin")
 }
 
 #[track_caller]
+#[must_use]
 pub fn python_command() -> Command {
     let python_path = env_var("PYTHON");
     Command::new(python_path)
 }
 
 #[track_caller]
+#[must_use]
 pub fn htmldocck() -> Command {
     let mut python = python_command();
     python.arg(source_root().join("src/etc/htmldocck.py"));
@@ -89,11 +99,41 @@ pub fn path<P: AsRef<Path>>(p: P) -> PathBuf {
 }
 
 /// Path to the root rust-lang/rust source checkout.
+#[must_use]
 pub fn source_root() -> PathBuf {
     env_var("SOURCE_ROOT").into()
 }
 
+/// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix.
+#[cfg(target_family = "windows")]
+pub fn create_symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) {
+    if link.as_ref().exists() {
+        std::fs::remove_dir(link.as_ref()).unwrap();
+    }
+    use std::os::windows::fs;
+    fs::symlink_file(original.as_ref(), link.as_ref()).expect(&format!(
+        "failed to create symlink {:?} for {:?}",
+        link.as_ref().display(),
+        original.as_ref().display(),
+    ));
+}
+
+/// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix.
+#[cfg(target_family = "unix")]
+pub fn create_symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) {
+    if link.as_ref().exists() {
+        std::fs::remove_dir(link.as_ref()).unwrap();
+    }
+    use std::os::unix::fs;
+    fs::symlink(original.as_ref(), link.as_ref()).expect(&format!(
+        "failed to create symlink {:?} for {:?}",
+        link.as_ref().display(),
+        original.as_ref().display(),
+    ));
+}
+
 /// Construct the static library name based on the platform.
+#[must_use]
 pub fn static_lib_name(name: &str) -> String {
     // See tools.mk (irrelevant lines omitted):
     //
@@ -118,6 +158,7 @@ pub fn static_lib_name(name: &str) -> String {
 }
 
 /// Construct the dynamic library name based on the platform.
+#[must_use]
 pub fn dynamic_lib_name(name: &str) -> String {
     // See tools.mk (irrelevant lines omitted):
     //
@@ -144,6 +185,7 @@ pub fn dynamic_lib_name(name: &str) -> String {
     }
 }
 
+#[must_use]
 pub fn dynamic_lib_extension() -> &'static str {
     if is_darwin() {
         "dylib"
@@ -155,16 +197,19 @@ pub fn dynamic_lib_extension() -> &'static str {
 }
 
 /// Generate the name a rust library (rlib) would have.
+#[must_use]
 pub fn rust_lib_name(name: &str) -> String {
     format!("lib{name}.rlib")
 }
 
 /// Construct the binary name based on platform.
+#[must_use]
 pub fn bin_name(name: &str) -> String {
     if is_windows() { format!("{name}.exe") } else { name.to_string() }
 }
 
 /// Return the current working directory.
+#[must_use]
 pub fn cwd() -> PathBuf {
     env::current_dir().unwrap()
 }
@@ -172,6 +217,7 @@ pub fn cwd() -> PathBuf {
 /// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
 /// available on the platform!
 #[track_caller]
+#[must_use]
 pub fn cygpath_windows<P: AsRef<Path>>(path: P) -> String {
     let caller = panic::Location::caller();
     let mut cygpath = Command::new("cygpath");
@@ -187,6 +233,7 @@ pub fn cygpath_windows<P: AsRef<Path>>(path: P) -> String {
 
 /// Run `uname`. This assumes that `uname` is available on the platform!
 #[track_caller]
+#[must_use]
 pub fn uname() -> String {
     let caller = panic::Location::caller();
     let mut uname = Command::new("uname");
@@ -285,6 +332,18 @@ pub fn read_dir<F: Fn(&Path)>(dir: impl AsRef<Path>, callback: F) {
     }
 }
 
+/// Check that `haystack` contains `needle`. Panic otherwise.
+#[track_caller]
+pub fn assert_contains(haystack: &str, needle: &str) {
+    if !haystack.contains(needle) {
+        eprintln!("=== HAYSTACK ===");
+        eprintln!("{}", haystack);
+        eprintln!("=== NEEDLE ===");
+        eprintln!("{}", needle);
+        panic!("needle was not found in haystack");
+    }
+}
+
 /// Check that `haystack` does not contain `needle`. Panic otherwise.
 #[track_caller]
 pub fn assert_not_contains(haystack: &str, needle: &str) {
diff --git a/src/tools/run-make-support/src/llvm.rs b/src/tools/run-make-support/src/llvm.rs
new file mode 100644
index 00000000000..414251abda2
--- /dev/null
+++ b/src/tools/run-make-support/src/llvm.rs
@@ -0,0 +1,127 @@
+use std::path::{Path, PathBuf};
+
+use crate::{env_var, Command};
+
+/// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
+/// at `$LLVM_BIN_DIR/llvm-readobj`.
+pub fn llvm_readobj() -> LlvmReadobj {
+    LlvmReadobj::new()
+}
+
+/// Construct a new `llvm-profdata` invocation. This assumes that `llvm-profdata` is available
+/// at `$LLVM_BIN_DIR/llvm-profdata`.
+pub fn llvm_profdata() -> LlvmProfdata {
+    LlvmProfdata::new()
+}
+
+/// Construct a new `llvm-filecheck` invocation. This assumes that `llvm-filecheck` is available
+/// at `$LLVM_FILECHECK`.
+pub fn llvm_filecheck() -> LlvmFilecheck {
+    LlvmFilecheck::new()
+}
+
+/// A `llvm-readobj` invocation builder.
+#[derive(Debug)]
+#[must_use]
+pub struct LlvmReadobj {
+    cmd: Command,
+}
+
+/// A `llvm-profdata` invocation builder.
+#[derive(Debug)]
+#[must_use]
+pub struct LlvmProfdata {
+    cmd: Command,
+}
+
+/// A `llvm-filecheck` invocation builder.
+#[derive(Debug)]
+#[must_use]
+pub struct LlvmFilecheck {
+    cmd: Command,
+}
+
+crate::impl_common_helpers!(LlvmReadobj);
+crate::impl_common_helpers!(LlvmProfdata);
+crate::impl_common_helpers!(LlvmFilecheck);
+
+/// Generate the path to the bin directory of LLVM.
+#[must_use]
+pub fn llvm_bin_dir() -> PathBuf {
+    let llvm_bin_dir = env_var("LLVM_BIN_DIR");
+    PathBuf::from(llvm_bin_dir)
+}
+
+impl LlvmReadobj {
+    /// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
+    /// at `$LLVM_BIN_DIR/llvm-readobj`.
+    pub fn new() -> Self {
+        let llvm_readobj = llvm_bin_dir().join("llvm-readobj");
+        let cmd = Command::new(llvm_readobj);
+        Self { cmd }
+    }
+
+    /// Provide an input file.
+    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
+    /// Pass `--file-header` to display file headers.
+    pub fn file_header(&mut self) -> &mut Self {
+        self.cmd.arg("--file-header");
+        self
+    }
+}
+
+impl LlvmProfdata {
+    /// Construct a new `llvm-profdata` invocation. This assumes that `llvm-profdata` is available
+    /// at `$LLVM_BIN_DIR/llvm-profdata`.
+    pub fn new() -> Self {
+        let llvm_profdata = llvm_bin_dir().join("llvm-profdata");
+        let cmd = Command::new(llvm_profdata);
+        Self { cmd }
+    }
+
+    /// Provide an input file.
+    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
+    /// Specify the output file path.
+    pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg("-o");
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
+    /// Take several profile data files generated by PGO instrumentation and merge them
+    /// together into a single indexed profile data file.
+    pub fn merge(&mut self) -> &mut Self {
+        self.cmd.arg("merge");
+        self
+    }
+}
+
+impl LlvmFilecheck {
+    /// Construct a new `llvm-filecheck` invocation. This assumes that `llvm-filecheck` is available
+    /// at `$LLVM_FILECHECK`.
+    pub fn new() -> Self {
+        let llvm_filecheck = env_var("LLVM_FILECHECK");
+        let cmd = Command::new(llvm_filecheck);
+        Self { cmd }
+    }
+
+    /// Pipe a read file into standard input containing patterns that will be matched against the .patterns(path) call.
+    pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
+        self.cmd.set_stdin(input.as_ref().to_vec().into_boxed_slice());
+        self
+    }
+
+    /// Provide the patterns that need to be matched.
+    pub fn patterns<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg(path.as_ref());
+        self
+    }
+}
diff --git a/src/tools/run-make-support/src/llvm_readobj.rs b/src/tools/run-make-support/src/llvm_readobj.rs
index 57ddfc205e6..3c719356e8f 100644
--- a/src/tools/run-make-support/src/llvm_readobj.rs
+++ b/src/tools/run-make-support/src/llvm_readobj.rs
@@ -12,6 +12,7 @@ pub fn llvm_readobj() -> LlvmReadobj {
 
 /// A `llvm-readobj` invocation builder.
 #[derive(Debug)]
+#[must_use]
 pub struct LlvmReadobj {
     cmd: Command,
 }
diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs
index 6fa1a75363c..54730bb7de7 100644
--- a/src/tools/run-make-support/src/run.rs
+++ b/src/tools/run-make-support/src/run.rs
@@ -9,12 +9,17 @@ use crate::{cwd, env_var, is_windows, set_host_rpath};
 use super::handle_failed_output;
 
 #[track_caller]
-fn run_common(name: &str) -> Command {
+fn run_common(name: &str, args: Option<&[&str]>) -> Command {
     let mut bin_path = PathBuf::new();
     bin_path.push(cwd());
     bin_path.push(name);
     let ld_lib_path_envvar = env_var("LD_LIB_PATH_ENVVAR");
     let mut cmd = Command::new(bin_path);
+    if let Some(args) = args {
+        for arg in args {
+            cmd.arg(arg);
+        }
+    }
     cmd.env(&ld_lib_path_envvar, {
         let mut paths = vec![];
         paths.push(cwd());
@@ -43,7 +48,19 @@ fn run_common(name: &str) -> Command {
 #[track_caller]
 pub fn run(name: &str) -> CompletedProcess {
     let caller = panic::Location::caller();
-    let mut cmd = run_common(name);
+    let mut cmd = run_common(name, None);
+    let output = cmd.run();
+    if !output.status().success() {
+        handle_failed_output(&cmd, output, caller.line());
+    }
+    output
+}
+
+/// Run a built binary with one or more argument(s) and make sure it succeeds.
+#[track_caller]
+pub fn run_with_args(name: &str, args: &[&str]) -> CompletedProcess {
+    let caller = panic::Location::caller();
+    let mut cmd = run_common(name, Some(args));
     let output = cmd.run();
     if !output.status().success() {
         handle_failed_output(&cmd, output, caller.line());
@@ -55,7 +72,7 @@ pub fn run(name: &str) -> CompletedProcess {
 #[track_caller]
 pub fn run_fail(name: &str) -> CompletedProcess {
     let caller = panic::Location::caller();
-    let mut cmd = run_common(name);
+    let mut cmd = run_common(name, None);
     let output = cmd.run_fail();
     if output.status().success() {
         handle_failed_output(&cmd, output, caller.line());
diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs
index 32fa5018d80..331e1a5ab8b 100644
--- a/src/tools/run-make-support/src/rustc.rs
+++ b/src/tools/run-make-support/src/rustc.rs
@@ -18,6 +18,7 @@ pub fn aux_build() -> Rustc {
 
 /// A `rustc` invocation builder.
 #[derive(Debug)]
+#[must_use]
 pub struct Rustc {
     cmd: Command,
 }
@@ -105,6 +106,12 @@ impl Rustc {
         self
     }
 
+    //Adjust the backtrace level, displaying more detailed information at higher levels.
+    pub fn set_backtrace_level<R: AsRef<OsStr>>(&mut self, level: R) -> &mut Self {
+        self.cmd.env("RUST_BACKTRACE", level);
+        self
+    }
+
     /// Specify path to the output file. Equivalent to `-o`` in rustc.
     pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         self.cmd.arg("-o");
@@ -146,6 +153,24 @@ impl Rustc {
         self
     }
 
+    /// Specify directory path used for profile generation
+    pub fn profile_generate<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        let mut arg = OsString::new();
+        arg.push("-Cprofile-generate=");
+        arg.push(path.as_ref());
+        self.cmd.arg(&arg);
+        self
+    }
+
+    /// Specify directory path used for profile usage
+    pub fn profile_use<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        let mut arg = OsString::new();
+        arg.push("-Cprofile-use=");
+        arg.push(path.as_ref());
+        self.cmd.arg(&arg);
+        self
+    }
+
     /// Specify error format to use
     pub fn error_format(&mut self, format: &str) -> &mut Self {
         self.cmd.arg(format!("--error-format={format}"));
diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs
index 332906f739a..93078561254 100644
--- a/src/tools/run-make-support/src/rustdoc.rs
+++ b/src/tools/run-make-support/src/rustdoc.rs
@@ -17,6 +17,7 @@ pub fn rustdoc() -> Rustdoc {
 }
 
 #[derive(Debug)]
+#[must_use]
 pub struct Rustdoc {
     cmd: Command,
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 5a9621bb69a..241690d0089 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -1387,6 +1387,7 @@ fn generic_args_sans_defaults<'ga>(
                     }
                     // otherwise, if the arg is equal to the param default, hide it (unless the
                     // default is an error which can happen for the trait Self type)
+                    #[allow(unstable_name_collisions)]
                     default_parameters.get(i).is_none_or(|default_parameter| {
                         // !is_err(default_parameter.skip_binders())
                         //     &&
diff --git a/src/tools/tidy/config/requirements.in b/src/tools/tidy/config/requirements.in
index 882e09dae45..047617c6559 100644
--- a/src/tools/tidy/config/requirements.in
+++ b/src/tools/tidy/config/requirements.in
@@ -1,10 +1,10 @@
 # requirements.in This is the source file for our pinned version requirements
 # file "requirements.txt" To regenerate that file, pip-tools is required
-# (`python -m pip install pip-tools`). Once installed, run: `pip-compile
-# --generate-hashes src/tools/tidy/config/requirements.in`
+# (`python -m pip install pip-tools==7.4.1`). Once installed, run: `pip-compile
+# --generate-hashes --strip-extras src/tools/tidy/config/requirements.in`
 #
 # Note: this generation step should be run with the oldest supported python
-# version (currently 3.7) to ensure backward compatibility
+# version (currently 3.9) to ensure backward compatibility
 
 black==23.3.0
 ruff==0.0.272
diff --git a/src/tools/tidy/config/requirements.txt b/src/tools/tidy/config/requirements.txt
index 9fd617ad621..a53c98cac7a 100644
--- a/src/tools/tidy/config/requirements.txt
+++ b/src/tools/tidy/config/requirements.txt
@@ -1,8 +1,8 @@
 #
-# This file is autogenerated by pip-compile with Python 3.11
+# This file is autogenerated by pip-compile with Python 3.9
 # by the following command:
 #
-#    pip-compile --generate-hashes src/tools/tidy/config/requirements.in
+#    pip-compile --generate-hashes --strip-extras src/tools/tidy/config/requirements.in
 #
 black==23.3.0 \
     --hash=sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5 \
@@ -35,10 +35,6 @@ click==8.1.3 \
     --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \
     --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48
     # via black
-importlib-metadata==6.7.0 \
-    --hash=sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4 \
-    --hash=sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5
-    # via click
 mypy-extensions==1.0.0 \
     --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \
     --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782
@@ -78,40 +74,7 @@ tomli==2.0.1 \
     --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
     --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
     # via black
-typed-ast==1.5.4 \
-    --hash=sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2 \
-    --hash=sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1 \
-    --hash=sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6 \
-    --hash=sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62 \
-    --hash=sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac \
-    --hash=sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d \
-    --hash=sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc \
-    --hash=sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2 \
-    --hash=sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97 \
-    --hash=sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35 \
-    --hash=sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6 \
-    --hash=sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1 \
-    --hash=sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4 \
-    --hash=sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c \
-    --hash=sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e \
-    --hash=sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec \
-    --hash=sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f \
-    --hash=sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72 \
-    --hash=sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47 \
-    --hash=sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72 \
-    --hash=sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe \
-    --hash=sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6 \
-    --hash=sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3 \
-    --hash=sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66
+typing-extensions==4.12.2 \
+    --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
+    --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
     # via black
-typing-extensions==4.6.3 \
-    --hash=sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26 \
-    --hash=sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5
-    # via
-    #   black
-    #   importlib-metadata
-    #   platformdirs
-zipp==3.15.0 \
-    --hash=sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b \
-    --hash=sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556
-    # via importlib-metadata
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index ac89a30f353..f45e9e766a9 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -1,5 +1,4 @@
 run-make/allocator-shim-circular-deps/Makefile
-run-make/allow-non-lint-warnings-cmdline/Makefile
 run-make/archive-duplicate-names/Makefile
 run-make/atomic-lock-free/Makefile
 run-make/branch-protection-check-IBT/Makefile
@@ -12,13 +11,11 @@ run-make/c-unwind-abi-catch-panic/Makefile
 run-make/cat-and-grep-sanity-check/Makefile
 run-make/cdylib-dylib-linkage/Makefile
 run-make/cdylib-fewer-symbols/Makefile
-run-make/codegen-options-parsing/Makefile
 run-make/comment-section/Makefile
 run-make/compiler-lookup-paths-2/Makefile
 run-make/compiler-lookup-paths/Makefile
 run-make/compiler-rt-works-on-mingw/Makefile
 run-make/compressed-debuginfo/Makefile
-run-make/const_fn_mir/Makefile
 run-make/crate-hash-rustc-version/Makefile
 run-make/crate-name-priority/Makefile
 run-make/cross-lang-lto-clang/Makefile
@@ -27,7 +24,6 @@ run-make/cross-lang-lto-upstream-rlibs/Makefile
 run-make/cross-lang-lto/Makefile
 run-make/debug-assertions/Makefile
 run-make/debugger-visualizer-dep-info/Makefile
-run-make/dep-graph/Makefile
 run-make/dep-info-doesnt-run-much/Makefile
 run-make/dep-info-spaces/Makefile
 run-make/dep-info/Makefile
@@ -168,7 +164,6 @@ run-make/pass-linker-flags/Makefile
 run-make/pass-non-c-like-enum-to-c/Makefile
 run-make/pdb-alt-path/Makefile
 run-make/pdb-buildinfo-cl-cmd/Makefile
-run-make/pgo-branch-weights/Makefile
 run-make/pgo-gen-lto/Makefile
 run-make/pgo-gen-no-imp-symbols/Makefile
 run-make/pgo-gen/Makefile
@@ -214,7 +209,6 @@ run-make/sepcomp-cci-copies/Makefile
 run-make/sepcomp-inlining/Makefile
 run-make/sepcomp-separate/Makefile
 run-make/share-generics-dylib/Makefile
-run-make/short-ice/Makefile
 run-make/silly-file-names/Makefile
 run-make/simd-ffi/Makefile
 run-make/split-debuginfo/Makefile
@@ -228,9 +222,6 @@ run-make/std-core-cycle/Makefile
 run-make/symbol-mangling-hashed/Makefile
 run-make/symbol-visibility/Makefile
 run-make/symbols-include-type-name/Makefile
-run-make/symlinked-extern/Makefile
-run-make/symlinked-libraries/Makefile
-run-make/symlinked-rlib/Makefile
 run-make/sysroot-crates-are-unstable/Makefile
 run-make/target-cpu-native/Makefile
 run-make/target-specs/Makefile
diff --git a/src/tools/tidy/src/alphabetical.rs b/src/tools/tidy/src/alphabetical.rs
index 150a9594350..a29286fa2c5 100644
--- a/src/tools/tidy/src/alphabetical.rs
+++ b/src/tools/tidy/src/alphabetical.rs
@@ -88,7 +88,7 @@ fn check_section<'a>(
         let trimmed_line = line.trim_start_matches(' ');
 
         if trimmed_line.starts_with("//")
-            || (trimmed_line.starts_with("#") && !trimmed_line.starts_with("#!"))
+            || (trimmed_line.starts_with('#') && !trimmed_line.starts_with("#!"))
             || trimmed_line.starts_with(is_close_bracket)
         {
             continue;
diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs
index 64ba79dc185..c82e8b6fee9 100644
--- a/src/tools/tidy/src/bins.rs
+++ b/src/tools/tidy/src/bins.rs
@@ -61,7 +61,7 @@ mod os_impl {
                     fs::remove_file(&path).expect("Deleted temp file");
                     // If the file is executable, then we assume that this
                     // filesystem does not track executability, so skip this check.
-                    return if exec { Unsupported } else { Supported };
+                    if exec { Unsupported } else { Supported }
                 }
                 Err(e) => {
                     // If the directory is read-only or we otherwise don't have rights,
@@ -76,7 +76,7 @@ mod os_impl {
 
                     panic!("unable to create temporary file `{:?}`: {:?}", path, e);
                 }
-            };
+            }
         }
 
         for &source_dir in sources {
@@ -92,7 +92,7 @@ mod os_impl {
             }
         }
 
-        return true;
+        true
     }
 
     // FIXME: check when rust-installer test sh files will be removed,
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 2dd3d17f9e3..7337c9843c7 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -699,11 +699,9 @@ fn check_permitted_dependencies(
     for dep in deps {
         let dep = pkg_from_id(metadata, dep);
         // If this path is in-tree, we don't require it to be explicitly permitted.
-        if dep.source.is_some() {
-            if !permitted_dependencies.contains(dep.name.as_str()) {
-                tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id);
-                has_permitted_dep_error = true;
-            }
+        if dep.source.is_some() && !permitted_dependencies.contains(dep.name.as_str()) {
+            tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id);
+            has_permitted_dep_error = true;
         }
     }
 
diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs
index 39f7e70b693..47e2be761e6 100644
--- a/src/tools/tidy/src/error_codes.rs
+++ b/src/tools/tidy/src/error_codes.rs
@@ -308,11 +308,9 @@ fn check_error_codes_tests(
         for line in file.lines() {
             let s = line.trim();
             // Assuming the line starts with `error[E`, we can substring the error code out.
-            if s.starts_with("error[E") {
-                if &s[6..11] == code {
-                    found_code = true;
-                    break;
-                }
+            if s.starts_with("error[E") && &s[6..11] == code {
+                found_code = true;
+                break;
             };
         }
 
diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs
index 2c97a39f100..995ad58cb62 100644
--- a/src/tools/tidy/src/ext_tool_checks.rs
+++ b/src/tools/tidy/src/ext_tool_checks.rs
@@ -24,9 +24,8 @@ use std::io;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
-/// Minimum python revision is 3.7 for ruff
-const MIN_PY_REV: (u32, u32) = (3, 7);
-const MIN_PY_REV_STR: &str = "≥3.7";
+const MIN_PY_REV: (u32, u32) = (3, 9);
+const MIN_PY_REV_STR: &str = "≥3.9";
 
 /// Path to find the python executable within a virtual environment
 #[cfg(target_os = "windows")]
@@ -78,9 +77,9 @@ fn check_impl(
     let mut py_path = None;
 
     let (cfg_args, file_args): (Vec<_>, Vec<_>) = pos_args
-        .into_iter()
+        .iter()
         .map(OsStr::new)
-        .partition(|arg| arg.to_str().is_some_and(|s| s.starts_with("-")));
+        .partition(|arg| arg.to_str().is_some_and(|s| s.starts_with('-')));
 
     if python_lint || python_fmt {
         let venv_path = outdir.join("venv");
@@ -223,17 +222,8 @@ fn get_or_create_venv(venv_path: &Path, src_reqs_path: &Path) -> Result<PathBuf,
 fn create_venv_at_path(path: &Path) -> Result<(), Error> {
     /// Preferred python versions in order. Newest to oldest then current
     /// development versions
-    const TRY_PY: &[&str] = &[
-        "python3.11",
-        "python3.10",
-        "python3.9",
-        "python3.8",
-        "python3.7",
-        "python3",
-        "python",
-        "python3.12",
-        "python3.13",
-    ];
+    const TRY_PY: &[&str] =
+        &["python3.11", "python3.10", "python3.9", "python3", "python", "python3.12", "python3.13"];
 
     let mut sys_py = None;
     let mut found = Vec::new();
@@ -274,13 +264,19 @@ fn create_venv_at_path(path: &Path) -> Result<(), Error> {
     if out.status.success() {
         return Ok(());
     }
-    let err = if String::from_utf8_lossy(&out.stderr).contains("No module named virtualenv") {
-        Error::Generic(format!(
+
+    let stderr = String::from_utf8_lossy(&out.stderr);
+    let err = if stderr.contains("No module named virtualenv") {
+        Error::Generic(
             "virtualenv not found: you may need to install it \
                                (`python3 -m pip install venv`)"
-        ))
+                .to_owned(),
+        )
     } else {
-        Error::Generic(format!("failed to create venv at '{}' using {sys_py}", path.display()))
+        Error::Generic(format!(
+            "failed to create venv at '{}' using {sys_py}: {stderr}",
+            path.display()
+        ))
     };
     Err(err)
 }
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index a6ba8959f0c..3c7284ce6db 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -2760,7 +2760,6 @@ ui/lint/issue-1866.rs
 ui/lint/issue-19102.rs
 ui/lint/issue-20343.rs
 ui/lint/issue-30302.rs
-ui/lint/issue-31924-non-snake-ffi.rs
 ui/lint/issue-34798.rs
 ui/lint/issue-35075.rs
 ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs
@@ -2769,7 +2768,6 @@ ui/lint/issue-54099-camel-case-underscore-types.rs
 ui/lint/issue-57410-1.rs
 ui/lint/issue-57410.rs
 ui/lint/issue-63364.rs
-ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs
 ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs
 ui/lint/issue-79546-fuel-ice.rs
 ui/lint/issue-79744.rs
@@ -2777,7 +2775,6 @@ ui/lint/issue-80988.rs
 ui/lint/issue-81218.rs
 ui/lint/issue-83477.rs
 ui/lint/issue-87274-paren-parent.rs
-ui/lint/issue-89469.rs
 ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs
 ui/lint/issue-97094.rs
 ui/lint/issue-99387.rs
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 64cc2277620..7bcb85335e0 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -444,7 +444,9 @@ pub fn check(path: &Path, bad: &mut bool) {
                 suppressible_tidy_err!(err, skip_cr, "CR character");
             }
             if filename != "style.rs" {
-                if trimmed.contains("TODO") {
+                // Allow using TODO in diagnostic suggestions by marking the
+                // relevant line with `// ignore-tidy-todo`.
+                if trimmed.contains("TODO") && !trimmed.contains("ignore-tidy-todo") {
                     err(
                         "TODO is used for tasks that should be done before merging a PR; If you want to leave a message in the codebase use FIXME",
                     )
@@ -461,10 +463,13 @@ pub fn check(path: &Path, bad: &mut bool) {
                 }
             }
             // for now we just check libcore
-            if trimmed.contains("unsafe {") && !trimmed.starts_with("//") && !last_safety_comment {
-                if file.components().any(|c| c.as_os_str() == "core") && !is_test {
-                    suppressible_tidy_err!(err, skip_undocumented_unsafe, "undocumented unsafe");
-                }
+            if trimmed.contains("unsafe {")
+                && !trimmed.starts_with("//")
+                && !last_safety_comment
+                && file.components().any(|c| c.as_os_str() == "core")
+                && !is_test
+            {
+                suppressible_tidy_err!(err, skip_undocumented_unsafe, "undocumented unsafe");
             }
             if trimmed.contains("// SAFETY:") {
                 last_safety_comment = true;
@@ -485,10 +490,10 @@ pub fn check(path: &Path, bad: &mut bool) {
                     "copyright notices attributed to the Rust Project Developers are deprecated"
                 );
             }
-            if !file.components().any(|c| c.as_os_str() == "rustc_baked_icu_data") {
-                if is_unexplained_ignore(&extension, line) {
-                    err(UNEXPLAINED_IGNORE_DOCTEST_INFO);
-                }
+            if !file.components().any(|c| c.as_os_str() == "rustc_baked_icu_data")
+                && is_unexplained_ignore(&extension, line)
+            {
+                err(UNEXPLAINED_IGNORE_DOCTEST_INFO);
             }
 
             if filename.ends_with(".cpp") && line.contains("llvm_unreachable") {
@@ -523,26 +528,24 @@ pub fn check(path: &Path, bad: &mut bool) {
                         backtick_count += comment_text.chars().filter(|ch| *ch == '`').count();
                     }
                     comment_block = Some((start_line, backtick_count));
-                } else {
-                    if let Some((start_line, backtick_count)) = comment_block.take() {
-                        if backtick_count % 2 == 1 {
-                            let mut err = |msg: &str| {
-                                tidy_error!(bad, "{}:{start_line}: {msg}", file.display());
-                            };
-                            let block_len = (i + 1) - start_line;
-                            if block_len == 1 {
-                                suppressible_tidy_err!(
-                                    err,
-                                    skip_odd_backticks,
-                                    "comment with odd number of backticks"
-                                );
-                            } else {
-                                suppressible_tidy_err!(
-                                    err,
-                                    skip_odd_backticks,
-                                    "{block_len}-line comment block with odd number of backticks"
-                                );
-                            }
+                } else if let Some((start_line, backtick_count)) = comment_block.take() {
+                    if backtick_count % 2 == 1 {
+                        let mut err = |msg: &str| {
+                            tidy_error!(bad, "{}:{start_line}: {msg}", file.display());
+                        };
+                        let block_len = (i + 1) - start_line;
+                        if block_len == 1 {
+                            suppressible_tidy_err!(
+                                err,
+                                skip_odd_backticks,
+                                "comment with odd number of backticks"
+                            );
+                        } else {
+                            suppressible_tidy_err!(
+                                err,
+                                skip_odd_backticks,
+                                "{block_len}-line comment block with odd number of backticks"
+                            );
                         }
                     }
                 }
diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs
index 63a03834166..1cecf998e28 100644
--- a/src/tools/tidy/src/walk.rs
+++ b/src/tools/tidy/src/walk.rs
@@ -79,13 +79,11 @@ pub(crate) fn walk_no_read(
     let walker = walker.filter_entry(move |e| {
         !skip(e.path(), e.file_type().map(|ft| ft.is_dir()).unwrap_or(false))
     });
-    for entry in walker.build() {
-        if let Ok(entry) = entry {
-            if entry.file_type().map_or(true, |kind| kind.is_dir() || kind.is_symlink()) {
-                continue;
-            }
-            f(&entry);
+    for entry in walker.build().flatten() {
+        if entry.file_type().map_or(true, |kind| kind.is_dir() || kind.is_symlink()) {
+            continue;
         }
+        f(&entry);
     }
 }
 
@@ -97,11 +95,9 @@ pub(crate) fn walk_dir(
 ) {
     let mut walker = ignore::WalkBuilder::new(path);
     let walker = walker.filter_entry(move |e| !skip(e.path()));
-    for entry in walker.build() {
-        if let Ok(entry) = entry {
-            if entry.path().is_dir() {
-                f(&entry);
-            }
+    for entry in walker.build().flatten() {
+        if entry.path().is_dir() {
+            f(&entry);
         }
     }
 }
diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs
index c470d502a65..55bfbed8b0e 100644
--- a/src/tools/tidy/src/x_version.rs
+++ b/src/tools/tidy/src/x_version.rs
@@ -52,7 +52,7 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
             );
         }
     } else {
-        return tidy_error!(bad, "failed to check version of `x`: {}", cargo_list.status);
+        tidy_error!(bad, "failed to check version of `x`: {}", cargo_list.status)
     }
 }
 
diff --git a/tests/assembly/asm/x86-types.rs b/tests/assembly/asm/x86-types.rs
index 2b4ebb05349..8e229614420 100644
--- a/tests/assembly/asm/x86-types.rs
+++ b/tests/assembly/asm/x86-types.rs
@@ -7,7 +7,7 @@
 //@ compile-flags: -C llvm-args=--x86-asm-syntax=intel
 //@ compile-flags: -C target-feature=+avx512bw
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, f16, f128)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
@@ -41,6 +41,8 @@ pub struct i32x4(i32, i32, i32, i32);
 #[repr(simd)]
 pub struct i64x2(i64, i64);
 #[repr(simd)]
+pub struct f16x8(f16, f16, f16, f16, f16, f16, f16, f16);
+#[repr(simd)]
 pub struct f32x4(f32, f32, f32, f32);
 #[repr(simd)]
 pub struct f64x2(f64, f64);
@@ -87,6 +89,8 @@ pub struct i32x8(i32, i32, i32, i32, i32, i32, i32, i32);
 #[repr(simd)]
 pub struct i64x4(i64, i64, i64, i64);
 #[repr(simd)]
+pub struct f16x16(f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16);
+#[repr(simd)]
 pub struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32);
 #[repr(simd)]
 pub struct f64x4(f64, f64, f64, f64);
@@ -198,35 +202,59 @@ pub struct i32x16(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i3
 #[repr(simd)]
 pub struct i64x8(i64, i64, i64, i64, i64, i64, i64, i64);
 #[repr(simd)]
+pub struct f16x32(
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+    f16,
+);
+#[repr(simd)]
 pub struct f32x16(f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32);
 #[repr(simd)]
 pub struct f64x8(f64, f64, f64, f64, f64, f64, f64, f64);
 
-impl Copy for i8 {}
-impl Copy for i16 {}
-impl Copy for i32 {}
-impl Copy for f32 {}
-impl Copy for i64 {}
-impl Copy for f64 {}
-impl Copy for ptr {}
-impl Copy for i8x16 {}
-impl Copy for i16x8 {}
-impl Copy for i32x4 {}
-impl Copy for i64x2 {}
-impl Copy for f32x4 {}
-impl Copy for f64x2 {}
-impl Copy for i8x32 {}
-impl Copy for i16x16 {}
-impl Copy for i32x8 {}
-impl Copy for i64x4 {}
-impl Copy for f32x8 {}
-impl Copy for f64x4 {}
-impl Copy for i8x64 {}
-impl Copy for i16x32 {}
-impl Copy for i32x16 {}
-impl Copy for i64x8 {}
-impl Copy for f32x16 {}
-impl Copy for f64x8 {}
+macro_rules! impl_copy {
+    ($($ty:ident)*) => {
+        $(
+            impl Copy for $ty {}
+        )*
+    };
+}
+
+impl_copy!(
+    i8 i16 f16 i32 f32 i64 f64 f128 ptr
+    i8x16 i16x8 i32x4 i64x2 f16x8 f32x4 f64x2
+    i8x32 i16x16 i32x8 i64x4 f16x16 f32x8 f64x4
+    i8x64 i16x32 i32x16 i64x8 f16x32 f32x16 f64x8
+);
 
 extern "C" {
     fn extern_func();
@@ -292,6 +320,13 @@ macro_rules! check_reg {
 // CHECK: #NO_APP
 check!(reg_i16 i16 reg "mov");
 
+// CHECK-LABEL: reg_f16:
+// CHECK: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f16 f16 reg "mov");
+
 // CHECK-LABEL: reg_i32:
 // CHECK: #APP
 // x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
@@ -334,6 +369,13 @@ check!(reg_ptr ptr reg "mov");
 // CHECK: #NO_APP
 check!(reg_abcd_i16 i16 reg_abcd "mov");
 
+// CHECK-LABEL: reg_abcd_f16:
+// CHECK: #APP
+// x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
+// i686: mov e{{[a-z0-9]+}}, e{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_abcd_f16 f16 reg_abcd "mov");
+
 // CHECK-LABEL: reg_abcd_i32:
 // CHECK: #APP
 // x86_64: mov r{{[a-z0-9]+}}, r{{[a-z0-9]+}}
@@ -375,6 +417,12 @@ check!(reg_abcd_ptr ptr reg_abcd "mov");
 // CHECK: #NO_APP
 check!(reg_byte i8 reg_byte "mov");
 
+// CHECK-LABEL: xmm_reg_f16:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_f16 f16 xmm_reg "movaps");
+
 // CHECK-LABEL: xmm_reg_i32:
 // CHECK: #APP
 // CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
@@ -399,6 +447,12 @@ check!(xmm_reg_i64 i64 xmm_reg "movaps");
 // CHECK: #NO_APP
 check!(xmm_reg_f64 f64 xmm_reg "movaps");
 
+// CHECK-LABEL: xmm_reg_f128:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_f128 f128 xmm_reg "movaps");
+
 // CHECK-LABEL: xmm_reg_ptr:
 // CHECK: #APP
 // CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
@@ -429,6 +483,12 @@ check!(xmm_reg_i32x4 i32x4 xmm_reg "movaps");
 // CHECK: #NO_APP
 check!(xmm_reg_i64x2 i64x2 xmm_reg "movaps");
 
+// CHECK-LABEL: xmm_reg_f16x8:
+// CHECK: #APP
+// CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(xmm_reg_f16x8 f16x8 xmm_reg "movaps");
+
 // CHECK-LABEL: xmm_reg_f32x4:
 // CHECK: #APP
 // CHECK: movaps xmm{{[0-9]+}}, xmm{{[0-9]+}}
@@ -441,6 +501,12 @@ check!(xmm_reg_f32x4 f32x4 xmm_reg "movaps");
 // CHECK: #NO_APP
 check!(xmm_reg_f64x2 f64x2 xmm_reg "movaps");
 
+// CHECK-LABEL: ymm_reg_f16:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f16 f16 ymm_reg "vmovaps");
+
 // CHECK-LABEL: ymm_reg_i32:
 // CHECK: #APP
 // CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
@@ -465,6 +531,12 @@ check!(ymm_reg_i64 i64 ymm_reg "vmovaps");
 // CHECK: #NO_APP
 check!(ymm_reg_f64 f64 ymm_reg "vmovaps");
 
+// CHECK-LABEL: ymm_reg_f128:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f128 f128 ymm_reg "vmovaps");
+
 // CHECK-LABEL: ymm_reg_ptr:
 // CHECK: #APP
 // CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
@@ -495,6 +567,12 @@ check!(ymm_reg_i32x4 i32x4 ymm_reg "vmovaps");
 // CHECK: #NO_APP
 check!(ymm_reg_i64x2 i64x2 ymm_reg "vmovaps");
 
+// CHECK-LABEL: ymm_reg_f16x8:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f16x8 f16x8 ymm_reg "vmovaps");
+
 // CHECK-LABEL: ymm_reg_f32x4:
 // CHECK: #APP
 // CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
@@ -531,6 +609,12 @@ check!(ymm_reg_i32x8 i32x8 ymm_reg "vmovaps");
 // CHECK: #NO_APP
 check!(ymm_reg_i64x4 i64x4 ymm_reg "vmovaps");
 
+// CHECK-LABEL: ymm_reg_f16x16:
+// CHECK: #APP
+// CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(ymm_reg_f16x16 f16x16 ymm_reg "vmovaps");
+
 // CHECK-LABEL: ymm_reg_f32x8:
 // CHECK: #APP
 // CHECK: vmovaps ymm{{[0-9]+}}, ymm{{[0-9]+}}
@@ -543,6 +627,12 @@ check!(ymm_reg_f32x8 f32x8 ymm_reg "vmovaps");
 // CHECK: #NO_APP
 check!(ymm_reg_f64x4 f64x4 ymm_reg "vmovaps");
 
+// CHECK-LABEL: zmm_reg_f16:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f16 f16 zmm_reg "vmovaps");
+
 // CHECK-LABEL: zmm_reg_i32:
 // CHECK: #APP
 // CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
@@ -567,6 +657,12 @@ check!(zmm_reg_i64 i64 zmm_reg "vmovaps");
 // CHECK: #NO_APP
 check!(zmm_reg_f64 f64 zmm_reg "vmovaps");
 
+// CHECK-LABEL: zmm_reg_f128:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f128 f128 zmm_reg "vmovaps");
+
 // CHECK-LABEL: zmm_reg_ptr:
 // CHECK: #APP
 // CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
@@ -597,6 +693,12 @@ check!(zmm_reg_i32x4 i32x4 zmm_reg "vmovaps");
 // CHECK: #NO_APP
 check!(zmm_reg_i64x2 i64x2 zmm_reg "vmovaps");
 
+// CHECK-LABEL: zmm_reg_f16x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f16x8 f16x8 zmm_reg "vmovaps");
+
 // CHECK-LABEL: zmm_reg_f32x4:
 // CHECK: #APP
 // CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
@@ -633,6 +735,12 @@ check!(zmm_reg_i32x8 i32x8 zmm_reg "vmovaps");
 // CHECK: #NO_APP
 check!(zmm_reg_i64x4 i64x4 zmm_reg "vmovaps");
 
+// CHECK-LABEL: zmm_reg_f16x16:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f16x16 f16x16 zmm_reg "vmovaps");
+
 // CHECK-LABEL: zmm_reg_f32x8:
 // CHECK: #APP
 // CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
@@ -669,6 +777,12 @@ check!(zmm_reg_i32x16 i32x16 zmm_reg "vmovaps");
 // CHECK: #NO_APP
 check!(zmm_reg_i64x8 i64x8 zmm_reg "vmovaps");
 
+// CHECK-LABEL: zmm_reg_f16x32:
+// CHECK: #APP
+// CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
+// CHECK: #NO_APP
+check!(zmm_reg_f16x32 f16x32 zmm_reg "vmovaps");
+
 // CHECK-LABEL: zmm_reg_f32x16:
 // CHECK: #APP
 // CHECK: vmovaps zmm{{[0-9]+}}, zmm{{[0-9]+}}
@@ -717,6 +831,12 @@ check!(kreg_ptr ptr kreg "kmovq");
 // CHECK: #NO_APP
 check_reg!(eax_i16 i16 "eax" "mov");
 
+// CHECK-LABEL: eax_f16:
+// CHECK: #APP
+// CHECK: mov eax, eax
+// CHECK: #NO_APP
+check_reg!(eax_f16 f16 "eax" "mov");
+
 // CHECK-LABEL: eax_i32:
 // CHECK: #APP
 // CHECK: mov eax, eax
@@ -756,6 +876,12 @@ check_reg!(eax_ptr ptr "eax" "mov");
 #[cfg(i686)]
 check_reg!(ah_byte i8 "ah" "mov");
 
+// CHECK-LABEL: xmm0_f16:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_f16 f16 "xmm0" "movaps");
+
 // CHECK-LABEL: xmm0_i32:
 // CHECK: #APP
 // CHECK: movaps xmm0, xmm0
@@ -780,6 +906,12 @@ check_reg!(xmm0_i64 i64 "xmm0" "movaps");
 // CHECK: #NO_APP
 check_reg!(xmm0_f64 f64 "xmm0" "movaps");
 
+// CHECK-LABEL: xmm0_f128:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_f128 f128 "xmm0" "movaps");
+
 // CHECK-LABEL: xmm0_ptr:
 // CHECK: #APP
 // CHECK: movaps xmm0, xmm0
@@ -810,6 +942,12 @@ check_reg!(xmm0_i32x4 i32x4 "xmm0" "movaps");
 // CHECK: #NO_APP
 check_reg!(xmm0_i64x2 i64x2 "xmm0" "movaps");
 
+// CHECK-LABEL: xmm0_f16x8:
+// CHECK: #APP
+// CHECK: movaps xmm0, xmm0
+// CHECK: #NO_APP
+check_reg!(xmm0_f16x8 f16x8 "xmm0" "movaps");
+
 // CHECK-LABEL: xmm0_f32x4:
 // CHECK: #APP
 // CHECK: movaps xmm0, xmm0
@@ -822,6 +960,12 @@ check_reg!(xmm0_f32x4 f32x4 "xmm0" "movaps");
 // CHECK: #NO_APP
 check_reg!(xmm0_f64x2 f64x2 "xmm0" "movaps");
 
+// CHECK-LABEL: ymm0_f16:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f16 f16 "ymm0" "vmovaps");
+
 // CHECK-LABEL: ymm0_i32:
 // CHECK: #APP
 // CHECK: vmovaps ymm0, ymm0
@@ -846,6 +990,12 @@ check_reg!(ymm0_i64 i64 "ymm0" "vmovaps");
 // CHECK: #NO_APP
 check_reg!(ymm0_f64 f64 "ymm0" "vmovaps");
 
+// CHECK-LABEL: ymm0_f128:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f128 f128 "ymm0" "vmovaps");
+
 // CHECK-LABEL: ymm0_ptr:
 // CHECK: #APP
 // CHECK: vmovaps ymm0, ymm0
@@ -876,6 +1026,12 @@ check_reg!(ymm0_i32x4 i32x4 "ymm0" "vmovaps");
 // CHECK: #NO_APP
 check_reg!(ymm0_i64x2 i64x2 "ymm0" "vmovaps");
 
+// CHECK-LABEL: ymm0_f16x8:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f16x8 f16x8 "ymm0" "vmovaps");
+
 // CHECK-LABEL: ymm0_f32x4:
 // CHECK: #APP
 // CHECK: vmovaps ymm0, ymm0
@@ -912,6 +1068,12 @@ check_reg!(ymm0_i32x8 i32x8 "ymm0" "vmovaps");
 // CHECK: #NO_APP
 check_reg!(ymm0_i64x4 i64x4 "ymm0" "vmovaps");
 
+// CHECK-LABEL: ymm0_f16x16:
+// CHECK: #APP
+// CHECK: vmovaps ymm0, ymm0
+// CHECK: #NO_APP
+check_reg!(ymm0_f16x16 f16x16 "ymm0" "vmovaps");
+
 // CHECK-LABEL: ymm0_f32x8:
 // CHECK: #APP
 // CHECK: vmovaps ymm0, ymm0
@@ -924,6 +1086,12 @@ check_reg!(ymm0_f32x8 f32x8 "ymm0" "vmovaps");
 // CHECK: #NO_APP
 check_reg!(ymm0_f64x4 f64x4 "ymm0" "vmovaps");
 
+// CHECK-LABEL: zmm0_f16:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f16 f16 "zmm0" "vmovaps");
+
 // CHECK-LABEL: zmm0_i32:
 // CHECK: #APP
 // CHECK: vmovaps zmm0, zmm0
@@ -948,6 +1116,12 @@ check_reg!(zmm0_i64 i64 "zmm0" "vmovaps");
 // CHECK: #NO_APP
 check_reg!(zmm0_f64 f64 "zmm0" "vmovaps");
 
+// CHECK-LABEL: zmm0_f128:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f128 f128 "zmm0" "vmovaps");
+
 // CHECK-LABEL: zmm0_ptr:
 // CHECK: #APP
 // CHECK: vmovaps zmm0, zmm0
@@ -978,6 +1152,12 @@ check_reg!(zmm0_i32x4 i32x4 "zmm0" "vmovaps");
 // CHECK: #NO_APP
 check_reg!(zmm0_i64x2 i64x2 "zmm0" "vmovaps");
 
+// CHECK-LABEL: zmm0_f16x8:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f16x8 f16x8 "zmm0" "vmovaps");
+
 // CHECK-LABEL: zmm0_f32x4:
 // CHECK: #APP
 // CHECK: vmovaps zmm0, zmm0
@@ -1014,6 +1194,12 @@ check_reg!(zmm0_i32x8 i32x8 "zmm0" "vmovaps");
 // CHECK: #NO_APP
 check_reg!(zmm0_i64x4 i64x4 "zmm0" "vmovaps");
 
+// CHECK-LABEL: zmm0_f16x16:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f16x16 f16x16 "zmm0" "vmovaps");
+
 // CHECK-LABEL: zmm0_f32x8:
 // CHECK: #APP
 // CHECK: vmovaps zmm0, zmm0
@@ -1050,6 +1236,12 @@ check_reg!(zmm0_i32x16 i32x16 "zmm0" "vmovaps");
 // CHECK: #NO_APP
 check_reg!(zmm0_i64x8 i64x8 "zmm0" "vmovaps");
 
+// CHECK-LABEL: zmm0_f16x32:
+// CHECK: #APP
+// CHECK: vmovaps zmm0, zmm0
+// CHECK: #NO_APP
+check_reg!(zmm0_f16x32 f16x32 "zmm0" "vmovaps");
+
 // CHECK-LABEL: zmm0_f32x16:
 // CHECK: #APP
 // CHECK: vmovaps zmm0, zmm0
diff --git a/tests/assembly/issue-83585-small-pod-struct-equality.rs b/tests/assembly/issue-83585-small-pod-struct-equality.rs
new file mode 100644
index 00000000000..14bec1337f0
--- /dev/null
+++ b/tests/assembly/issue-83585-small-pod-struct-equality.rs
@@ -0,0 +1,27 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3
+//@ only-x86_64
+
+#![crate_type = "lib"]
+
+type T = u8;
+type T1 = (T, T, T, T, T, T, T, T);
+
+// CHECK-LABEL: foo1a
+// CHECK: cmpq
+// CHECK-NEXT: sete
+// CHECK-NEXT: {{retq|popq}}
+#[no_mangle]
+pub fn foo1a(a: T1, b: T1) -> bool {
+    a == b
+}
+
+// CHECK-LABEL: foo1b
+// CHECK: movq
+// CHECK: cmpq
+// CHECK-NEXT: sete
+// CHECK-NEXT: {{retq|popq}}
+#[no_mangle]
+pub fn foo1b(a: &T1, b: &T1) -> bool {
+    a == b
+}
diff --git a/tests/codegen/instrument-coverage/instrument-coverage-off.rs b/tests/codegen/instrument-coverage/instrument-coverage-off.rs
index 616e3295e5b..e44d6c65874 100644
--- a/tests/codegen/instrument-coverage/instrument-coverage-off.rs
+++ b/tests/codegen/instrument-coverage/instrument-coverage-off.rs
@@ -1,5 +1,6 @@
 // Test that `-Cinstrument-coverage=off` does not add coverage instrumentation to LLVM IR.
 
+//@ compile-flags: -Zno-profiler-runtime
 //@ revisions: n no off false_ zero
 //@ [n] compile-flags: -Cinstrument-coverage=n
 //@ [no] compile-flags: -Cinstrument-coverage=no
diff --git a/tests/codegen/instrument-coverage/instrument-coverage.rs b/tests/codegen/instrument-coverage/instrument-coverage.rs
index 65fa437d250..23d23651c72 100644
--- a/tests/codegen/instrument-coverage/instrument-coverage.rs
+++ b/tests/codegen/instrument-coverage/instrument-coverage.rs
@@ -1,6 +1,6 @@
 // Test that `-Cinstrument-coverage` creates expected __llvm_profile_filename symbol in LLVM IR.
 
-//@ needs-profiler-support
+//@ compile-flags: -Zno-profiler-runtime
 //@ revisions: default y yes on true_ all
 //@ [default] compile-flags: -Cinstrument-coverage
 //@ [y] compile-flags: -Cinstrument-coverage=y
@@ -9,8 +9,8 @@
 //@ [true_] compile-flags: -Cinstrument-coverage=true
 //@ [all] compile-flags: -Cinstrument-coverage=all
 
-// CHECK: @__llvm_profile_filename = {{.*}}"default_%m_%p.profraw\00"{{.*}}
-// CHECK: @__llvm_coverage_mapping
+// CHECK-DAG: @__llvm_coverage_mapping
+// CHECK-DAG: @__llvm_profile_filename = {{.*}}"default_%m_%p.profraw\00"{{.*}}
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/instrument-coverage/testprog.rs b/tests/codegen/instrument-coverage/testprog.rs
index acc4f35d905..eea4d9cb3cf 100644
--- a/tests/codegen/instrument-coverage/testprog.rs
+++ b/tests/codegen/instrument-coverage/testprog.rs
@@ -1,5 +1,5 @@
 //@ edition: 2021
-//@ needs-profiler-support
+//@ compile-flags: -Zno-profiler-runtime
 //@ compile-flags: -Cinstrument-coverage -Copt-level=0
 //@ revisions: LINUX DARWIN WINDOWS
 
diff --git a/tests/codegen/issues/issue-109328-split_first.rs b/tests/codegen/issues/issue-109328-split_first.rs
new file mode 100644
index 00000000000..7f7957593d2
--- /dev/null
+++ b/tests/codegen/issues/issue-109328-split_first.rs
@@ -0,0 +1,16 @@
+//@ compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @foo
+// CHECK-NEXT: {{.*}}:
+// CHECK-NEXT: getelementptr inbounds
+// CHECK-NEXT: load [[TYPE:i(32|64)]]
+// CHECK-NEXT: icmp eq [[TYPE]]
+// CHECK-NEXT: br i1
+#[no_mangle]
+pub fn foo(input: &mut &[u64]) -> Option<u64> {
+    let (first, rest) = input.split_first()?;
+    *input = rest;
+    Some(*first)
+}
diff --git a/tests/codegen/issues/issue-110797-enum-jump-same.rs b/tests/codegen/issues/issue-110797-enum-jump-same.rs
new file mode 100644
index 00000000000..f34b191ac70
--- /dev/null
+++ b/tests/codegen/issues/issue-110797-enum-jump-same.rs
@@ -0,0 +1,26 @@
+//@ compile-flags: -O
+//@ min-llvm-version: 18
+
+#![crate_type = "lib"]
+
+pub enum K {
+    A(Box<[i32]>),
+    B(Box<[u8]>),
+    C(Box<[String]>),
+    D(Box<[u16]>),
+}
+
+// CHECK-LABEL: @get_len
+// CHECK-NEXT: {{.*}}:
+// CHECK-NEXT: getelementptr inbounds
+// CHECK-NEXT: load [[TYPE:i(32|64)]]
+// CHECK-NEXT: ret [[TYPE]]
+#[no_mangle]
+pub fn get_len(arg: &K) -> usize {
+    match arg {
+        K::A(ref lst) => lst.len(),
+        K::B(ref lst) => lst.len(),
+        K::C(ref lst) => lst.len(),
+        K::D(ref lst) => lst.len(),
+    }
+}
diff --git a/tests/codegen/issues/issue-111508-vec-tryinto-array.rs b/tests/codegen/issues/issue-111508-vec-tryinto-array.rs
new file mode 100644
index 00000000000..6415724b40a
--- /dev/null
+++ b/tests/codegen/issues/issue-111508-vec-tryinto-array.rs
@@ -0,0 +1,22 @@
+//@ compile-flags: -O
+// This regress since Rust version 1.72.
+//@ min-llvm-version: 18.1.4
+
+#![crate_type = "lib"]
+
+use std::convert::TryInto;
+
+const N: usize = 24;
+
+// CHECK-LABEL: @example
+// CHECK-NOT: unwrap_failed
+#[no_mangle]
+pub fn example(a: Vec<u8>) -> u8 {
+    if a.len() != 32 {
+        return 0;
+    }
+
+    let a: [u8; 32] = a.try_into().unwrap();
+
+    a[15] + a[N]
+}
diff --git a/tests/codegen/issues/issue-112509-slice-get-andthen-get.rs b/tests/codegen/issues/issue-112509-slice-get-andthen-get.rs
new file mode 100644
index 00000000000..ae02c3fb79e
--- /dev/null
+++ b/tests/codegen/issues/issue-112509-slice-get-andthen-get.rs
@@ -0,0 +1,12 @@
+//@ compile-flags: -O
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @write_u8_variant_a
+// CHECK-NEXT: {{.*}}:
+// CHECK-NEXT: getelementptr
+// CHECK-NEXT: icmp ugt
+#[no_mangle]
+pub fn write_u8_variant_a(bytes: &mut [u8], buf: u8, offset: usize) -> Option<&mut [u8]> {
+    let buf = buf.to_le_bytes();
+    bytes.get_mut(offset..).and_then(|bytes| bytes.get_mut(..buf.len()))
+}
diff --git a/tests/codegen/issues/issue-113757-bounds-check-after-cmp-max.rs b/tests/codegen/issues/issue-113757-bounds-check-after-cmp-max.rs
new file mode 100644
index 00000000000..d495adf9980
--- /dev/null
+++ b/tests/codegen/issues/issue-113757-bounds-check-after-cmp-max.rs
@@ -0,0 +1,18 @@
+// in Rust 1.73, -O and opt-level=3 optimizes differently
+//@ compile-flags: -C opt-level=3
+#![crate_type = "lib"]
+
+use std::cmp::max;
+
+// CHECK-LABEL: @foo
+// CHECK-NOT: slice_start_index_len_fail
+// CHECK-NOT: unreachable
+#[no_mangle]
+pub fn foo(v: &mut Vec<u8>, size: usize) -> Option<&mut [u8]> {
+    if v.len() > max(1, size) {
+        let start = v.len() - size;
+        Some(&mut v[start..])
+    } else {
+        None
+    }
+}
diff --git a/tests/codegen/issues/issue-118392.rs b/tests/codegen/issues/issue-118392.rs
new file mode 100644
index 00000000000..2cbb1f8b204
--- /dev/null
+++ b/tests/codegen/issues/issue-118392.rs
@@ -0,0 +1,11 @@
+//@ compile-flags: -O
+//@ min-llvm-version: 18
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @div2
+// CHECK: ashr i32 %a, 1
+// CHECK-NEXT: ret i32
+#[no_mangle]
+pub fn div2(a: i32) -> i32 {
+    a.div_euclid(2)
+}
diff --git a/tests/codegen/issues/issue-36010-some-box-is_some.rs b/tests/codegen/issues/issue-36010-some-box-is_some.rs
new file mode 100644
index 00000000000..44c01096f15
--- /dev/null
+++ b/tests/codegen/issues/issue-36010-some-box-is_some.rs
@@ -0,0 +1,28 @@
+#![crate_type = "lib"]
+
+//@ compile-flags: -O
+
+use std::mem;
+
+fn foo<T>(a: &mut T, b: T) -> bool {
+    let b = Some(mem::replace(a, b));
+    let ret = b.is_some();
+    mem::forget(b);
+    return ret;
+}
+
+// CHECK-LABEL: @foo_u32
+// CHECK: store i32
+// CHECK-NEXT: ret i1 true
+#[no_mangle]
+pub fn foo_u32(a: &mut u32, b: u32) -> bool {
+    foo(a, b)
+}
+
+// CHECK-LABEL: @foo_box
+// CHECK: store ptr
+// CHECK-NEXT: ret i1 true
+#[no_mangle]
+pub fn foo_box(a: &mut Box<u32>, b: Box<u32>) -> bool {
+    foo(a, b)
+}
diff --git a/tests/codegen/issues/issue-68667-unwrap-combinators.rs b/tests/codegen/issues/issue-68667-unwrap-combinators.rs
new file mode 100644
index 00000000000..6bd4c566a0c
--- /dev/null
+++ b/tests/codegen/issues/issue-68667-unwrap-combinators.rs
@@ -0,0 +1,15 @@
+#![crate_type = "lib"]
+
+//@ compile-flags: -O
+
+// MIR inlining now optimizes this code.
+
+// CHECK-LABEL: @unwrap_combinators
+// CHECK: icmp
+// CHECK-NEXT: icmp
+// CHECK-NEXT: select i1
+// CHECK-NEXT: ret i1
+#[no_mangle]
+pub fn unwrap_combinators(a: Option<i32>, b: i32) -> bool {
+    a.map(|t| t >= b).unwrap_or(false)
+}
diff --git a/tests/codegen/issues/issue-74938-array-split-at.rs b/tests/codegen/issues/issue-74938-array-split-at.rs
new file mode 100644
index 00000000000..2675e404ced
--- /dev/null
+++ b/tests/codegen/issues/issue-74938-array-split-at.rs
@@ -0,0 +1,14 @@
+//@ compile-flags: -O
+
+#![crate_type = "lib"]
+
+const N: usize = 3;
+pub type T = u8;
+
+// CHECK-LABEL: @split_multiple
+// CHECK-NOT: unreachable
+#[no_mangle]
+pub fn split_multiple(slice: &[T]) -> (&[T], &[T]) {
+    let len = slice.len() / N;
+    slice.split_at(len * N)
+}
diff --git a/tests/codegen/issues/issue-93036-assert-index.rs b/tests/codegen/issues/issue-93036-assert-index.rs
new file mode 100644
index 00000000000..7a2ea087266
--- /dev/null
+++ b/tests/codegen/issues/issue-93036-assert-index.rs
@@ -0,0 +1,14 @@
+//@ compile-flags: -O
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+// CHECK-LABEL: @foo
+// CHECK-NOT: unreachable
+pub fn foo(arr: &mut [u32]) {
+    for i in 0..arr.len() {
+        for j in 0..i {
+            assert!(j < arr.len());
+        }
+    }
+}
diff --git a/tests/codegen/naked-fn/naked-nocoverage.rs b/tests/codegen/naked-fn/naked-nocoverage.rs
index e8d3b5834fa..d73c5b7fd26 100644
--- a/tests/codegen/naked-fn/naked-nocoverage.rs
+++ b/tests/codegen/naked-fn/naked-nocoverage.rs
@@ -2,7 +2,7 @@
 // Regression test for issue #105170.
 //
 //@ needs-asm-support
-//@ needs-profiler-support
+//@ compile-flags: -Zno-profiler-runtime
 //@ compile-flags: -Cinstrument-coverage
 #![crate_type = "lib"]
 #![feature(naked_functions)]
diff --git a/tests/codegen/pgo-counter-bias.rs b/tests/codegen/pgo-counter-bias.rs
index 87d31073d5a..48e815dda04 100644
--- a/tests/codegen/pgo-counter-bias.rs
+++ b/tests/codegen/pgo-counter-bias.rs
@@ -2,7 +2,7 @@
 
 //@ ignore-apple -runtime-counter-relocation not honored on Mach-O
 //@ compile-flags: -Cprofile-generate -Cllvm-args=-runtime-counter-relocation -Clto=fat
-//@ needs-profiler-support
+//@ compile-flags: -Zno-profiler-runtime
 //@ no-prefer-dynamic
 
 // CHECK: @__llvm_profile_counter_bias = {{.*}}global
diff --git a/tests/codegen/pgo-instrumentation.rs b/tests/codegen/pgo-instrumentation.rs
index b1906c145c6..a8f12ccce1c 100644
--- a/tests/codegen/pgo-instrumentation.rs
+++ b/tests/codegen/pgo-instrumentation.rs
@@ -1,6 +1,6 @@
 // Test that `-Cprofile-generate` creates expected instrumentation artifacts in LLVM IR.
 
-//@ needs-profiler-support
+//@ compile-flags: -Zno-profiler-runtime
 //@ compile-flags: -Cprofile-generate -Ccodegen-units=1
 
 // CHECK: @__llvm_profile_raw_version =
diff --git a/tests/codegen/slice-pointer-nonnull-unwrap.rs b/tests/codegen/slice-pointer-nonnull-unwrap.rs
new file mode 100644
index 00000000000..2c4a959685f
--- /dev/null
+++ b/tests/codegen/slice-pointer-nonnull-unwrap.rs
@@ -0,0 +1,19 @@
+//@ compile-flags: -O
+//@ min-llvm-version: 18
+#![crate_type = "lib"]
+
+use std::ptr::NonNull;
+
+// CHECK-LABEL: @slice_ptr_len_1
+// CHECK-NEXT: {{.*}}:
+// CHECK-NEXT: ret {{i(32|64)}} %ptr.1
+#[no_mangle]
+pub fn slice_ptr_len_1(ptr: *const [u8]) -> usize {
+    let ptr = ptr.cast_mut();
+    if let Some(ptr) = NonNull::new(ptr) {
+        ptr.len()
+    } else {
+        // We know ptr is null, so we know ptr.wrapping_byte_add(1) is not null.
+        NonNull::new(ptr.wrapping_byte_add(1)).unwrap().len()
+    }
+}
diff --git a/tests/crashes/109812.rs b/tests/crashes/109812.rs
deleted file mode 100644
index c29b8746521..00000000000
--- a/tests/crashes/109812.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//@ known-bug: #109812
-
-#![warn(rust_2021_incompatible_closure_captures)]
-
-enum Either {
-    One(X),
-    Two(X),
-}
-
-struct X(Y);
-
-struct Y;
-
-fn move_into_fnmut() {
-    let x = X(Y);
-
-    consume_fnmut(|| {
-        let Either::Two(ref mut _t) = x;
-
-        let X(mut _t) = x;
-    });
-}
diff --git a/tests/crashes/124583.rs b/tests/crashes/124583.rs
deleted file mode 100644
index ffd9d7521ad..00000000000
--- a/tests/crashes/124583.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-//@ known-bug: rust-lang/rust#124583
-
-fn main() {
-    let _ = -(-0.0f16);
-}
diff --git a/tests/crashes/125811.rs b/tests/crashes/125811.rs
deleted file mode 100644
index eb764e8d152..00000000000
--- a/tests/crashes/125811.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-//@ known-bug: rust-lang/rust#125811
-mod assert {
-    use std::mem::{Assume, BikeshedIntrinsicFrom};
-
-    pub fn is_transmutable<Src, Dst>()
-    where
-        Dst: BikeshedIntrinsicFrom<Src>,
-    {
-    }
-}
-
-#[repr(C)]
-struct Zst;
-
-enum V0 {
-    B(!),
-}
-
-enum V2 {
-    V = 2,
-}
-
-enum Lopsided {
-    Smol(Zst),
-    Lorg(V0),
-}
-
-#[repr(C)]
-#[repr(C)]
-struct Dst(Lopsided, V2);
-
-fn should_pad_variants() {
-    assert::is_transmutable::<Src, Dst>();
-}
diff --git a/tests/crashes/125914.rs b/tests/crashes/125914.rs
deleted file mode 100644
index 77ccb9fb097..00000000000
--- a/tests/crashes/125914.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ known-bug: rust-lang/rust#125914
-enum AstKind<'ast> {
-    ExprInt,
-}
-
-enum Foo {
-    Bar(isize),
-    Baz,
-}
-
-enum Other {
-    Other1(Foo),
-    Other2(AstKind),
-}
-
-fn main() {
-    match Other::Other1(Foo::Baz) {
-        ::Other::Other2(::Foo::Bar(..)) => {}
-    }
-}
diff --git a/tests/run-make/allow-non-lint-warnings-cmdline/Makefile b/tests/run-make/allow-non-lint-warnings-cmdline/Makefile
deleted file mode 100644
index 78b9a7b9898..00000000000
--- a/tests/run-make/allow-non-lint-warnings-cmdline/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# Test that -A warnings makes the 'empty trait list for derive' warning go away
-OUT=$(shell $(RUSTC) foo.rs -A warnings 2>&1 | grep "warning" )
-
-all: foo
-	test -z '$(OUT)'
-
-# This is just to make sure the above command actually succeeds
-foo:
-	$(RUSTC) foo.rs -A warnings
diff --git a/tests/run-make/codegen-options-parsing/Makefile b/tests/run-make/codegen-options-parsing/Makefile
deleted file mode 100644
index beaf233502b..00000000000
--- a/tests/run-make/codegen-options-parsing/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
-# This test intentionally feeds invalid inputs to codegen and checks if the error message outputs contain specific helpful indications.
-
-# ignore-cross-compile
-include ../tools.mk
-
-all:
-	#Option taking a number
-	$(RUSTC) -C codegen-units dummy.rs 2>&1 | \
-		$(CGREP) 'codegen option `codegen-units` requires a number'
-	$(RUSTC) -C codegen-units= dummy.rs 2>&1 | \
-		$(CGREP) 'incorrect value `` for codegen option `codegen-units` - a number was expected'
-	$(RUSTC) -C codegen-units=foo dummy.rs 2>&1 | \
-		$(CGREP) 'incorrect value `foo` for codegen option `codegen-units` - a number was expected'
-	$(RUSTC) -C codegen-units=1 dummy.rs
-	#Option taking a string
-	$(RUSTC) -C extra-filename dummy.rs 2>&1 | \
-		$(CGREP) 'codegen option `extra-filename` requires a string'
-	$(RUSTC) -C extra-filename= dummy.rs 2>&1
-	$(RUSTC) -C extra-filename=foo dummy.rs 2>&1
-	#Option taking no argument
-	$(RUSTC) -C lto= dummy.rs 2>&1 | \
-		$(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted'
-	$(RUSTC) -C lto=1 dummy.rs 2>&1 | \
-		$(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted'
-	$(RUSTC) -C lto=foo dummy.rs 2>&1 | \
-		$(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted'
-	$(RUSTC) -C lto dummy.rs
-
-	# Should not link dead code...
-	$(RUSTC) --print link-args dummy.rs 2>&1 | \
-		$(CGREP) -e '--gc-sections|-z[^ ]* [^ ]*<ignore>|-dead_strip|/OPT:REF'
-	# ... unless you specifically ask to keep it
-	$(RUSTC) --print link-args -C link-dead-code dummy.rs 2>&1 | \
-		$(CGREP) -ve '--gc-sections|-z[^ ]* [^ ]*<ignore>|-dead_strip|/OPT:REF'
diff --git a/tests/run-make/codegen-options-parsing/rmake.rs b/tests/run-make/codegen-options-parsing/rmake.rs
new file mode 100644
index 00000000000..c78b41a88dc
--- /dev/null
+++ b/tests/run-make/codegen-options-parsing/rmake.rs
@@ -0,0 +1,56 @@
+// This test intentionally feeds invalid inputs to codegen and checks if the error message outputs
+// contain specific helpful indications.
+
+//@ ignore-cross-compile
+
+use run_make_support::regex::Regex;
+use run_make_support::rustc;
+
+fn main() {
+    // Option taking a number.
+    rustc()
+        .input("dummy.rs")
+        .arg("-Ccodegen-units")
+        .run_fail()
+        .assert_stderr_contains("codegen option `codegen-units` requires a number");
+    rustc().input("dummy.rs").arg("-Ccodegen-units=").run_fail().assert_stderr_contains(
+        "incorrect value `` for codegen option `codegen-units` - a number was expected",
+    );
+    rustc().input("dummy.rs").arg("-Ccodegen-units=foo").run_fail().assert_stderr_contains(
+        "incorrect value `foo` for codegen option `codegen-units` - a number was expected",
+    );
+    rustc().input("dummy.rs").arg("-Ccodegen-units=1").run();
+
+    // Option taking a string.
+    rustc()
+        .input("dummy.rs")
+        .arg("-Cextra-filename")
+        .run_fail()
+        .assert_stderr_contains("codegen option `extra-filename` requires a string");
+    rustc().input("dummy.rs").arg("-Cextra-filename=").run();
+    rustc().input("dummy.rs").arg("-Cextra-filename=foo").run();
+
+    // Option taking no argument.
+    rustc().input("dummy.rs").arg("-Clto=").run_fail().assert_stderr_contains(
+        "codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, \
+             `fat`, or omitted",
+    );
+    rustc().input("dummy.rs").arg("-Clto=1").run_fail().assert_stderr_contains(
+        "codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, \
+             `fat`, or omitted",
+    );
+    rustc().input("dummy.rs").arg("-Clto=foo").run_fail().assert_stderr_contains(
+        "codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, \
+             `fat`, or omitted",
+    );
+    rustc().input("dummy.rs").arg("-Clto").run();
+
+    let regex = Regex::new("--gc-sections|-z[^ ]* [^ ]*<ignore>|-dead_strip|/OPT:REF").unwrap();
+    // Should not link dead code...
+    let stdout = rustc().input("dummy.rs").print("link-args").run().stdout_utf8();
+    assert!(regex.is_match(&stdout));
+    // ... unless you specifically ask to keep it
+    let stdout =
+        rustc().input("dummy.rs").print("link-args").arg("-Clink-dead-code").run().stdout_utf8();
+    assert!(!regex.is_match(&stdout));
+}
diff --git a/tests/run-make/const_fn_mir/Makefile b/tests/run-make/const_fn_mir/Makefile
deleted file mode 100644
index 3399446130d..00000000000
--- a/tests/run-make/const_fn_mir/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# needs-unwind -Cpanic=abort gives different MIR output
-include ../tools.mk
-
-all:
-	$(RUSTC) main.rs --emit=mir -o "$(TMPDIR)"/dump.mir
-	$(RUSTC_TEST_OP) "$(TMPDIR)"/dump.mir dump.mir
diff --git a/tests/run-make/const_fn_mir/rmake.rs b/tests/run-make/const_fn_mir/rmake.rs
new file mode 100644
index 00000000000..a4cc4299b1b
--- /dev/null
+++ b/tests/run-make/const_fn_mir/rmake.rs
@@ -0,0 +1,8 @@
+// The `needs-unwind -Cpanic=abort` gives a different MIR output.
+
+use run_make_support::{cwd, diff, rustc};
+
+fn main() {
+    rustc().input("main.rs").emit("mir").output("dump-actual.mir").run();
+    diff().expected_file("dump.mir").actual_file("dump-actual.mir").run();
+}
diff --git a/tests/run-make/dep-graph/Makefile b/tests/run-make/dep-graph/Makefile
deleted file mode 100644
index d06333f4454..00000000000
--- a/tests/run-make/dep-graph/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-include ../tools.mk
-
-# ignore-cross-compile
-
-# Just verify that we successfully run and produce dep graphs when requested.
-
-all:
-	RUST_DEP_GRAPH=$(TMPDIR)/dep-graph $(RUSTC) \
-        -Cincremental=$(TMPDIR)/incr \
-        -Zquery-dep-graph -Zdump-dep-graph foo.rs
-	test -f $(TMPDIR)/dep-graph.txt
-	test -f $(TMPDIR)/dep-graph.dot
diff --git a/tests/run-make/dep-graph/rmake.rs b/tests/run-make/dep-graph/rmake.rs
new file mode 100644
index 00000000000..351418997f1
--- /dev/null
+++ b/tests/run-make/dep-graph/rmake.rs
@@ -0,0 +1,18 @@
+// Just verify that we successfully run and produce dep graphs when requested.
+
+//@ ignore-cross-compile
+
+use run_make_support::{path, rustc};
+
+fn main() {
+    rustc()
+        .input("foo.rs")
+        .incremental(path("incr"))
+        .arg("-Zquery-dep-graph")
+        .arg("-Zdump-dep-graph")
+        .env("RUST_DEP_GRAPH", path("dep-graph"))
+        .run();
+
+    assert!(path("dep-graph.txt").is_file());
+    assert!(path("dep-graph.dot").is_file());
+}
diff --git a/tests/run-make/optimization-remarks-dir-pgo/Makefile b/tests/run-make/optimization-remarks-dir-pgo/Makefile
index 3bc3d7d1428..57ffd6e70f0 100644
--- a/tests/run-make/optimization-remarks-dir-pgo/Makefile
+++ b/tests/run-make/optimization-remarks-dir-pgo/Makefile
@@ -1,10 +1,6 @@
 # needs-profiler-support
-# ignore-windows-gnu
 # ignore-cross-compile
 
-# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
-# properly. Since we only have GCC on the CI ignore the test for now.
-
 include ../tools.mk
 
 PROFILE_DIR=$(TMPDIR)/profiles
diff --git a/tests/run-make/pgo-branch-weights/Makefile b/tests/run-make/pgo-branch-weights/Makefile
deleted file mode 100644
index 4c9f8b2493a..00000000000
--- a/tests/run-make/pgo-branch-weights/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-# needs-profiler-support
-# ignore-windows-gnu
-# ignore-cross-compile
-
-# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
-# properly. Since we only have GCC on the CI ignore the test for now.
-
-include ../tools.mk
-
-# For some very small programs GNU ld seems to not properly handle
-# instrumentation sections correctly. Neither Gold nor LLD have that problem.
-ifeq ($(UNAME),Linux)
-ifneq (,$(findstring x86,$(TARGET)))
-COMMON_FLAGS=-Clink-args=-fuse-ld=gold
-endif
-endif
-
-
-all:
-	# We don't compile `opaque` with either optimizations or instrumentation.
-	$(RUSTC) $(COMMON_FLAGS) opaque.rs || exit 1
-	# Compile the test program with instrumentation
-	mkdir -p "$(TMPDIR)/prof_data_dir" || exit 1
-	$(RUSTC) $(COMMON_FLAGS) interesting.rs \
-		-Cprofile-generate="$(TMPDIR)/prof_data_dir" -O -Ccodegen-units=1 || exit 1
-	$(RUSTC) $(COMMON_FLAGS) main.rs -Cprofile-generate="$(TMPDIR)/prof_data_dir" -O || exit 1
-	# The argument below generates to the expected branch weights
-	$(call RUN,main aaaaaaaaaaaa2bbbbbbbbbbbb2bbbbbbbbbbbbbbbbcc) || exit 1
-	"$(LLVM_BIN_DIR)/llvm-profdata" merge \
-		-o "$(TMPDIR)/prof_data_dir/merged.profdata" \
-		"$(TMPDIR)/prof_data_dir" || exit 1
-	$(RUSTC) $(COMMON_FLAGS) interesting.rs \
-		-Cprofile-use="$(TMPDIR)/prof_data_dir/merged.profdata" -O \
-		-Ccodegen-units=1 --emit=llvm-ir || exit 1
-	cat "$(TMPDIR)/interesting.ll" | "$(LLVM_FILECHECK)" filecheck-patterns.txt
diff --git a/tests/run-make/pgo-branch-weights/rmake.rs b/tests/run-make/pgo-branch-weights/rmake.rs
new file mode 100644
index 00000000000..d3cb79c39af
--- /dev/null
+++ b/tests/run-make/pgo-branch-weights/rmake.rs
@@ -0,0 +1,41 @@
+// This test generates an instrumented binary - a program which
+// will keep track of how many times it calls each function, a useful
+// feature for optimization. Then, an argument (aaaaaaaaaaaa2bbbbbbbbbbbb2bbbbbbbbbbbbbbbbcc)
+// is passed into the instrumented binary, which should react with a number of function calls
+// fully known in advance. (For example, the letter 'a' results in calling f1())
+
+// If the test passes, the expected function call count was added to the use-phase LLVM-IR.
+// See https://github.com/rust-lang/rust/pull/66631
+
+//@ needs-profiler-support
+//@ ignore-cross-compile
+
+use run_make_support::{fs_wrapper, llvm_filecheck, llvm_profdata, run_with_args, rustc};
+use std::path::Path;
+
+fn main() {
+    let path_prof_data_dir = Path::new("prof_data_dir");
+    let path_merged_profdata = path_prof_data_dir.join("merged.profdata");
+    rustc().input("opaque.rs").run();
+    fs_wrapper::create_dir_all(&path_prof_data_dir);
+    rustc()
+        .input("interesting.rs")
+        .profile_generate(&path_prof_data_dir)
+        .opt()
+        .codegen_units(1)
+        .run();
+    rustc().input("main.rs").profile_generate(&path_prof_data_dir).opt().run();
+    run_with_args("main", &["aaaaaaaaaaaa2bbbbbbbbbbbb2bbbbbbbbbbbbbbbbcc"]);
+    llvm_profdata().merge().output(&path_merged_profdata).input(path_prof_data_dir).run();
+    rustc()
+        .input("interesting.rs")
+        .profile_use(path_merged_profdata)
+        .opt()
+        .codegen_units(1)
+        .emit("llvm-ir")
+        .run();
+    llvm_filecheck()
+        .patterns("filecheck-patterns.txt")
+        .stdin(fs_wrapper::read("interesting.ll"))
+        .run();
+}
diff --git a/tests/run-make/pgo-gen-lto/Makefile b/tests/run-make/pgo-gen-lto/Makefile
index 8b647846af3..54164c99522 100644
--- a/tests/run-make/pgo-gen-lto/Makefile
+++ b/tests/run-make/pgo-gen-lto/Makefile
@@ -1,10 +1,6 @@
 # needs-profiler-support
-# ignore-windows-gnu
 # ignore-cross-compile
 
-# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
-# properly. Since we only have GCC on the CI ignore the test for now.
-
 include ../tools.mk
 
 COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Cprofile-generate="$(TMPDIR)"
diff --git a/tests/run-make/pgo-gen-no-imp-symbols/Makefile b/tests/run-make/pgo-gen-no-imp-symbols/Makefile
index 7f72b11b611..d2baa145ba5 100644
--- a/tests/run-make/pgo-gen-no-imp-symbols/Makefile
+++ b/tests/run-make/pgo-gen-no-imp-symbols/Makefile
@@ -1,8 +1,6 @@
-# needs-profiler-support
-
 include ../tools.mk
 
-COMPILE_FLAGS=-O -Ccodegen-units=1 -Cprofile-generate="$(TMPDIR)"
+COMPILE_FLAGS=-O -Ccodegen-units=1 -Cprofile-generate="$(TMPDIR)" -Zno-profiler-runtime
 
 all:
 	$(RUSTC) $(COMPILE_FLAGS) --emit=llvm-ir test.rs
diff --git a/tests/run-make/pgo-gen/Makefile b/tests/run-make/pgo-gen/Makefile
index bf32cfdb802..c1d456986fb 100644
--- a/tests/run-make/pgo-gen/Makefile
+++ b/tests/run-make/pgo-gen/Makefile
@@ -1,10 +1,6 @@
 # needs-profiler-support
-# ignore-windows-gnu
 # ignore-cross-compile
 
-# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
-# properly. Since we only have GCC on the CI ignore the test for now.
-
 include ../tools.mk
 
 COMPILE_FLAGS=-g -Cprofile-generate="$(TMPDIR)"
diff --git a/tests/run-make/pgo-indirect-call-promotion/Makefile b/tests/run-make/pgo-indirect-call-promotion/Makefile
index 542eb244d39..8d1e69c4aba 100644
--- a/tests/run-make/pgo-indirect-call-promotion/Makefile
+++ b/tests/run-make/pgo-indirect-call-promotion/Makefile
@@ -1,10 +1,6 @@
 # needs-profiler-support
-# ignore-windows-gnu
 # ignore-cross-compile
 
-# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
-# properly. Since we only have GCC on the CI ignore the test for now.
-
 include ../tools.mk
 
 all:
diff --git a/tests/run-make/pgo-use/Makefile b/tests/run-make/pgo-use/Makefile
index 9f440118dae..92098a4019c 100644
--- a/tests/run-make/pgo-use/Makefile
+++ b/tests/run-make/pgo-use/Makefile
@@ -1,10 +1,6 @@
 # needs-profiler-support
-# ignore-windows-gnu
 # ignore-cross-compile
 
-# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
-# properly. Since we only have GCC on the CI ignore the test for now.
-
 include ../tools.mk
 
 # This test makes sure that PGO profiling data leads to cold functions being
diff --git a/tests/run-make/short-ice/Makefile b/tests/run-make/short-ice/Makefile
deleted file mode 100644
index 23006fc09e2..00000000000
--- a/tests/run-make/short-ice/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-include ../tools.mk
-
-# ignore-windows
-
-export RUSTC := $(RUSTC_ORIGINAL)
-export LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
-export TMPDIR := $(TMPDIR)
-
-all:
-	bash check.sh
diff --git a/tests/run-make/short-ice/check.sh b/tests/run-make/short-ice/check.sh
deleted file mode 100644
index 56babd2142f..00000000000
--- a/tests/run-make/short-ice/check.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh
-export RUSTC_ICE=0
-RUST_BACKTRACE=1 $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-1.log 2>&1
-RUST_BACKTRACE=full $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-2.log 2>&1
-
-short=$(cat $TMPDIR/rust-test-1.log | wc -l)
-full=$(cat $TMPDIR/rust-test-2.log | wc -l)
-rustc_query_count=$(cat $TMPDIR/rust-test-1.log | grep rustc_query_ | wc -l)
-rustc_query_count_full=$(cat $TMPDIR/rust-test-2.log | grep rustc_query_ | wc -l)
-
-begin_count=$(cat $TMPDIR/rust-test-2.log | grep __rust_begin_short_backtrace | wc -l)
-end_count=$(cat $TMPDIR/rust-test-2.log | grep __rust_end_short_backtrace | wc -l)
-
-cat $TMPDIR/rust-test-1.log
-echo "====================="
-cat $TMPDIR/rust-test-2.log
-echo "====================="
-
-echo "short backtrace: $short"
-echo "full  backtrace: $full"
-echo "begin_count: $begin_count"
-echo "end_count  : $end_count"
-echo "rustc_query_count: $rustc_query_count"
-echo "rustc_query_count_full: $rustc_query_count_full"
-
-## backtraces to vary a bit depending on platform and configuration options,
-## here we make sure that the short backtrace of rustc_query is shorter than the full,
-## and marks are in pairs.
-if [ $short -lt $full ] &&
-    [ $begin_count -eq $end_count ] &&
-    [ $(($rustc_query_count + 5)) -lt $rustc_query_count_full ] &&
-    [ $rustc_query_count_full -gt 5 ]; then
-    exit 0
-else
-    exit 1
-fi
diff --git a/tests/run-make/short-ice/rmake.rs b/tests/run-make/short-ice/rmake.rs
new file mode 100644
index 00000000000..81403931c78
--- /dev/null
+++ b/tests/run-make/short-ice/rmake.rs
@@ -0,0 +1,42 @@
+// Backtraces in internal compiler errors used to be unbearably long, spanning
+// multiple hundreds of lines. A fix was pushed in #108938, and this test gathers
+// varied metrics on level 1 and full-level backtraces to check that the output
+// was shortened down to an appropriate length.
+// See https://github.com/rust-lang/rust/issues/107910
+
+//@ ignore-windows
+// Reason: the assert_eq! on line 32 fails, as error output on Windows is different.
+
+use run_make_support::rustc;
+
+fn main() {
+    let rust_test_1 =
+        rustc().set_backtrace_level("1").input("src/lib.rs").arg("-Ztreat-err-as-bug=1").run_fail();
+    let rust_test_2 = rustc()
+        .set_backtrace_level("full")
+        .input("src/lib.rs")
+        .arg("-Ztreat-err-as-bug=1")
+        .run_fail();
+
+    let mut rust_test_log_1 = rust_test_1.stderr_utf8();
+    rust_test_log_1.push_str(&rust_test_1.stdout_utf8());
+    let rust_test_log_1 = rust_test_log_1.as_str();
+
+    let mut rust_test_log_2 = rust_test_2.stderr_utf8();
+    rust_test_log_2.push_str(&rust_test_2.stdout_utf8());
+    let rust_test_log_2 = rust_test_log_2.as_str();
+
+    let rustc_query_count_full = count_lines_with(rust_test_log_2, "rustc_query_");
+
+    assert!(rust_test_log_1.lines().count() < rust_test_log_2.lines().count());
+    assert_eq!(
+        count_lines_with(rust_test_log_2, "__rust_begin_short_backtrace"),
+        count_lines_with(rust_test_log_2, "__rust_end_short_backtrace")
+    );
+    assert!(count_lines_with(rust_test_log_1, "rustc_query_") + 5 < rustc_query_count_full);
+    assert!(rustc_query_count_full > 5);
+}
+
+fn count_lines_with(s: &str, search: &str) -> usize {
+    s.lines().filter(|l| l.contains(search)).count()
+}
diff --git a/tests/run-make/symlinked-extern/Makefile b/tests/run-make/symlinked-extern/Makefile
deleted file mode 100644
index 28c764b84e8..00000000000
--- a/tests/run-make/symlinked-extern/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# ignore-windows
-# `ln` is actually `cp` on msys.
-
-all:
-	$(RUSTC) foo.rs
-	mkdir -p $(TMPDIR)/other
-	ln -nsf $(TMPDIR)/libfoo.rlib $(TMPDIR)/other
-	$(RUSTC) bar.rs -L $(TMPDIR)
-	$(RUSTC) baz.rs --extern foo=$(TMPDIR)/other/libfoo.rlib  -L $(TMPDIR)
diff --git a/tests/run-make/symlinked-extern/rmake.rs b/tests/run-make/symlinked-extern/rmake.rs
new file mode 100644
index 00000000000..98f69aefbe6
--- /dev/null
+++ b/tests/run-make/symlinked-extern/rmake.rs
@@ -0,0 +1,21 @@
+// Crates that are resolved normally have their path canonicalized and all
+// symlinks resolved. This did not happen for paths specified
+// using the --extern option to rustc, which could lead to rustc thinking
+// that it encountered two different versions of a crate, when it's
+// actually the same version found through different paths.
+// See https://github.com/rust-lang/rust/pull/16505
+
+// This test checks that --extern and symlinks together
+// can result in successful compilation.
+
+//@ ignore-cross-compile
+
+use run_make_support::{create_symlink, cwd, fs_wrapper, rustc};
+
+fn main() {
+    rustc().input("foo.rs").run();
+    fs_wrapper::create_dir_all("other");
+    create_symlink("libfoo.rlib", "other");
+    rustc().input("bar.rs").library_search_path(cwd()).run();
+    rustc().input("baz.rs").extern_("foo", "other").library_search_path(cwd()).run();
+}
diff --git a/tests/run-make/symlinked-libraries/Makefile b/tests/run-make/symlinked-libraries/Makefile
deleted file mode 100644
index fb0b6127e6f..00000000000
--- a/tests/run-make/symlinked-libraries/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# ignore-windows
-# `ln` is actually `cp` on msys.
-
-all:
-	$(RUSTC) foo.rs -C prefer-dynamic
-	mkdir -p $(TMPDIR)/other
-	ln -nsf $(TMPDIR)/$(call DYLIB_GLOB,foo) $(TMPDIR)/other
-	$(RUSTC) bar.rs -L $(TMPDIR)/other
diff --git a/tests/run-make/symlinked-libraries/rmake.rs b/tests/run-make/symlinked-libraries/rmake.rs
new file mode 100644
index 00000000000..eaf0c44206a
--- /dev/null
+++ b/tests/run-make/symlinked-libraries/rmake.rs
@@ -0,0 +1,16 @@
+// When a directory and a symlink simultaneously exist with the same name,
+// setting that name as the library search path should not cause rustc
+// to avoid looking in the symlink and cause an error. This test creates
+// a directory and a symlink named "other", and places the library in the symlink.
+// If it succeeds, the library was successfully found.
+// See https://github.com/rust-lang/rust/issues/12459
+
+//@ ignore-cross-compile
+use run_make_support::{create_symlink, dynamic_lib_name, fs_wrapper, rustc};
+
+fn main() {
+    rustc().input("foo.rs").arg("-Cprefer-dynamic").run();
+    fs_wrapper::create_dir_all("other");
+    create_symlink(dynamic_lib_name("foo"), "other");
+    rustc().input("bar.rs").library_search_path("other").run();
+}
diff --git a/tests/run-make/symlinked-rlib/Makefile b/tests/run-make/symlinked-rlib/Makefile
deleted file mode 100644
index a8565f683c3..00000000000
--- a/tests/run-make/symlinked-rlib/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# ignore-windows
-# `ln` is actually `cp` on msys.
-
-all:
-	$(RUSTC) foo.rs --crate-type=rlib -o $(TMPDIR)/foo.xxx
-	ln -nsf $(TMPDIR)/foo.xxx $(TMPDIR)/libfoo.rlib
-	$(RUSTC) bar.rs -L $(TMPDIR)
diff --git a/tests/run-make/symlinked-rlib/rmake.rs b/tests/run-make/symlinked-rlib/rmake.rs
new file mode 100644
index 00000000000..3759ca25928
--- /dev/null
+++ b/tests/run-make/symlinked-rlib/rmake.rs
@@ -0,0 +1,16 @@
+// Rustc did not recognize libraries which were symlinked
+// to files having extension other than .rlib. This was fixed
+// in #32828. This test creates a symlink to "foo.xxx", which has
+// an unusual file extension, and checks that rustc can successfully
+// use it as an rlib library.
+// See https://github.com/rust-lang/rust/pull/32828
+
+//@ ignore-cross-compile
+
+use run_make_support::{create_symlink, cwd, rustc};
+
+fn main() {
+    rustc().input("foo.rs").crate_type("rlib").output("foo.xxx").run();
+    create_symlink("foo.xxx", "libfoo.rlib");
+    rustc().input("bar.rs").library_search_path(cwd()).run();
+}
diff --git a/tests/run-make/track-pgo-dep-info/Makefile b/tests/run-make/track-pgo-dep-info/Makefile
index 6c7f67d0f0a..3afe3662fa7 100644
--- a/tests/run-make/track-pgo-dep-info/Makefile
+++ b/tests/run-make/track-pgo-dep-info/Makefile
@@ -1,5 +1,4 @@
 # needs-profiler-support
-# ignore-windows-gnu
 
 include ../tools.mk
 
diff --git a/tests/rustdoc-gui/help-page.goml b/tests/rustdoc-gui/help-page.goml
deleted file mode 100644
index 09d33af139c..00000000000
--- a/tests/rustdoc-gui/help-page.goml
+++ /dev/null
@@ -1,69 +0,0 @@
-// This test ensures that opening the help page in its own tab works.
-include: "utils.goml"
-go-to: "file://" + |DOC_PATH| + "/help.html"
-set-window-size: (1000, 1000) // Try desktop size first.
-wait-for: "#help"
-assert-css: ("#help", {"display": "block"})
-assert-css: ("#help dd", {"font-size": "16px"})
-click: "#help-button > a"
-assert-css: ("#help", {"display": "block"})
-compare-elements-property: (".sub", "#help", ["offsetWidth"])
-compare-elements-position: (".sub", "#help", ["x"])
-set-window-size: (500, 1000) // Try mobile next.
-assert-css: ("#help", {"display": "block"})
-compare-elements-property: (".sub", "#help", ["offsetWidth"])
-compare-elements-position: (".sub", "#help", ["x"])
-
-// Checking the color of the elements of the help menu.
-show-text: true
-define-function: (
-    "check-colors",
-    [theme, color, background, box_shadow],
-    block {
-        call-function: ("switch-theme", {"theme": |theme|})
-        assert-css: ("#help kbd", {
-            "color": |color|,
-            "background-color": |background|,
-            "box-shadow": |box_shadow| + " 0px -1px 0px 0px inset",
-        }, ALL)
-    },
-)
-
-call-function: ("check-colors", {
-    "theme": "ayu",
-    "color": "#c5c5c5",
-    "background": "#314559",
-    "box_shadow": "#5c6773",
-})
-call-function: ("check-colors", {
-    "theme": "dark",
-    "color": "#000",
-    "background": "#fafbfc",
-    "box_shadow": "#c6cbd1",
-})
-call-function: ("check-colors", {
-    "theme": "light",
-    "color": "#000",
-    "background": "#fafbfc",
-    "box_shadow": "#c6cbd1",
-})
-
-// This test ensures that opening the help popover without switching pages works.
-go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
-set-window-size: (1000, 1000) // Only supported on desktop.
-assert-false: "#help"
-click: "#help-button > a"
-assert-css: ("#help", {"display": "block"})
-assert-css: ("#help dd", {"font-size": "16px"})
-click: "#help-button > a"
-assert-css: ("#help", {"display": "none"})
-compare-elements-property-false: (".sub", "#help", ["offsetWidth"])
-compare-elements-position-false: (".sub", "#help", ["x"])
-
-// This test ensures that the "the rustdoc book" anchor link within the help popover works.
-go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
-set-window-size: (1000, 1000) // Popover only appears when the screen width is >700px.
-assert-false: "#help"
-click: "#help-button > a"
-click: "//*[@id='help']//a[text()='the rustdoc book']"
-wait-for-document-property: ({"URL": "https://doc.rust-lang.org/"}, STARTS_WITH)
diff --git a/tests/ui-fulldeps/stable-mir/check_def_ty.rs b/tests/ui-fulldeps/stable-mir/check_def_ty.rs
new file mode 100644
index 00000000000..9f45b62d343
--- /dev/null
+++ b/tests/ui-fulldeps/stable-mir/check_def_ty.rs
@@ -0,0 +1,114 @@
+//@ run-pass
+//! Test that users are able to use stable mir APIs to retrieve type information from a crate item
+//! definition.
+
+//@ ignore-stage1
+//@ ignore-cross-compile
+//@ ignore-remote
+//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
+//@ edition: 2021
+
+#![feature(rustc_private)]
+#![feature(assert_matches)]
+#![feature(control_flow_enum)]
+
+#[macro_use]
+extern crate rustc_smir;
+extern crate rustc_driver;
+extern crate rustc_interface;
+extern crate stable_mir;
+
+use rustc_smir::rustc_internal;
+use stable_mir::ty::{Ty, ForeignItemKind};
+use stable_mir::*;
+use std::io::Write;
+use std::ops::ControlFlow;
+
+const CRATE_NAME: &str = "crate_def_ty";
+
+/// Test if we can retrieve type information from different definitions.
+fn test_def_tys() -> ControlFlow<()> {
+    let items = stable_mir::all_local_items();
+    for item in &items {
+        // Type from crate items.
+        let ty = item.ty();
+        match item.name().as_str() {
+            "STATIC_STR" => assert!(ty.kind().is_ref()),
+            "CONST_U32" => assert!(ty.kind().is_integral()),
+            "main" => { check_fn_def(ty) }
+            _ => unreachable!("Unexpected item: `{item:?}`")
+        }
+    }
+
+    let foreign_items = stable_mir::local_crate().foreign_modules();
+    for item in foreign_items[0].module().items() {
+        // Type from foreign items.
+        let ty = item.ty();
+        let item_kind = item.kind();
+        let name = item.name();
+        match item_kind {
+            ForeignItemKind::Fn(fn_def) => {
+                assert_eq!(&name, "extern_fn");
+                assert_eq!(ty, fn_def.ty());
+                check_fn_def(ty)
+            }
+            ForeignItemKind::Static(def) => {
+                assert_eq!(&name, "EXT_STATIC");
+                assert_eq!(ty, def.ty());
+                assert!(ty.kind().is_integral())
+            }
+            _ => unreachable!("Unexpected kind: {item_kind:?}")
+        };
+    }
+
+    ControlFlow::Continue(())
+}
+
+fn check_fn_def(ty: Ty) {
+    let kind = ty.kind();
+    let (def, args) = kind.fn_def().expect(&format!("Expected function type, but found: {ty}"));
+    assert!(def.ty().kind().is_fn());
+    assert_eq!(def.ty_with_args(args), ty);
+}
+
+/// This test will generate and analyze a dummy crate using the stable mir.
+/// For that, it will first write the dummy crate into a file.
+/// Then it will create a `StableMir` using custom arguments and then
+/// it will run the compiler.
+fn main() {
+    let path = "defs_ty_input.rs";
+    generate_input(&path).unwrap();
+    let args = vec![
+        "rustc".to_string(),
+        "-Cpanic=abort".to_string(),
+        "--crate-name".to_string(),
+        CRATE_NAME.to_string(),
+        path.to_string(),
+    ];
+    run!(args, test_def_tys).unwrap();
+}
+
+fn generate_input(path: &str) -> std::io::Result<()> {
+    let mut file = std::fs::File::create(path)?;
+    write!(
+        file,
+        r#"
+        // We would like to check intrinsic definition.
+        #![feature(core_intrinsics)]
+        static STATIC_STR: &str = "foo";
+        const CONST_U32: u32 = 0u32;
+
+        fn main() {{
+            let _c = core::char::from_u32(99);
+            let _v = Vec::<u8>::new();
+            let _i = std::intrinsics::size_of::<u8>();
+        }}
+
+        extern "C" {{
+            fn extern_fn(x: i32) -> i32;
+            static EXT_STATIC: i32;
+        }}
+    "#
+    )?;
+    Ok(())
+}
diff --git a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs
index 7e247ce0c75..d7f37f36681 100644
--- a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs
+++ b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs
@@ -55,16 +55,19 @@ fn test_intrinsics() -> ControlFlow<()> {
 ///
 /// If by any chance this test breaks because you changed how an intrinsic is implemented, please
 /// update the test to invoke a different intrinsic.
+///
+/// In StableMIR, we only expose intrinsic body if they are not marked with
+/// `rustc_intrinsic_must_be_overridden`.
 fn check_instance(instance: &Instance) {
     assert_eq!(instance.kind, InstanceKind::Intrinsic);
     let name = instance.intrinsic_name().unwrap();
     if instance.has_body() {
         let Some(body) = instance.body() else { unreachable!("Expected a body") };
         assert!(!body.blocks.is_empty());
-        assert_matches!(name.as_str(), "likely" | "vtable_size");
+        assert_eq!(&name, "likely");
     } else {
         assert!(instance.body().is_none());
-        assert_eq!(&name, "size_of_val");
+        assert_matches!(name.as_str(), "size_of_val" | "vtable_size");
     }
 }
 
@@ -75,11 +78,13 @@ fn check_def(fn_def: FnDef) {
 
     let name = intrinsic.fn_name();
     match name.as_str() {
-        "likely" | "size_of_val" => {
+        "likely" => {
             assert!(!intrinsic.must_be_overridden());
+            assert!(fn_def.has_body());
         }
-        "vtable_size" => {
+        "vtable_size" | "size_of_val" => {
             assert!(intrinsic.must_be_overridden());
+            assert!(!fn_def.has_body());
         }
         _ => unreachable!("Unexpected intrinsic: {}", name),
     }
@@ -96,9 +101,9 @@ impl<'a> MirVisitor for CallsVisitor<'a> {
             TerminatorKind::Call { func, .. } => {
                 let TyKind::RigidTy(RigidTy::FnDef(def, args)) =
                     func.ty(self.locals).unwrap().kind()
-                else {
-                    return;
-                };
+                    else {
+                        return;
+                    };
                 self.calls.push((def, args.clone()));
             }
             _ => {}
diff --git a/tests/ui-fulldeps/stable-mir/check_transform.rs b/tests/ui-fulldeps/stable-mir/check_transform.rs
index b203e76e54f..1d3e4c6845b 100644
--- a/tests/ui-fulldeps/stable-mir/check_transform.rs
+++ b/tests/ui-fulldeps/stable-mir/check_transform.rs
@@ -21,7 +21,7 @@ extern crate stable_mir;
 use rustc_smir::rustc_internal;
 use stable_mir::mir::alloc::GlobalAlloc;
 use stable_mir::mir::mono::Instance;
-use stable_mir::mir::{Body, Constant, Operand, Rvalue, StatementKind, TerminatorKind};
+use stable_mir::mir::{Body, ConstOperand, Operand, Rvalue, StatementKind, TerminatorKind};
 use stable_mir::ty::{ConstantKind, MirConst};
 use stable_mir::{CrateDef, CrateItems, ItemKind};
 use std::convert::TryFrom;
@@ -72,7 +72,7 @@ fn check_msg(body: &Body, expected: &str) {
                             .unwrap()
                     }
                 };
-                let ConstantKind::Allocated(alloc) = msg_const.literal.kind() else {
+                let ConstantKind::Allocated(alloc) = msg_const.const_.kind() else {
                     unreachable!()
                 };
                 assert_eq!(alloc.provenance.ptrs.len(), 1);
@@ -96,8 +96,8 @@ fn change_panic_msg(mut body: Body, new_msg: &str) -> Body {
         match &mut bb.terminator.kind {
             TerminatorKind::Call { args, .. } => {
                 let new_const = MirConst::from_str(new_msg);
-                args[0] = Operand::Constant(Constant {
-                    literal: new_const,
+                args[0] = Operand::Constant(ConstOperand {
+                    const_: new_const,
                     span: bb.terminator.span,
                     user_ty: None,
                 });
diff --git a/tests/run-make/allow-non-lint-warnings-cmdline/foo.rs b/tests/ui/allow-non-lint-warnings.rs
index 02e8ccabf79..f8f5a78ebff 100644
--- a/tests/run-make/allow-non-lint-warnings-cmdline/foo.rs
+++ b/tests/ui/allow-non-lint-warnings.rs
@@ -1,3 +1,6 @@
+//@ compile-flags: -Awarnings
+//@ check-pass
+
 #[derive()]
 #[derive(Copy, Clone)]
 pub struct Foo;
diff --git a/tests/ui/asm/x86_64/type-check-3.stderr b/tests/ui/asm/x86_64/type-check-3.stderr
index 34bfcd71cac..202b97ca5c0 100644
--- a/tests/ui/asm/x86_64/type-check-3.stderr
+++ b/tests/ui/asm/x86_64/type-check-3.stderr
@@ -4,7 +4,7 @@ error: type `i128` cannot be used with this register class
 LL |         asm!("{}", in(reg) 0i128);
    |                            ^^^^^
    |
-   = note: register class `reg` supports these types: i16, i32, i64, f32, f64
+   = note: register class `reg` supports these types: i16, i32, i64, f16, f32, f64
 
 error: type `__m128` cannot be used with this register class
   --> $DIR/type-check-3.rs:16:28
@@ -12,7 +12,7 @@ error: type `__m128` cannot be used with this register class
 LL |         asm!("{}", in(reg) _mm_setzero_ps());
    |                            ^^^^^^^^^^^^^^^^
    |
-   = note: register class `reg` supports these types: i16, i32, i64, f32, f64
+   = note: register class `reg` supports these types: i16, i32, i64, f16, f32, f64
 
 error: type `__m256` cannot be used with this register class
   --> $DIR/type-check-3.rs:18:28
@@ -20,7 +20,7 @@ error: type `__m256` cannot be used with this register class
 LL |         asm!("{}", in(reg) _mm256_setzero_ps());
    |                            ^^^^^^^^^^^^^^^^^^^
    |
-   = note: register class `reg` supports these types: i16, i32, i64, f32, f64
+   = note: register class `reg` supports these types: i16, i32, i64, f16, f32, f64
 
 error: type `u8` cannot be used with this register class
   --> $DIR/type-check-3.rs:20:32
@@ -28,7 +28,7 @@ error: type `u8` cannot be used with this register class
 LL |         asm!("{}", in(xmm_reg) 0u8);
    |                                ^^^
    |
-   = note: register class `xmm_reg` supports these types: i32, i64, f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
+   = note: register class `xmm_reg` supports these types: i32, i64, f16, f32, f64, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2
 
 error: `avx512bw` target feature is not enabled
   --> $DIR/type-check-3.rs:29:29
@@ -81,7 +81,7 @@ error: type `i8` cannot be used with this register class
 LL |         asm!("{}", in(reg) 0i8);
    |                            ^^^
    |
-   = note: register class `reg` supports these types: i16, i32, i64, f32, f64
+   = note: register class `reg` supports these types: i16, i32, i64, f16, f32, f64
    = help: consider using the `reg_byte` register class instead
 
 error: incompatible types for asm inout argument
diff --git a/tests/ui/associated-type-bounds/no-gat-position.rs b/tests/ui/associated-type-bounds/no-gat-position.rs
index cb62c882468..ec9214897fa 100644
--- a/tests/ui/associated-type-bounds/no-gat-position.rs
+++ b/tests/ui/associated-type-bounds/no-gat-position.rs
@@ -5,6 +5,7 @@ pub trait Iter {
 
     fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>;
     //~^ ERROR associated item constraints are not allowed here
+    //~| HELP consider removing this associated item constraint
 }
 
 impl Iter for () {
diff --git a/tests/ui/associated-type-bounds/no-gat-position.stderr b/tests/ui/associated-type-bounds/no-gat-position.stderr
index e167ac1fda4..39a2f89f9ac 100644
--- a/tests/ui/associated-type-bounds/no-gat-position.stderr
+++ b/tests/ui/associated-type-bounds/no-gat-position.stderr
@@ -3,6 +3,11 @@ error[E0229]: associated item constraints are not allowed here
    |
 LL |     fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>;
    |                                                        ^^^^^^^^^ associated item constraint not allowed here
+   |
+help: consider removing this associated item constraint
+   |
+LL |     fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>;
+   |                                                      ~~~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/associated-types/associated-types-eq-2.rs b/tests/ui/associated-types/associated-types-eq-2.rs
index f0a7d1e46b1..88eb2981061 100644
--- a/tests/ui/associated-types/associated-types-eq-2.rs
+++ b/tests/ui/associated-types/associated-types-eq-2.rs
@@ -76,7 +76,6 @@ trait Tr3<const N: i32, T2, T3> {
 impl Tr3<N
 //~^ ERROR associated item constraints are not allowed here
 //~| ERROR associated const equality is incomplete
-//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
 = 42, T2 = Qux, T3 = usize> for Bar {
 }
 
@@ -92,7 +91,6 @@ impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
 // matches the const param ident but the constraint is a type arg
 impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
 //~^ ERROR associated item constraints are not allowed here
-//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
 }
 
 // Test for when equality constraint's ident
diff --git a/tests/ui/associated-types/associated-types-eq-2.stderr b/tests/ui/associated-types/associated-types-eq-2.stderr
index 53e4e59128e..69b1b533450 100644
--- a/tests/ui/associated-types/associated-types-eq-2.stderr
+++ b/tests/ui/associated-types/associated-types-eq-2.stderr
@@ -5,7 +5,6 @@ LL |   impl Tr3<N
    |  __________^
 LL | |
 LL | |
-LL | |
 LL | | = 42, T2 = Qux, T3 = usize> for Bar {
    | |____^
    |
@@ -14,7 +13,7 @@ LL | | = 42, T2 = Qux, T3 = usize> for Bar {
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: associated const equality is incomplete
-  --> $DIR/associated-types-eq-2.rs:85:10
+  --> $DIR/associated-types-eq-2.rs:84:10
    |
 LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
    |          ^^^^^^
@@ -24,7 +23,7 @@ LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: associated const equality is incomplete
-  --> $DIR/associated-types-eq-2.rs:100:14
+  --> $DIR/associated-types-eq-2.rs:98:14
    |
 LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
    |              ^^^^^^^
@@ -34,7 +33,7 @@ LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: associated const equality is incomplete
-  --> $DIR/associated-types-eq-2.rs:108:10
+  --> $DIR/associated-types-eq-2.rs:106:10
    |
 LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
    |          ^^^^^^
@@ -190,22 +189,6 @@ help: to use `GenericTerm<i32>` as a generic argument specify it directly
 LL | impl Tr2<i32, Qux, GenericTerm<i32>> for Bar {
    |                    ~~~~~~~~~~~~~~~~
 
-error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
-  --> $DIR/associated-types-eq-2.rs:76:6
-   |
-LL | impl Tr3<N
-   |      ^^^ expected 3 generic arguments
-   |
-note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
-  --> $DIR/associated-types-eq-2.rs:69:7
-   |
-LL | trait Tr3<const N: i32, T2, T3> {
-   |       ^^^ ------------  --  --
-help: add missing generic arguments
-   |
-LL | impl Tr3<N, T2, T3, N
-   |          ++++++++++
-
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/associated-types-eq-2.rs:76:10
    |
@@ -213,7 +196,6 @@ LL |   impl Tr3<N
    |  __________^
 LL | |
 LL | |
-LL | |
 LL | | = 42, T2 = Qux, T3 = usize> for Bar {
    | |____^ associated item constraint not allowed here
    |
@@ -223,7 +205,7 @@ LL | impl Tr3<42, T2 = Qux, T3 = usize> for Bar {
    |          ~~
 
 error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
-  --> $DIR/associated-types-eq-2.rs:85:6
+  --> $DIR/associated-types-eq-2.rs:84:6
    |
 LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
    |      ^^^ expected 3 generic arguments
@@ -239,7 +221,7 @@ LL | impl Tr3<N, T2, T3, n = 42, T2 = Qux, T3 = usize> for Qux {
    |          ++++++++++
 
 error[E0229]: associated item constraints are not allowed here
-  --> $DIR/associated-types-eq-2.rs:85:10
+  --> $DIR/associated-types-eq-2.rs:84:10
    |
 LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
    |          ^^^^^^ associated item constraint not allowed here
@@ -249,24 +231,8 @@ help: consider removing this associated item binding
 LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
    |          ~~~~~~~
 
-error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
-  --> $DIR/associated-types-eq-2.rs:93:6
-   |
-LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
-   |      ^^^ expected 3 generic arguments
-   |
-note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
-  --> $DIR/associated-types-eq-2.rs:69:7
-   |
-LL | trait Tr3<const N: i32, T2, T3> {
-   |       ^^^ ------------  --  --
-help: add missing generic arguments
-   |
-LL | impl Tr3<N, T2, T3, N = u32, T2 = Qux, T3 = usize> for Bar {
-   |          ++++++++++
-
 error[E0229]: associated item constraints are not allowed here
-  --> $DIR/associated-types-eq-2.rs:93:10
+  --> $DIR/associated-types-eq-2.rs:92:10
    |
 LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
    |          ^^^^^^^ associated item constraint not allowed here
@@ -277,7 +243,7 @@ LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
    |          ~~~~~~~~
 
 error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
-  --> $DIR/associated-types-eq-2.rs:100:6
+  --> $DIR/associated-types-eq-2.rs:98:6
    |
 LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
    |      ^^^ -- supplied 1 generic argument
@@ -295,7 +261,7 @@ LL | impl Tr3<42, T2, T3, T2 = 42, T3 = usize> for Bar {
    |            ++++++++
 
 error[E0229]: associated item constraints are not allowed here
-  --> $DIR/associated-types-eq-2.rs:100:14
+  --> $DIR/associated-types-eq-2.rs:98:14
    |
 LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
    |              ^^^^^^^ associated item constraint not allowed here
@@ -306,7 +272,7 @@ LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
    |            ~~~~~~~~~
 
 error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
-  --> $DIR/associated-types-eq-2.rs:108:6
+  --> $DIR/associated-types-eq-2.rs:106:6
    |
 LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
    |      ^^^ expected 3 generic arguments
@@ -322,7 +288,7 @@ LL | impl Tr3<N, T2, T3, X = 42, Y = Qux, Z = usize> for Bar {
    |          ++++++++++
 
 error[E0229]: associated item constraints are not allowed here
-  --> $DIR/associated-types-eq-2.rs:108:10
+  --> $DIR/associated-types-eq-2.rs:106:10
    |
 LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
    |          ^^^^^^ associated item constraint not allowed here
@@ -333,13 +299,13 @@ LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
    |          ~~~~~~~
 
 error[E0107]: struct takes 1 generic argument but 0 generic arguments were supplied
-  --> $DIR/associated-types-eq-2.rs:119:13
+  --> $DIR/associated-types-eq-2.rs:117:13
    |
 LL | impl<'a, T> St<'a , T = Qux> {
    |             ^^ expected 1 generic argument
    |
 note: struct defined here, with 1 generic parameter: `T`
-  --> $DIR/associated-types-eq-2.rs:117:8
+  --> $DIR/associated-types-eq-2.rs:115:8
    |
 LL | struct St<'a, T> { v: &'a T }
    |        ^^     -
@@ -349,7 +315,7 @@ LL | impl<'a, T> St<'a, T , T = Qux> {
    |                  +++
 
 error[E0229]: associated item constraints are not allowed here
-  --> $DIR/associated-types-eq-2.rs:119:21
+  --> $DIR/associated-types-eq-2.rs:117:21
    |
 LL | impl<'a, T> St<'a , T = Qux> {
    |                     ^^^^^^^ associated item constraint not allowed here
@@ -359,7 +325,7 @@ help: to use `Qux` as a generic argument specify it directly
 LL | impl<'a, T> St<'a , Qux> {
    |                     ~~~
 
-error: aborting due to 27 previous errors
+error: aborting due to 25 previous errors
 
 Some errors have detailed explanations: E0046, E0107, E0229, E0658.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr
index 0fc1bb0b00f..010f51df15a 100644
--- a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr
+++ b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr
@@ -31,18 +31,6 @@ help: consider further restricting `Self`
 LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
    |                            +++++++++++++++++++++++++
 
-error[E0271]: type mismatch resolving `<Self as Deref>::Target == str`
-  --> $DIR/defaults-unsound-62211-1.rs:24:96
-   |
-LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
-   |                                                                                                ^^^^ types differ
-   |
-note: required by a bound in `UncheckedCopy::Output`
-  --> $DIR/defaults-unsound-62211-1.rs:24:31
-   |
-LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
-   |                               ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
-
 error[E0277]: the trait bound `Self: Deref` is not satisfied
   --> $DIR/defaults-unsound-62211-1.rs:24:96
    |
@@ -50,10 +38,10 @@ LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + Fro
    |                                                                                                ^^^^ the trait `Deref` is not implemented for `Self`
    |
 note: required by a bound in `UncheckedCopy::Output`
-  --> $DIR/defaults-unsound-62211-1.rs:24:25
+  --> $DIR/defaults-unsound-62211-1.rs:24:31
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
-   |                         ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
+   |                               ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
 help: consider further restricting `Self`
    |
 LL | trait UncheckedCopy: Sized + Deref {
@@ -75,7 +63,6 @@ help: consider further restricting `Self`
 LL | trait UncheckedCopy: Sized + Copy {
    |                            ++++++
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0271, E0277.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.rs b/tests/ui/associated-types/defaults-unsound-62211-1.rs
index f054611ed78..124bac0ea72 100644
--- a/tests/ui/associated-types/defaults-unsound-62211-1.rs
+++ b/tests/ui/associated-types/defaults-unsound-62211-1.rs
@@ -26,7 +26,6 @@ trait UncheckedCopy: Sized {
     //~| ERROR the trait bound `Self: Deref` is not satisfied
     //~| ERROR cannot add-assign `&'static str` to `Self`
     //~| ERROR `Self` doesn't implement `std::fmt::Display`
-    //[next]~| ERROR type mismatch resolving `<Self as Deref>::Target == str`
 
     // We said the Output type was Copy, so we can Copy it freely!
     fn unchecked_copy(other: &Self::Output) -> Self::Output {
diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr
index 751352d7c16..93478946570 100644
--- a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr
+++ b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr
@@ -31,18 +31,6 @@ help: consider further restricting `Self`
 LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
    |                            +++++++++++++++++++++++++
 
-error[E0271]: type mismatch resolving `<Self as Deref>::Target == str`
-  --> $DIR/defaults-unsound-62211-2.rs:24:96
-   |
-LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
-   |                                                                                                ^^^^ types differ
-   |
-note: required by a bound in `UncheckedCopy::Output`
-  --> $DIR/defaults-unsound-62211-2.rs:24:31
-   |
-LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
-   |                               ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
-
 error[E0277]: the trait bound `Self: Deref` is not satisfied
   --> $DIR/defaults-unsound-62211-2.rs:24:96
    |
@@ -50,10 +38,10 @@ LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + Fro
    |                                                                                                ^^^^ the trait `Deref` is not implemented for `Self`
    |
 note: required by a bound in `UncheckedCopy::Output`
-  --> $DIR/defaults-unsound-62211-2.rs:24:25
+  --> $DIR/defaults-unsound-62211-2.rs:24:31
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
-   |                         ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
+   |                               ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
 help: consider further restricting `Self`
    |
 LL | trait UncheckedCopy: Sized + Deref {
@@ -75,7 +63,6 @@ help: consider further restricting `Self`
 LL | trait UncheckedCopy: Sized + Copy {
    |                            ++++++
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0271, E0277.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.rs b/tests/ui/associated-types/defaults-unsound-62211-2.rs
index 956f14df0d5..998c39b5bad 100644
--- a/tests/ui/associated-types/defaults-unsound-62211-2.rs
+++ b/tests/ui/associated-types/defaults-unsound-62211-2.rs
@@ -26,7 +26,6 @@ trait UncheckedCopy: Sized {
     //~| ERROR the trait bound `Self: Deref` is not satisfied
     //~| ERROR cannot add-assign `&'static str` to `Self`
     //~| ERROR `Self` doesn't implement `std::fmt::Display`
-    //[next]~| ERROR type mismatch resolving `<Self as Deref>::Target == str`
 
     // We said the Output type was Copy, so we can Copy it freely!
     fn unchecked_copy(other: &Self::Output) -> Self::Output {
diff --git a/tests/ui/associated-types/issue-54108.next.stderr b/tests/ui/associated-types/issue-54108.next.stderr
index 9f6f00e7ca8..5e2fa551afe 100644
--- a/tests/ui/associated-types/issue-54108.next.stderr
+++ b/tests/ui/associated-types/issue-54108.next.stderr
@@ -1,15 +1,3 @@
-error[E0271]: type mismatch resolving `<<T as SubEncoder>::ActualSize as Add>::Output == <T as SubEncoder>::ActualSize`
-  --> $DIR/issue-54108.rs:23:17
-   |
-LL |     type Size = <Self as SubEncoder>::ActualSize;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
-   |
-note: required by a bound in `Encoder::Size`
-  --> $DIR/issue-54108.rs:8:20
-   |
-LL |     type Size: Add<Output = Self::Size>;
-   |                    ^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size`
-
 error[E0277]: cannot add `<T as SubEncoder>::ActualSize` to `<T as SubEncoder>::ActualSize`
   --> $DIR/issue-54108.rs:23:17
    |
@@ -18,16 +6,15 @@ LL |     type Size = <Self as SubEncoder>::ActualSize;
    |
    = help: the trait `Add` is not implemented for `<T as SubEncoder>::ActualSize`
 note: required by a bound in `Encoder::Size`
-  --> $DIR/issue-54108.rs:8:16
+  --> $DIR/issue-54108.rs:8:20
    |
 LL |     type Size: Add<Output = Self::Size>;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size`
+   |                    ^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size`
 help: consider further restricting the associated type
    |
 LL |     T: SubEncoder, <T as SubEncoder>::ActualSize: Add
    |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0271, E0277.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/associated-types/issue-54108.rs b/tests/ui/associated-types/issue-54108.rs
index 7c652fd7f49..bcc54f33362 100644
--- a/tests/ui/associated-types/issue-54108.rs
+++ b/tests/ui/associated-types/issue-54108.rs
@@ -22,7 +22,6 @@ where
 {
     type Size = <Self as SubEncoder>::ActualSize;
     //~^ ERROR: cannot add `<T as SubEncoder>::ActualSize` to `<T as SubEncoder>::ActualSize`
-    //[next]~| ERROR type mismatch resolving `<<T as SubEncoder>::ActualSize as Add>::Output == <T as SubEncoder>::ActualSize`
 
     fn foo(&self) -> Self::Size {
         self.bar() + self.bar()
diff --git a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr
index b07c5735dff..54960ae60bc 100644
--- a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr
+++ b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr
@@ -12,6 +12,11 @@ error[E0229]: associated item constraints are not allowed here
    |
 LL | impl Super1<'_, bar(): Send> for () {}
    |                 ^^^^^^^^^^^ associated item constraint not allowed here
+   |
+help: consider removing this associated item constraint
+   |
+LL | impl Super1<'_, bar(): Send> for () {}
+   |               ~~~~~~~~~~~~~
 
 error[E0046]: not all trait items implemented, missing: `bar`
   --> $DIR/rtn-in-impl-signature.rs:10:1
diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
index 47bb1a059be..4773ac4ccf7 100644
--- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
+++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'static u32: Defaulted` is not satisfied
   --> $DIR/typeck-default-trait-impl-precedence.rs:19:20
    |
 LL |     is_defaulted::<&'static u32>();
-   |                    ^^^^^^^^^^^^ the trait `Signed` is not implemented for `&'static u32`, which is required by `&'static u32: Defaulted`
+   |                    ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`, which is required by `&'static u32: Defaulted`
    |
 note: required for `&'static u32` to implement `Defaulted`
   --> $DIR/typeck-default-trait-impl-precedence.rs:10:19
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index 3796dca1727..d2026a68450 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -147,7 +147,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_env = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_env` are: ``, `gnu`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `p2`, `psx`, `relibc`, `sgx`, and `uclibc`
+   = note: expected values for `target_env` are: ``, `gnu`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `p1`, `p2`, `psx`, `relibc`, `sgx`, and `uclibc`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
diff --git a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr
index 6e41561f1a7..b6636d4de86 100644
--- a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr
+++ b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr
@@ -1,8 +1,8 @@
-error[E0284]: type annotations needed: cannot satisfy `<dyn Object<U, Output = T> as Object<U>>::Output == T`
+error[E0284]: type annotations needed: cannot normalize `<dyn Object<U, Output = T> as Object<U>>::Output`
   --> $DIR/indirect-impl-for-trait-obj-coherence.rs:25:41
    |
 LL |     foo::<dyn Object<U, Output = T>, U>(x)
-   |                                         ^ cannot satisfy `<dyn Object<U, Output = T> as Object<U>>::Output == T`
+   |                                         ^ cannot normalize `<dyn Object<U, Output = T> as Object<U>>::Output`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs
index 0b66a6e7830..abfd51c2008 100644
--- a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs
+++ b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs
@@ -23,7 +23,7 @@ fn foo<T: ?Sized, U>(x: <T as Object<U>>::Output) -> U {
 #[allow(dead_code)]
 fn transmute<T, U>(x: T) -> U {
     foo::<dyn Object<U, Output = T>, U>(x)
-    //[next]~^ ERROR type annotations needed: cannot satisfy `<dyn Object<U, Output = T> as Object<U>>::Output == T`
+    //[next]~^ ERROR type annotations needed: cannot normalize `<dyn Object<U, Output = T> as Object<U>>::Output`
 }
 
 fn main() {}
diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr
index f32bb1301da..bd65cee58d9 100644
--- a/tests/ui/coherence/occurs-check/associated-type.next.stderr
+++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr
@@ -16,11 +16,11 @@ LL | |     for<'a> *const T: ToUnit<'a>,
    |
    = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
 
-error[E0284]: type annotations needed: cannot satisfy `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc == usize`
+error[E0284]: type annotations needed: cannot normalize `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc`
   --> $DIR/associated-type.rs:44:59
    |
 LL |     foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize);
-   |                                                           ^^^^^^ cannot satisfy `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc == usize`
+   |                                                           ^^^^^^ cannot normalize `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/coherence/occurs-check/associated-type.rs b/tests/ui/coherence/occurs-check/associated-type.rs
index ac1236c554a..df03d5f60a0 100644
--- a/tests/ui/coherence/occurs-check/associated-type.rs
+++ b/tests/ui/coherence/occurs-check/associated-type.rs
@@ -42,5 +42,5 @@ fn foo<T: Overlap<U>, U>(x: T::Assoc) -> T::Assoc {
 
 fn main() {
     foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize);
-    //[next]~^ ERROR: cannot satisfy
+    //[next]~^ ERROR: cannot normalize
 }
diff --git a/tests/ui/const-generics/issues/issue-82956.stderr b/tests/ui/const-generics/issues/issue-82956.stderr
index d0fc7112426..a956fc741f4 100644
--- a/tests/ui/const-generics/issues/issue-82956.stderr
+++ b/tests/ui/const-generics/issues/issue-82956.stderr
@@ -4,7 +4,7 @@ error[E0433]: failed to resolve: use of undeclared type `IntoIter`
 LL |         let mut iter = IntoIter::new(self);
    |                        ^^^^^^^^ use of undeclared type `IntoIter`
    |
-help: consider importing one of these items
+help: consider importing one of these structs
    |
 LL + use std::array::IntoIter;
    |
diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs
index fbf1553c182..c15482f92dc 100644
--- a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs
+++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs
@@ -7,8 +7,7 @@ struct Bar;
 const T: usize = 42;
 
 impl Foo<N = 3> for Bar {
-//~^ ERROR trait takes 1 generic argument but 0 generic arguments were supplied
-//~| ERROR associated item constraints are not allowed here
+//~^ ERROR associated item constraints are not allowed here
 //~| ERROR associated const equality is incomplete
     fn do_x(&self) -> [u8; 3] {
         [0u8; 3]
diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
index a132859b412..78cddcc234c 100644
--- a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
+++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
@@ -8,22 +8,6 @@ LL | impl Foo<N = 3> for Bar {
    = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
-  --> $DIR/issue-89013-no-kw.rs:9:6
-   |
-LL | impl Foo<N = 3> for Bar {
-   |      ^^^ expected 1 generic argument
-   |
-note: trait defined here, with 1 generic parameter: `N`
-  --> $DIR/issue-89013-no-kw.rs:1:7
-   |
-LL | trait Foo<const N: usize> {
-   |       ^^^ --------------
-help: add missing generic argument
-   |
-LL | impl Foo<N, N = 3> for Bar {
-   |          ++
-
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/issue-89013-no-kw.rs:9:10
    |
@@ -35,7 +19,7 @@ help: to use `3` as a generic argument specify it directly
 LL | impl Foo<3> for Bar {
    |          ~
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0107, E0229, E0658.
-For more information about an error, try `rustc --explain E0107`.
+Some errors have detailed explanations: E0229, E0658.
+For more information about an error, try `rustc --explain E0229`.
diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013.rs
index c9c7ff3a170..6302f7f2ad5 100644
--- a/tests/ui/const-generics/parser-error-recovery/issue-89013.rs
+++ b/tests/ui/const-generics/parser-error-recovery/issue-89013.rs
@@ -8,7 +8,6 @@ const T: usize = 42;
 
 impl Foo<N = const 3> for Bar {
 //~^ ERROR expected lifetime, type, or constant, found keyword `const`
-//~| ERROR trait takes 1 generic
 //~| ERROR associated item constraints are not allowed here
 //~| ERROR associated const equality is incomplete
     fn do_x(&self) -> [u8; 3] {
diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr
index 2fdd1208565..387eb226e70 100644
--- a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr
+++ b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr
@@ -20,22 +20,6 @@ LL | impl Foo<N = const 3> for Bar {
    = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
-  --> $DIR/issue-89013.rs:9:6
-   |
-LL | impl Foo<N = const 3> for Bar {
-   |      ^^^ expected 1 generic argument
-   |
-note: trait defined here, with 1 generic parameter: `N`
-  --> $DIR/issue-89013.rs:1:7
-   |
-LL | trait Foo<const N: usize> {
-   |       ^^^ --------------
-help: add missing generic argument
-   |
-LL | impl Foo<N, N = const 3> for Bar {
-   |          ++
-
 error[E0229]: associated item constraints are not allowed here
   --> $DIR/issue-89013.rs:9:10
    |
@@ -47,7 +31,7 @@ help: to use `3` as a generic argument specify it directly
 LL | impl Foo<3> for Bar {
    |          ~
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0107, E0229, E0658.
-For more information about an error, try `rustc --explain E0107`.
+Some errors have detailed explanations: E0229, E0658.
+For more information about an error, try `rustc --explain E0229`.
diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.rs b/tests/ui/consts/const_refs_to_static-ice-121413.rs
index 8a24fb799b6..8fc3912efd0 100644
--- a/tests/ui/consts/const_refs_to_static-ice-121413.rs
+++ b/tests/ui/consts/const_refs_to_static-ice-121413.rs
@@ -5,12 +5,16 @@
 // ignore-tidy-linelength
 #![feature(const_refs_to_static)]
 const REF_INTERIOR_MUT: &usize = {
+    //~^ HELP consider importing this struct
     static FOO: Sync = AtomicUsize::new(0);
     //~^ ERROR failed to resolve: use of undeclared type `AtomicUsize`
     //~| WARN trait objects without an explicit `dyn` are deprecated
     //~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
     //~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
     //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+    //~| HELP if this is an object-safe trait, use `dyn`
+    //~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static)`
+    //~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static)`
     unsafe { &*(&FOO as *const _ as *const usize) }
 };
 pub fn main() {}
diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.stderr b/tests/ui/consts/const_refs_to_static-ice-121413.stderr
index c977c698a92..fbe32a70293 100644
--- a/tests/ui/consts/const_refs_to_static-ice-121413.stderr
+++ b/tests/ui/consts/const_refs_to_static-ice-121413.stderr
@@ -1,5 +1,5 @@
 error[E0433]: failed to resolve: use of undeclared type `AtomicUsize`
-  --> $DIR/const_refs_to_static-ice-121413.rs:8:24
+  --> $DIR/const_refs_to_static-ice-121413.rs:9:24
    |
 LL |     static FOO: Sync = AtomicUsize::new(0);
    |                        ^^^^^^^^^^^ use of undeclared type `AtomicUsize`
@@ -10,7 +10,7 @@ LL + use std::sync::atomic::AtomicUsize;
    |
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/const_refs_to_static-ice-121413.rs:8:17
+  --> $DIR/const_refs_to_static-ice-121413.rs:9:17
    |
 LL |     static FOO: Sync = AtomicUsize::new(0);
    |                 ^^^^
@@ -24,7 +24,7 @@ LL |     static FOO: dyn Sync = AtomicUsize::new(0);
    |                 +++
 
 error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
-  --> $DIR/const_refs_to_static-ice-121413.rs:8:17
+  --> $DIR/const_refs_to_static-ice-121413.rs:9:17
    |
 LL |     static FOO: Sync = AtomicUsize::new(0);
    |                 ^^^^ doesn't have a size known at compile-time
@@ -32,7 +32,7 @@ LL |     static FOO: Sync = AtomicUsize::new(0);
    = help: the trait `Sized` is not implemented for `(dyn Sync + 'static)`
 
 error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
-  --> $DIR/const_refs_to_static-ice-121413.rs:8:24
+  --> $DIR/const_refs_to_static-ice-121413.rs:9:24
    |
 LL |     static FOO: Sync = AtomicUsize::new(0);
    |                        ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
diff --git a/tests/ui/consts/dangling-alloc-id-ice.rs b/tests/ui/consts/dangling-alloc-id-ice.rs
index 6b07b8b3cc8..76d6f33baf3 100644
--- a/tests/ui/consts/dangling-alloc-id-ice.rs
+++ b/tests/ui/consts/dangling-alloc-id-ice.rs
@@ -10,7 +10,7 @@ union Foo<'a> {
 }
 
 const FOO: &() = {
-    //~^ ERROR encountered dangling pointer
+    //~^ ERROR it is undefined behavior to use this value
     let y = ();
     unsafe { Foo { y: &y }.long_live_the_unit }
 };
diff --git a/tests/ui/consts/dangling-alloc-id-ice.stderr b/tests/ui/consts/dangling-alloc-id-ice.stderr
index de31acf9fa4..881c0b162ed 100644
--- a/tests/ui/consts/dangling-alloc-id-ice.stderr
+++ b/tests/ui/consts/dangling-alloc-id-ice.stderr
@@ -1,8 +1,14 @@
-error: encountered dangling pointer in final value of constant
+error[E0080]: it is undefined behavior to use this value
   --> $DIR/dangling-alloc-id-ice.rs:12:1
    |
 LL | const FOO: &() = {
-   | ^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (use-after-free)
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+               HEX_DUMP
+           }
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/dangling-zst-ice-issue-126393.rs b/tests/ui/consts/dangling-zst-ice-issue-126393.rs
new file mode 100644
index 00000000000..917aa0572fc
--- /dev/null
+++ b/tests/ui/consts/dangling-zst-ice-issue-126393.rs
@@ -0,0 +1,15 @@
+// Strip out raw byte dumps to make comparison platform-independent:
+//@ normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
+//@ normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*A(LLOC)?[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
+//@ normalize-stderr-test "HEX_DUMP\s*\n\s*HEX_DUMP" -> "HEX_DUMP"
+
+pub struct Wrapper;
+pub static MAGIC_FFI_REF: &'static Wrapper = unsafe {
+//~^ERROR: it is undefined behavior to use this value
+    std::mem::transmute(&{
+        let y = 42;
+        y
+    })
+};
+
+fn main() {}
diff --git a/tests/ui/consts/dangling-zst-ice-issue-126393.stderr b/tests/ui/consts/dangling-zst-ice-issue-126393.stderr
new file mode 100644
index 00000000000..d32b427f14e
--- /dev/null
+++ b/tests/ui/consts/dangling-zst-ice-issue-126393.stderr
@@ -0,0 +1,14 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/dangling-zst-ice-issue-126393.rs:7:1
+   |
+LL | pub static MAGIC_FFI_REF: &'static Wrapper = unsafe {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (use-after-free)
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+               HEX_DUMP
+           }
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/delegation/macro-inside-list.rs b/tests/ui/delegation/macro-inside-list.rs
index 16c74d396ef..d07a4e47dd4 100644
--- a/tests/ui/delegation/macro-inside-list.rs
+++ b/tests/ui/delegation/macro-inside-list.rs
@@ -14,9 +14,9 @@ struct S(u8);
 
 // Macro expansion works inside delegation items.
 macro_rules! u8 { () => { u8 } }
-macro_rules! self_0 { () => { &self.0 } }
+macro_rules! self_0 { ($self:ident) => { &$self.0 } }
 impl Trait for S {
-    reuse <u8!() as Trait>::{foo, bar} { self_0!() }
+    reuse <u8!() as Trait>::{foo, bar} { self_0!(self) }
 }
 
 fn main() {
diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs
index 5f78de97638..25d7a4cb895 100644
--- a/tests/ui/delegation/not-supported.rs
+++ b/tests/ui/delegation/not-supported.rs
@@ -70,12 +70,16 @@ mod opaque {
 
         pub fn opaque_arg(_: impl Trait) -> i32 { 0 }
         pub fn opaque_ret() -> impl Trait { unimplemented!() }
+        //~^ warn: this function depends on never type fallback being `()`
+        //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
     }
     reuse to_reuse::opaque_arg;
     //~^ ERROR delegation with early bound generics is not supported yet
 
     trait ToReuse {
         fn opaque_ret() -> impl Trait { unimplemented!() }
+        //~^ warn: this function depends on never type fallback being `()`
+        //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
     }
 
     // FIXME: Inherited `impl Trait`s create query cycles when used inside trait impls.
diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr
index e2cb04f977b..4ce01fd5d88 100644
--- a/tests/ui/delegation/not-supported.stderr
+++ b/tests/ui/delegation/not-supported.stderr
@@ -107,7 +107,7 @@ LL |         reuse Trait::foo2 { &self.0 }
    |                      ^^^^
 
 error: delegation with early bound generics is not supported yet
-  --> $DIR/not-supported.rs:74:21
+  --> $DIR/not-supported.rs:76:21
    |
 LL |         pub fn opaque_arg(_: impl Trait) -> i32 { 0 }
    |         --------------------------------------- callee defined here
@@ -115,46 +115,77 @@ LL |         pub fn opaque_arg(_: impl Trait) -> i32 { 0 }
 LL |     reuse to_reuse::opaque_arg;
    |                     ^^^^^^^^^^
 
-error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:82:5: 82:24>::{synthetic#0}`
-  --> $DIR/not-supported.rs:83:25
+warning: this function depends on never type fallback being `()`
+  --> $DIR/not-supported.rs:80:9
+   |
+LL |         fn opaque_ret() -> impl Trait { unimplemented!() }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: opaque::Trait` will fail
+  --> $DIR/not-supported.rs:80:28
+   |
+LL |         fn opaque_ret() -> impl Trait { unimplemented!() }
+   |                            ^^^^^^^^^^
+   = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
+
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:86:5: 86:24>::{synthetic#0}`
+  --> $DIR/not-supported.rs:87:25
    |
 LL |         reuse to_reuse::opaque_ret;
    |                         ^^^^^^^^^^
    |
 note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
-  --> $DIR/not-supported.rs:83:25
+  --> $DIR/not-supported.rs:87:25
    |
 LL |         reuse to_reuse::opaque_ret;
    |                         ^^^^^^^^^^
-   = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:82:5: 82:24>::{synthetic#0}`, completing the cycle
-note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:82:5: 82:24>` is well-formed
-  --> $DIR/not-supported.rs:82:5
+   = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:86:5: 86:24>::{synthetic#0}`, completing the cycle
+note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:86:5: 86:24>` is well-formed
+  --> $DIR/not-supported.rs:86:5
    |
 LL |     impl ToReuse for u8 {
    |     ^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:85:5: 85:25>::{synthetic#0}`
-  --> $DIR/not-supported.rs:86:24
+warning: this function depends on never type fallback being `()`
+  --> $DIR/not-supported.rs:72:9
+   |
+LL |         pub fn opaque_ret() -> impl Trait { unimplemented!() }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: opaque::Trait` will fail
+  --> $DIR/not-supported.rs:72:32
+   |
+LL |         pub fn opaque_ret() -> impl Trait { unimplemented!() }
+   |                                ^^^^^^^^^^
+
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:89:5: 89:25>::{synthetic#0}`
+  --> $DIR/not-supported.rs:90:24
    |
 LL |         reuse ToReuse::opaque_ret;
    |                        ^^^^^^^^^^
    |
 note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
-  --> $DIR/not-supported.rs:86:24
+  --> $DIR/not-supported.rs:90:24
    |
 LL |         reuse ToReuse::opaque_ret;
    |                        ^^^^^^^^^^
-   = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:85:5: 85:25>::{synthetic#0}`, completing the cycle
-note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:85:5: 85:25>` is well-formed
-  --> $DIR/not-supported.rs:85:5
+   = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:89:5: 89:25>::{synthetic#0}`, completing the cycle
+note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:89:5: 89:25>` is well-formed
+  --> $DIR/not-supported.rs:89:5
    |
 LL |     impl ToReuse for u16 {
    |     ^^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error: recursive delegation is not supported yet
-  --> $DIR/not-supported.rs:99:22
+  --> $DIR/not-supported.rs:103:22
    |
 LL |         pub reuse to_reuse2::foo;
    |                              --- callee defined here
@@ -162,7 +193,7 @@ LL |         pub reuse to_reuse2::foo;
 LL |     reuse to_reuse1::foo;
    |                      ^^^
 
-error: aborting due to 16 previous errors
+error: aborting due to 16 previous errors; 2 warnings emitted
 
 Some errors have detailed explanations: E0049, E0195, E0391.
 For more information about an error, try `rustc --explain E0049`.
diff --git a/tests/ui/delegation/self-hygiene.rs b/tests/ui/delegation/self-hygiene.rs
new file mode 100644
index 00000000000..dac6c319416
--- /dev/null
+++ b/tests/ui/delegation/self-hygiene.rs
@@ -0,0 +1,20 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+macro_rules! emit_self { () => { self } }
+//~^ ERROR expected value, found module `self`
+//~| ERROR expected value, found module `self`
+
+struct S;
+impl S {
+    fn method(self) {
+        emit_self!();
+    }
+}
+
+fn foo(arg: u8) {}
+reuse foo as bar {
+    emit_self!()
+}
+
+fn main() {}
diff --git a/tests/ui/delegation/self-hygiene.stderr b/tests/ui/delegation/self-hygiene.stderr
new file mode 100644
index 00000000000..fa64b7d1d7f
--- /dev/null
+++ b/tests/ui/delegation/self-hygiene.stderr
@@ -0,0 +1,31 @@
+error[E0424]: expected value, found module `self`
+  --> $DIR/self-hygiene.rs:4:34
+   |
+LL |   macro_rules! emit_self { () => { self } }
+   |                                    ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+...
+LL | /     fn method(self) {
+LL | |         emit_self!();
+   | |         ------------ in this macro invocation
+LL | |     }
+   | |_____- this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters
+   |
+   = note: this error originates in the macro `emit_self` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0424]: expected value, found module `self`
+  --> $DIR/self-hygiene.rs:4:34
+   |
+LL |   macro_rules! emit_self { () => { self } }
+   |                                    ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+...
+LL | / reuse foo as bar {
+LL | |     emit_self!()
+   | |     ------------ in this macro invocation
+LL | | }
+   | |_- delegation supports a `self` parameter, but a macro invocation can only access identifiers it receives from parameters
+   |
+   = note: this error originates in the macro `emit_self` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0424`.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
index 568cb8931a1..d189d2dbded 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
@@ -25,7 +25,7 @@ LL |     SelectInt.check("bar");
    = help: the trait `AsExpression<Text>` is implemented for `&str`
    = help: for that trait implementation, expected `Text`, found `Integer`
 
-error[E0271]: type mismatch resolving `<&str as AsExpression<<SelectInt as Expression>::SqlType>>::Expression == _`
+error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text`
   --> $DIR/as_expression.rs:57:5
    |
 LL |     SelectInt.check("bar");
diff --git a/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr b/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr
index 5c610f36322..b1a15b8594a 100644
--- a/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr
+++ b/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr
@@ -22,7 +22,7 @@ error[E0425]: cannot find value `Set` in this scope
 LL | fn setup() -> Set { Set }
    |                     ^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing one of these unit variants
    |
 LL + use AffixHeart::Set;
    |
diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr
new file mode 100644
index 00000000000..134fd098b7e
--- /dev/null
+++ b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr
@@ -0,0 +1,33 @@
+warning: this function depends on never type fallback being `()`
+  --> $DIR/never-type-fallback-breaking.rs:15:1
+   |
+LL | fn m() {
+   | ^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: Default` will fail
+  --> $DIR/never-type-fallback-breaking.rs:19:17
+   |
+LL |         true => Default::default(),
+   |                 ^^^^^^^^^^^^^^^^^^
+   = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
+
+warning: this function depends on never type fallback being `()`
+  --> $DIR/never-type-fallback-breaking.rs:27:1
+   |
+LL | fn q() -> Option<()> {
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: Default` will fail
+  --> $DIR/never-type-fallback-breaking.rs:34:5
+   |
+LL |     deserialize()?;
+   |     ^^^^^^^^^^^^^
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr
index e9a8882eb6c..461e4ae0bdf 100644
--- a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr
+++ b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `!: Default` is not satisfied
-  --> $DIR/never-type-fallback-breaking.rs:17:17
+  --> $DIR/never-type-fallback-breaking.rs:19:17
    |
 LL |         true => Default::default(),
    |                 ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
@@ -8,7 +8,7 @@ LL |         true => Default::default(),
    = help: did you intend to use the type `()` here instead?
 
 error[E0277]: the trait bound `!: Default` is not satisfied
-  --> $DIR/never-type-fallback-breaking.rs:30:5
+  --> $DIR/never-type-fallback-breaking.rs:34:5
    |
 LL |     deserialize()?;
    |     ^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
@@ -16,7 +16,7 @@ LL |     deserialize()?;
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
    = help: did you intend to use the type `()` here instead?
 note: required by a bound in `deserialize`
-  --> $DIR/never-type-fallback-breaking.rs:26:23
+  --> $DIR/never-type-fallback-breaking.rs:30:23
    |
 LL |     fn deserialize<T: Default>() -> Option<T> {
    |                       ^^^^^^^ required by this bound in `deserialize`
diff --git a/tests/ui/editions/never-type-fallback-breaking.rs b/tests/ui/editions/never-type-fallback-breaking.rs
index 7dfa4702807..7b4a1b1de04 100644
--- a/tests/ui/editions/never-type-fallback-breaking.rs
+++ b/tests/ui/editions/never-type-fallback-breaking.rs
@@ -13,6 +13,8 @@ fn main() {
 }
 
 fn m() {
+    //[e2021]~^ this function depends on never type fallback being `()`
+    //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
     let x = match true {
         true => Default::default(),
         //[e2024]~^ error: the trait bound `!: Default` is not satisfied
@@ -23,6 +25,8 @@ fn m() {
 }
 
 fn q() -> Option<()> {
+    //[e2021]~^ this function depends on never type fallback being `()`
+    //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
     fn deserialize<T: Default>() -> Option<T> {
         Some(T::default())
     }
diff --git a/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.rs b/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.rs
new file mode 100644
index 00000000000..e700999ae4b
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.rs
@@ -0,0 +1,9 @@
+macro_rules! join {
+    ($lhs:ident, $rhs:ident) => {
+        let ${concat($lhs, $rhs)}: () = ();
+        //~^ ERROR the `concat` meta-variable expression is unstable
+    };
+}
+
+fn main() {
+}
diff --git a/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.stderr b/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.stderr
new file mode 100644
index 00000000000..5b2589d8c89
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.stderr
@@ -0,0 +1,13 @@
+error[E0658]: the `concat` meta-variable expression is unstable
+  --> $DIR/feature-gate-macro-metavar-expr-concat.rs:3:14
+   |
+LL |         let ${concat($lhs, $rhs)}: () = ();
+   |              ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #124225 <https://github.com/rust-lang/rust/issues/124225> for more information
+   = help: add `#![feature(macro_metavar_expr_concat)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr
index 2c372b6c3a7..9b5d84b5b09 100644
--- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr
+++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `i32: Baz<Self>` is not satisfied
   --> $DIR/assume-gat-normalization-for-nested-goals.rs:9:30
    |
 LL |     type Bar<T>: Baz<Self> = i32;
-   |                              ^^^ the trait `Eq<i32>` is not implemented for `i32`, which is required by `i32: Baz<Self>`
+   |                              ^^^ the trait `Eq<i32>` is not implemented for `<Self as Foo>::Bar<()>`, which is required by `i32: Baz<Self>`
    |
 note: required for `i32` to implement `Baz<Self>`
   --> $DIR/assume-gat-normalization-for-nested-goals.rs:16:23
diff --git a/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.rs b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.rs
new file mode 100644
index 00000000000..68879a0af29
--- /dev/null
+++ b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.rs
@@ -0,0 +1,26 @@
+//@ error-pattern: r#T: 'static
+//@ error-pattern: r#K: 'static
+//@ error-pattern: T: 'static=
+
+// https://github.com/rust-lang/rust/issues/124785
+
+struct Foo<T, K = i32>(&'static T, &'static K);
+//~^ ERROR: the parameter type `T` may not live long enough
+//~| ERROR: the parameter type `K` may not live long enough
+
+struct Bar<r#T, r#K = i32>(&'static r#T, &'static r#K);
+//~^ ERROR: the parameter type `T` may not live long enough
+//~| ERROR: the parameter type `K` may not live long enough
+
+struct Boo<T= i32>(&'static T);
+//~^ ERROR: the parameter type `T` may not live long enough
+
+struct Far<T
+= i32>(&'static T);
+//~^ ERROR: the parameter type `T` may not live long enough
+
+struct S<'a, K: 'a = i32>(&'static K);
+//~^ ERROR: lifetime parameter `'a` is never used
+//~| ERROR: the parameter type `K` may not live long enough
+
+fn main() {}
diff --git a/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr
new file mode 100644
index 00000000000..7d985a9013f
--- /dev/null
+++ b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr
@@ -0,0 +1,110 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:7:24
+   |
+LL | struct Foo<T, K = i32>(&'static T, &'static K);
+   |                        ^^^^^^^^^^
+   |                        |
+   |                        the parameter type `T` must be valid for the static lifetime...
+   |                        ...so that the reference type `&'static T` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct Foo<T: 'static, K = i32>(&'static T, &'static K);
+   |             +++++++++
+
+error[E0310]: the parameter type `K` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:7:36
+   |
+LL | struct Foo<T, K = i32>(&'static T, &'static K);
+   |                                    ^^^^^^^^^^
+   |                                    |
+   |                                    the parameter type `K` must be valid for the static lifetime...
+   |                                    ...so that the reference type `&'static K` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct Foo<T, K: 'static = i32>(&'static T, &'static K);
+   |                +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:11:28
+   |
+LL | struct Bar<r#T, r#K = i32>(&'static r#T, &'static r#K);
+   |                            ^^^^^^^^^^^^
+   |                            |
+   |                            the parameter type `T` must be valid for the static lifetime...
+   |                            ...so that the reference type `&'static T` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct Bar<r#T: 'static, r#K = i32>(&'static r#T, &'static r#K);
+   |               +++++++++
+
+error[E0310]: the parameter type `K` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:11:42
+   |
+LL | struct Bar<r#T, r#K = i32>(&'static r#T, &'static r#K);
+   |                                          ^^^^^^^^^^^^
+   |                                          |
+   |                                          the parameter type `K` must be valid for the static lifetime...
+   |                                          ...so that the reference type `&'static K` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct Bar<r#T, r#K: 'static = i32>(&'static r#T, &'static r#K);
+   |                    +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:15:20
+   |
+LL | struct Boo<T= i32>(&'static T);
+   |                    ^^^^^^^^^^
+   |                    |
+   |                    the parameter type `T` must be valid for the static lifetime...
+   |                    ...so that the reference type `&'static T` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct Boo<T: 'static= i32>(&'static T);
+   |             +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:19:8
+   |
+LL | = i32>(&'static T);
+   |        ^^^^^^^^^^
+   |        |
+   |        the parameter type `T` must be valid for the static lifetime...
+   |        ...so that the reference type `&'static T` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct Far<T: 'static
+   |             +++++++++
+
+error[E0310]: the parameter type `K` may not live long enough
+  --> $DIR/static-lifetime-tip-with-default-type.rs:22:27
+   |
+LL | struct S<'a, K: 'a = i32>(&'static K);
+   |                           ^^^^^^^^^^
+   |                           |
+   |                           the parameter type `K` must be valid for the static lifetime...
+   |                           ...so that the reference type `&'static K` does not outlive the data it points at
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | struct S<'a, K: 'a + 'static = i32>(&'static K);
+   |                    +++++++++
+
+error[E0392]: lifetime parameter `'a` is never used
+  --> $DIR/static-lifetime-tip-with-default-type.rs:22:10
+   |
+LL | struct S<'a, K: 'a = i32>(&'static K);
+   |          ^^ unused lifetime parameter
+   |
+   = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0310, E0392.
+For more information about an error, try `rustc --explain E0310`.
diff --git a/tests/ui/generics/impl-block-params-declared-in-wrong-spot-issue-113073.rs b/tests/ui/generics/impl-block-params-declared-in-wrong-spot-issue-113073.rs
new file mode 100644
index 00000000000..3a5b60e5763
--- /dev/null
+++ b/tests/ui/generics/impl-block-params-declared-in-wrong-spot-issue-113073.rs
@@ -0,0 +1,33 @@
+trait Foo<T> {}
+
+impl Foo<T: Default> for String {}
+//~^ ERROR associated item constraints are not allowed here
+//~| HELP declare the type parameter right after the `impl` keyword
+
+impl Foo<T: 'a + Default> for u8 {}
+//~^ ERROR associated item constraints are not allowed here
+//~| HELP declare the type parameter right after the `impl` keyword
+//~| ERROR use of undeclared lifetime name `'a`
+//~| HELP consider introducing lifetime `'a` here
+
+impl<T> Foo<T: Default> for u16 {}
+//~^ ERROR associated item constraints are not allowed here
+//~| HELP declare the type parameter right after the `impl` keyword
+
+impl<'a> Foo<T: 'a + Default> for u32 {}
+//~^ ERROR associated item constraints are not allowed here
+//~| HELP declare the type parameter right after the `impl` keyword
+
+trait Bar<T, K> {}
+
+impl Bar<T: Default, K: Default> for String {}
+//~^ ERROR associated item constraints are not allowed here
+//~| HELP declare the type parameter right after the `impl` keyword
+
+impl<T> Bar<T, K: Default> for u8 {}
+//~^ ERROR trait takes 2 generic arguments but 1 generic argument was supplied
+//~| HELP add missing generic argument
+//~| ERROR associated item constraints are not allowed here
+//~| HELP declare the type parameter right after the `impl` keyword
+
+fn main() {}
diff --git a/tests/ui/generics/impl-block-params-declared-in-wrong-spot-issue-113073.stderr b/tests/ui/generics/impl-block-params-declared-in-wrong-spot-issue-113073.stderr
new file mode 100644
index 00000000000..dfc6761e17e
--- /dev/null
+++ b/tests/ui/generics/impl-block-params-declared-in-wrong-spot-issue-113073.stderr
@@ -0,0 +1,96 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:7:13
+   |
+LL | impl Foo<T: 'a + Default> for u8 {}
+   |     -       ^^ undeclared lifetime
+   |     |
+   |     help: consider introducing lifetime `'a` here: `<'a>`
+
+error[E0229]: associated item constraints are not allowed here
+  --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:3:10
+   |
+LL | impl Foo<T: Default> for String {}
+   |          ^^^^^^^^^^ associated item constraint not allowed here
+   |
+help: declare the type parameter right after the `impl` keyword
+   |
+LL | impl<T: Default> Foo<T> for String {}
+   |     ++++++++++++     ~
+
+error[E0229]: associated item constraints are not allowed here
+  --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:7:10
+   |
+LL | impl Foo<T: 'a + Default> for u8 {}
+   |          ^^^^^^^^^^^^^^^ associated item constraint not allowed here
+   |
+help: declare the type parameter right after the `impl` keyword
+   |
+LL | impl<'a, T: 'a + Default> Foo<T> for u8 {}
+   |     +++++++++++++++++++++     ~
+
+error[E0229]: associated item constraints are not allowed here
+  --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:13:13
+   |
+LL | impl<T> Foo<T: Default> for u16 {}
+   |             ^^^^^^^^^^ associated item constraint not allowed here
+   |
+help: declare the type parameter right after the `impl` keyword
+   |
+LL | impl<T, T: Default> Foo<T> for u16 {}
+   |       ++++++++++++      ~
+
+error[E0229]: associated item constraints are not allowed here
+  --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:17:14
+   |
+LL | impl<'a> Foo<T: 'a + Default> for u32 {}
+   |              ^^^^^^^^^^^^^^^ associated item constraint not allowed here
+   |
+help: declare the type parameter right after the `impl` keyword
+   |
+LL | impl<'a, 'a, T: 'a + Default> Foo<T> for u32 {}
+   |        +++++++++++++++++++++      ~
+
+error[E0229]: associated item constraints are not allowed here
+  --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:23:10
+   |
+LL | impl Bar<T: Default, K: Default> for String {}
+   |          ^^^^^^^^^^ associated item constraint not allowed here
+   |
+help: declare the type parameter right after the `impl` keyword
+   |
+LL | impl<T: Default> Bar<T, K: Default> for String {}
+   |     ++++++++++++     ~
+
+error[E0107]: trait takes 2 generic arguments but 1 generic argument was supplied
+  --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:27:9
+   |
+LL | impl<T> Bar<T, K: Default> for u8 {}
+   |         ^^^ - supplied 1 generic argument
+   |         |
+   |         expected 2 generic arguments
+   |
+note: trait defined here, with 2 generic parameters: `T`, `K`
+  --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:21:7
+   |
+LL | trait Bar<T, K> {}
+   |       ^^^ -  -
+help: add missing generic argument
+   |
+LL | impl<T> Bar<T, K, K: Default> for u8 {}
+   |              +++
+
+error[E0229]: associated item constraints are not allowed here
+  --> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:27:16
+   |
+LL | impl<T> Bar<T, K: Default> for u8 {}
+   |                ^^^^^^^^^^ associated item constraint not allowed here
+   |
+help: declare the type parameter right after the `impl` keyword
+   |
+LL | impl<T, K: Default> Bar<T, K> for u8 {}
+   |       ++++++++++++         ~
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0107, E0229, E0261.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr
index 14a3d5e178d..31d74d1c022 100644
--- a/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr
@@ -1,8 +1,8 @@
-error[E0284]: type annotations needed: cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc <: <T as Trait<'_>>::Assoc`
+error[E0284]: type annotations needed: cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to <T as Trait<'_>>::Assoc`
   --> $DIR/rigid-equate-projections-in-higher-ranked-fn-signature.rs:27:50
    |
 LL |     let _: for<'a> fn(<_ as Trait<'a>>::Assoc) = foo::<T>();
-   |                                                  ^^^^^^^^^^ cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc <: <T as Trait<'_>>::Assoc`
+   |                                                  ^^^^^^^^^^ cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to <T as Trait<'_>>::Assoc`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr
index 78e6376bca2..cc229764ad3 100644
--- a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr
+++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr
@@ -24,8 +24,7 @@ LL |         fn f() { my_core::mem::drop(0); }
 LL | a!();
    | ---- in this macro invocation
    |
-   = help: consider importing one of these items:
-           core::mem
+   = help: consider importing this module:
            std::mem
    = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -35,9 +34,7 @@ error[E0433]: failed to resolve: use of undeclared crate or module `my_core`
 LL |     fn f() { my_core::mem::drop(0); }
    |              ^^^^^^^ use of undeclared crate or module `my_core`
    |
-help: consider importing one of these items
-   |
-LL +     use core::mem;
+help: consider importing this module
    |
 LL +     use std::mem;
    |
diff --git a/tests/ui/impl-trait/associated-type-undefine.rs b/tests/ui/impl-trait/associated-type-undefine.rs
new file mode 100644
index 00000000000..c8f07021fbf
--- /dev/null
+++ b/tests/ui/impl-trait/associated-type-undefine.rs
@@ -0,0 +1,28 @@
+#![feature(impl_trait_in_assoc_type)]
+
+trait Foo: Sized {
+    type Bar;
+    type Gat<T: Foo>;
+    fn foo(self) -> (<Self as Foo>::Gat<u32>, <Self as Foo>::Gat<Self>);
+}
+
+impl Foo for u32 {
+    type Bar = ();
+    type Gat<T: Foo> = ();
+    fn foo(self) -> (<Self as Foo>::Gat<u32>, <Self as Foo>::Gat<Self>) {
+        ((), ())
+    }
+}
+
+impl Foo for () {
+    type Bar = impl Sized;
+    type Gat<T: Foo> = <T as Foo>::Bar;
+    // Because we encounter `Gat<u32>` first, we never walk into another `Gat`
+    // again, thus missing the opaque type that we could be defining.
+    fn foo(self) -> (<Self as Foo>::Gat<u32>, <Self as Foo>::Gat<Self>) {
+        ((), ())
+        //~^ ERROR: mismatched types
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/associated-type-undefine.stderr b/tests/ui/impl-trait/associated-type-undefine.stderr
new file mode 100644
index 00000000000..5d9d525eb93
--- /dev/null
+++ b/tests/ui/impl-trait/associated-type-undefine.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/associated-type-undefine.rs:23:14
+   |
+LL |     type Bar = impl Sized;
+   |                ---------- the expected opaque type
+...
+LL |         ((), ())
+   |              ^^ expected opaque type, found `()`
+   |
+   = note: expected opaque type `<() as Foo>::Bar`
+                found unit type `()`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/associated-type-undefine.rs:22:8
+   |
+LL |     fn foo(self) -> (<Self as Foo>::Gat<u32>, <Self as Foo>::Gat<Self>) {
+   |        ^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/call_method_ambiguous.next.stderr b/tests/ui/impl-trait/call_method_ambiguous.next.stderr
new file mode 100644
index 00000000000..cd222aa7ae9
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_ambiguous.next.stderr
@@ -0,0 +1,17 @@
+error[E0282]: type annotations needed
+  --> $DIR/call_method_ambiguous.rs:29:13
+   |
+LL |         let mut iter = foo(n - 1, m);
+   |             ^^^^^^^^
+LL |
+LL |         assert_eq!(iter.get(), 1);
+   |                    ---- type must be known at this point
+   |
+help: consider giving `iter` an explicit type
+   |
+LL |         let mut iter: /* Type */ = foo(n - 1, m);
+   |                     ++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_ambiguous.rs b/tests/ui/impl-trait/call_method_ambiguous.rs
new file mode 100644
index 00000000000..c26c01e002d
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_ambiguous.rs
@@ -0,0 +1,39 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[current] run-pass
+
+#![feature(precise_capturing)]
+#![allow(incomplete_features)]
+
+trait Get {
+    fn get(&mut self) -> u32;
+}
+
+impl Get for () {
+    fn get(&mut self) -> u32 {
+        0
+    }
+}
+
+impl<T> Get for &mut T
+where
+    T: Get,
+{
+    fn get(&mut self) -> u32 {
+        T::get(self) + 1
+    }
+}
+
+fn foo(n: usize, m: &mut ()) -> impl use<'_> Get {
+    if n > 0 {
+        let mut iter = foo(n - 1, m);
+        //[next]~^ type annotations needed
+        assert_eq!(iter.get(), 1);
+    }
+    m
+}
+
+fn main() {
+    let g = foo(1, &mut ()).get();
+    assert_eq!(g, 1);
+}
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr
new file mode 100644
index 00000000000..271051f120a
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr
@@ -0,0 +1,17 @@
+error[E0282]: type annotations needed
+  --> $DIR/call_method_on_inherent_impl.rs:18:13
+   |
+LL |         let x = my_foo();
+   |             ^
+LL |
+LL |         x.my_debug();
+   |         - type must be known at this point
+   |
+help: consider giving `x` an explicit type
+   |
+LL |         let x: /* Type */ = my_foo();
+   |              ++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl.rs b/tests/ui/impl-trait/call_method_on_inherent_impl.rs
new file mode 100644
index 00000000000..17f7cad660d
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl.rs
@@ -0,0 +1,25 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[current] check-pass
+
+trait MyDebug {
+    fn my_debug(&self);
+}
+
+impl<T> MyDebug for T
+where
+    T: std::fmt::Debug,
+{
+    fn my_debug(&self) {}
+}
+
+fn my_foo() -> impl std::fmt::Debug {
+    if false {
+        let x = my_foo();
+        //[next]~^ type annotations needed
+        x.my_debug();
+    }
+    ()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr
new file mode 100644
index 00000000000..6ecb2b05fc5
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `my_debug` found for reference `&impl Debug` in the current scope
+  --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:16:11
+   |
+LL |         x.my_debug();
+   |           ^^^^^^^^ method not found in `&impl Debug`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it
+  --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:4:1
+   |
+LL | trait MyDebug {
+   | ^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr
new file mode 100644
index 00000000000..5fb0b8f1d14
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr
@@ -0,0 +1,17 @@
+error[E0282]: type annotations needed for `&_`
+  --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:14:13
+   |
+LL |         let x = &my_foo();
+   |             ^
+LL |
+LL |         x.my_debug();
+   |           -------- type must be known at this point
+   |
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
+   |
+LL |         let x: &_ = &my_foo();
+   |              ++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs
new file mode 100644
index 00000000000..7fb2ff3b2bc
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs
@@ -0,0 +1,22 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+trait MyDebug {
+    fn my_debug(&self);
+}
+
+impl MyDebug for &() {
+    fn my_debug(&self) {}
+}
+
+fn my_foo() -> impl std::fmt::Debug {
+    if false {
+        let x = &my_foo();
+        //[next]~^ ERROR: type annotations needed
+        x.my_debug();
+        //[current]~^ ERROR: no method named `my_debug`
+    }
+    ()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr
new file mode 100644
index 00000000000..fe6e166cb4f
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.current.stderr
@@ -0,0 +1,40 @@
+error[E0599]: no method named `my_debug` found for opaque type `impl Debug` in the current scope
+  --> $DIR/call_method_on_inherent_impl_ref.rs:20:11
+   |
+LL |     fn my_debug(&self);
+   |        -------- the method is available for `&impl Debug` here
+...
+LL |         x.my_debug();
+   |           ^^^^^^^^ method not found in `impl Debug`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it
+  --> $DIR/call_method_on_inherent_impl_ref.rs:4:1
+   |
+LL | trait MyDebug {
+   | ^^^^^^^^^^^^^
+
+error[E0391]: cycle detected when computing type of opaque `my_foo::{opaque#0}`
+  --> $DIR/call_method_on_inherent_impl_ref.rs:15:16
+   |
+LL | fn my_foo() -> impl std::fmt::Debug {
+   |                ^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires type-checking `my_foo`...
+  --> $DIR/call_method_on_inherent_impl_ref.rs:20:9
+   |
+LL |         x.my_debug();
+   |         ^
+   = note: ...which requires evaluating trait selection obligation `my_foo::{opaque#0}: core::marker::Unpin`...
+   = note: ...which again requires computing type of opaque `my_foo::{opaque#0}`, completing the cycle
+note: cycle used when computing type of `my_foo::{opaque#0}`
+  --> $DIR/call_method_on_inherent_impl_ref.rs:15:16
+   |
+LL | fn my_foo() -> impl std::fmt::Debug {
+   |                ^^^^^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0391, E0599.
+For more information about an error, try `rustc --explain E0391`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr
new file mode 100644
index 00000000000..327f6ca3450
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr
@@ -0,0 +1,31 @@
+error[E0282]: type annotations needed
+  --> $DIR/call_method_on_inherent_impl_ref.rs:18:13
+   |
+LL |         let x = my_foo();
+   |             ^
+LL |
+LL |         x.my_debug();
+   |         - type must be known at this point
+   |
+help: consider giving `x` an explicit type
+   |
+LL |         let x: /* Type */ = my_foo();
+   |              ++++++++++++
+
+error[E0282]: type annotations needed for `&_`
+  --> $DIR/call_method_on_inherent_impl_ref.rs:28:13
+   |
+LL |         let x = &my_bar();
+   |             ^
+LL |
+LL |         x.my_debug();
+   |           -------- type must be known at this point
+   |
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
+   |
+LL |         let x: &_ = &my_bar();
+   |              ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs
new file mode 100644
index 00000000000..40ad21532a4
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs
@@ -0,0 +1,35 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+trait MyDebug {
+    fn my_debug(&self);
+}
+
+impl<T> MyDebug for &T
+where
+    T: std::fmt::Debug,
+{
+    fn my_debug(&self) {}
+}
+
+fn my_foo() -> impl std::fmt::Debug {
+    //[current]~^ cycle
+    if false {
+        let x = my_foo();
+        //[next]~^ type annotations needed
+        x.my_debug();
+        //[current]~^ no method named `my_debug` found
+    }
+    ()
+}
+
+fn my_bar() -> impl std::fmt::Debug {
+    if false {
+        let x = &my_bar();
+        //[next]~^ type annotations needed
+        x.my_debug();
+    }
+    ()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/call_method_without_import.no_import.stderr b/tests/ui/impl-trait/call_method_without_import.no_import.stderr
new file mode 100644
index 00000000000..72982b695bb
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_without_import.no_import.stderr
@@ -0,0 +1,37 @@
+error[E0599]: no method named `fmt` found for opaque type `impl Debug` in the current scope
+  --> $DIR/call_method_without_import.rs:17:11
+   |
+LL |         x.fmt(f);
+   |           ^^^ method not found in `impl Debug`
+  --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+   |
+   = note: the method is available for `impl Debug` here
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: trait `Debug` which provides `fmt` is implemented but not in scope; perhaps you want to import it
+   |
+LL + use std::fmt::Debug;
+   |
+
+error[E0599]: no method named `fmt` found for mutable reference `&mut impl Debug` in the current scope
+  --> $DIR/call_method_without_import.rs:26:11
+   |
+LL |         x.fmt(f);
+   |           ^^^ method not found in `&mut impl Debug`
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following traits which provide `fmt` are implemented but not in scope; perhaps you want to import one of them
+   |
+LL + use std::fmt::Binary;
+   |
+LL + use std::fmt::Debug;
+   |
+LL + use std::fmt::Display;
+   |
+LL + use std::fmt::LowerExp;
+   |
+     and 5 other candidates
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/impl-trait/call_method_without_import.rs b/tests/ui/impl-trait/call_method_without_import.rs
new file mode 100644
index 00000000000..d62777ea283
--- /dev/null
+++ b/tests/ui/impl-trait/call_method_without_import.rs
@@ -0,0 +1,42 @@
+//! Test that opaque types only pick up methods from traits in their bounds
+//! if the trait is imported.
+//!
+//! FIXME: always look through the bounds of an opaque type to see if there are
+//! methods that could be called on any of the bound traits, irrespective of
+//! imported traits.
+
+//@ revisions: import no_import
+//@[import] check-pass
+
+#[cfg(import)]
+use std::fmt::Debug as _;
+
+fn foo(f: &mut std::fmt::Formatter<'_>) -> impl std::fmt::Debug {
+    if false {
+        let x = foo(f);
+        x.fmt(f);
+        //[no_import]~^ ERROR: no method named `fmt` found
+    }
+    ()
+}
+
+fn foo1(f: &mut std::fmt::Formatter<'_>) -> impl std::fmt::Debug {
+    if false {
+        let x = &mut foo(f);
+        x.fmt(f);
+        //[no_import]~^ ERROR: no method named `fmt` found
+    }
+    ()
+}
+
+// inconsistent with this
+fn bar<T>(t: impl std::fmt::Debug, f: &mut std::fmt::Formatter<'_>) {
+    t.fmt(f);
+}
+
+// and the desugared version, of course
+fn baz<T: std::fmt::Debug>(t: T, f: &mut std::fmt::Formatter<'_>) {
+    t.fmt(f);
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/method-resolution.rs b/tests/ui/impl-trait/method-resolution.rs
new file mode 100644
index 00000000000..60fbacd8646
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution.rs
@@ -0,0 +1,26 @@
+//! Since there is only one possible `bar` method, we invoke it and subsequently
+//! constrain `foo`'s RPIT to `u32`.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+trait Trait {}
+
+impl Trait for u32 {}
+
+struct Bar<T>(T);
+
+impl Bar<u32> {
+    fn bar(self) {}
+}
+
+fn foo(x: bool) -> Bar<impl Sized> {
+    if x {
+        let x = foo(false);
+        x.bar();
+    }
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/method-resolution2.next.stderr b/tests/ui/impl-trait/method-resolution2.next.stderr
new file mode 100644
index 00000000000..223430e1658
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution2.next.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-resolution2.rs:25:11
+   |
+LL |         x.bar();
+   |           ^^^ multiple `bar` found
+   |
+note: candidate #1 is defined in an impl for the type `Bar<T>`
+  --> $DIR/method-resolution2.rs:19:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Bar<u32>`
+  --> $DIR/method-resolution2.rs:15:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/impl-trait/method-resolution2.rs b/tests/ui/impl-trait/method-resolution2.rs
new file mode 100644
index 00000000000..88d4f3d9896
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution2.rs
@@ -0,0 +1,31 @@
+//! Check that the method call does not constrain the RPIT to `i32`, even though
+//! `i32` is the only type that satisfies the RPIT's trait bounds.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[current] check-pass
+
+trait Trait {}
+
+impl Trait for i32 {}
+
+struct Bar<T>(T);
+
+impl Bar<u32> {
+    fn bar(self) {}
+}
+
+impl<T: Trait> Bar<T> {
+    fn bar(self) {}
+}
+
+fn foo(x: bool) -> Bar<impl Trait> {
+    if x {
+        let x = foo(false);
+        x.bar();
+        //[next]~^ ERROR: multiple applicable items in scope
+    }
+    Bar(42_i32)
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/method-resolution3.current.stderr b/tests/ui/impl-trait/method-resolution3.current.stderr
new file mode 100644
index 00000000000..87dd862ef8f
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution3.current.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-resolution3.rs:21:11
+   |
+LL |         x.bar();
+   |           ^^^ multiple `bar` found
+   |
+note: candidate #1 is defined in an impl for the type `Bar<i32>`
+  --> $DIR/method-resolution3.rs:15:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Bar<u32>`
+  --> $DIR/method-resolution3.rs:11:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/impl-trait/method-resolution3.next.stderr b/tests/ui/impl-trait/method-resolution3.next.stderr
new file mode 100644
index 00000000000..87dd862ef8f
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution3.next.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-resolution3.rs:21:11
+   |
+LL |         x.bar();
+   |           ^^^ multiple `bar` found
+   |
+note: candidate #1 is defined in an impl for the type `Bar<i32>`
+  --> $DIR/method-resolution3.rs:15:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Bar<u32>`
+  --> $DIR/method-resolution3.rs:11:5
+   |
+LL |     fn bar(self) {}
+   |     ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/impl-trait/method-resolution3.rs b/tests/ui/impl-trait/method-resolution3.rs
new file mode 100644
index 00000000000..8c47ef4fc75
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution3.rs
@@ -0,0 +1,27 @@
+//! Check that we consider `Bar<impl Sized>` to successfully unify
+//! with both `Bar<u32>` and `Bar<i32>` (in isolation), so we bail
+//! out with ambiguity.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+struct Bar<T>(T);
+
+impl Bar<u32> {
+    fn bar(self) {}
+}
+
+impl Bar<i32> {
+    fn bar(self) {}
+}
+
+fn foo(x: bool) -> Bar<impl Sized> {
+    if x {
+        let x = foo(false);
+        x.bar();
+        //~^ ERROR: multiple applicable items in scope
+    }
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/method-resolution4.next.stderr b/tests/ui/impl-trait/method-resolution4.next.stderr
new file mode 100644
index 00000000000..b48de0af357
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution4.next.stderr
@@ -0,0 +1,22 @@
+error[E0282]: type annotations needed
+  --> $DIR/method-resolution4.rs:13:9
+   |
+LL |         foo(false).next().unwrap();
+   |         ^^^^^^^^^^ cannot infer type
+
+error[E0308]: mismatched types
+  --> $DIR/method-resolution4.rs:16:5
+   |
+LL | fn foo(b: bool) -> impl Iterator<Item = ()> {
+   |                    ------------------------ the expected opaque type
+...
+LL |     std::iter::empty()
+   |     ^^^^^^^^^^^^^^^^^^ types differ
+   |
+   = note: expected opaque type `impl Iterator<Item = ()>`
+                   found struct `std::iter::Empty<_>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0282, E0308.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/method-resolution4.rs b/tests/ui/impl-trait/method-resolution4.rs
new file mode 100644
index 00000000000..91884eb59fd
--- /dev/null
+++ b/tests/ui/impl-trait/method-resolution4.rs
@@ -0,0 +1,20 @@
+//! The recursive method call yields the opaque type. The
+//! `next` method call then constrains the hidden type to `&mut _`
+//! because `next` takes `&mut self`. We never resolve the inference
+//! variable, but get a type mismatch when comparing `&mut _` with
+//! `std::iter::Empty`.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[current] check-pass
+
+fn foo(b: bool) -> impl Iterator<Item = ()> {
+    if b {
+        foo(false).next().unwrap();
+        //[next]~^ type annotations needed
+    }
+    std::iter::empty()
+    //[next]~^ mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr
index 1f9a2a5e9d6..a53312e5c0b 100644
--- a/tests/ui/impl-trait/nested_impl_trait.stderr
+++ b/tests/ui/impl-trait/nested_impl_trait.stderr
@@ -46,7 +46,7 @@ error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfie
   --> $DIR/nested_impl_trait.rs:6:46
    |
 LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
-   |                                              ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
+   |                                              ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`, which is required by `impl Into<u32>: Into<impl Debug>`
    |
    = help: the trait `Into<U>` is implemented for `T`
    = note: required for `impl Into<u32>` to implement `Into<impl Debug>`
@@ -55,7 +55,7 @@ error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfie
   --> $DIR/nested_impl_trait.rs:19:34
    |
 LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
-   |                                  ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
+   |                                  ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`, which is required by `impl Into<u32>: Into<impl Debug>`
    |
    = help: the trait `Into<U>` is implemented for `T`
    = note: required for `impl Into<u32>` to implement `Into<impl Debug>`
diff --git a/tests/ui/impl-trait/recursive-parent-trait-method-call.rs b/tests/ui/impl-trait/recursive-parent-trait-method-call.rs
new file mode 100644
index 00000000000..4da9a06a465
--- /dev/null
+++ b/tests/ui/impl-trait/recursive-parent-trait-method-call.rs
@@ -0,0 +1,42 @@
+//! This test checks that we can resolve the `boxed` method call to `FutureExt`,
+//! because we know that the anonymous future does not implement `StreamExt`.
+
+//@ edition: 2021
+//@ check-pass
+
+use std::future::Future;
+use std::pin::Pin;
+
+trait FutureExt: Future + Sized + Send + 'static {
+    fn boxed(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'static>> {
+        Box::pin(self)
+    }
+}
+
+trait StreamExt: Future + Sized + Send + 'static {
+    fn boxed(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'static>> {
+        Box::pin(self)
+    }
+}
+
+impl<T: Future + Sized + Send + 'static> FutureExt for T {}
+
+fn go(i: usize) -> impl Future<Output = ()> + Send + 'static {
+    async move {
+        if i != 0 {
+            spawn(async move {
+                let fut = go(i - 1).boxed();
+                fut.await;
+            })
+            .await;
+        }
+    }
+}
+
+pub fn spawn<T: Send>(
+    _: impl Future<Output = T> + Send + 'static,
+) -> impl Future<Output = ()> + Send + 'static {
+    async move { todo!() }
+}
+
+fn main() {}
diff --git a/tests/ui/imports/cycle-import-in-std-1.stderr b/tests/ui/imports/cycle-import-in-std-1.stderr
index d4e6f32cc10..a7dfc6231ba 100644
--- a/tests/ui/imports/cycle-import-in-std-1.stderr
+++ b/tests/ui/imports/cycle-import-in-std-1.stderr
@@ -4,8 +4,7 @@ error[E0432]: unresolved import `ops`
 LL | use ops::{self as std};
    |           ^^^^^^^^^^^ no external crate `ops`
    |
-   = help: consider importing one of these items instead:
-           core::ops
+   = help: consider importing this module instead:
            std::ops
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/imports/cycle-import-in-std-2.stderr b/tests/ui/imports/cycle-import-in-std-2.stderr
index dc0270dffe4..8d94693cd51 100644
--- a/tests/ui/imports/cycle-import-in-std-2.stderr
+++ b/tests/ui/imports/cycle-import-in-std-2.stderr
@@ -4,8 +4,7 @@ error[E0432]: unresolved import `ops`
 LL | use ops::{self as std};
    |           ^^^^^^^^^^^ no external crate `ops`
    |
-   = help: consider importing one of these items instead:
-           core::ops
+   = help: consider importing this module instead:
            std::ops
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/imports/import-alias-issue-121168.edition2018.stderr b/tests/ui/imports/import-alias-issue-121168.edition2018.stderr
index b61a0e3edd5..e14e700c33d 100644
--- a/tests/ui/imports/import-alias-issue-121168.edition2018.stderr
+++ b/tests/ui/imports/import-alias-issue-121168.edition2018.stderr
@@ -4,7 +4,7 @@ error[E0412]: cannot find type `Foo` in this scope
 LL |     let _: Foo<i32> = todo!();
    |            ^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing one of these structs
    |
 LL + use crate::nice_crate_name::Foo;
    |
diff --git a/tests/ui/imports/import-alias-issue-121168.edition2021.stderr b/tests/ui/imports/import-alias-issue-121168.edition2021.stderr
index b61a0e3edd5..e14e700c33d 100644
--- a/tests/ui/imports/import-alias-issue-121168.edition2021.stderr
+++ b/tests/ui/imports/import-alias-issue-121168.edition2021.stderr
@@ -4,7 +4,7 @@ error[E0412]: cannot find type `Foo` in this scope
 LL |     let _: Foo<i32> = todo!();
    |            ^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing one of these structs
    |
 LL + use crate::nice_crate_name::Foo;
    |
diff --git a/tests/ui/imports/issue-56125.stderr b/tests/ui/imports/issue-56125.stderr
index d2a0f436c42..0c4a569c7ea 100644
--- a/tests/ui/imports/issue-56125.stderr
+++ b/tests/ui/imports/issue-56125.stderr
@@ -4,16 +4,16 @@ error[E0432]: unresolved import `empty::issue_56125`
 LL |     use empty::issue_56125;
    |         ^^^^^^^^^^^^^^^^^^ no `issue_56125` in `m3::empty`
    |
-help: consider importing one of these items instead
+help: consider importing one of these modules instead
    |
+LL |     use crate::m3::last_segment::issue_56125;
+   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     use crate::m3::non_last_segment::non_last_segment::issue_56125;
+   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 LL |     use ::issue_56125::issue_56125;
    |         ~~~~~~~~~~~~~~~~~~~~~~~~~~
 LL |     use ::issue_56125::last_segment::issue_56125;
    |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LL |     use ::issue_56125::non_last_segment::non_last_segment::issue_56125;
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LL |     use crate::m3::last_segment::issue_56125;
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      and 1 other candidate
 
 error[E0659]: `issue_56125` is ambiguous
diff --git a/tests/ui/instrument-coverage/coverage-options.rs b/tests/ui/instrument-coverage/coverage-options.rs
index 8f523a5fd11..7615a0fb275 100644
--- a/tests/ui/instrument-coverage/coverage-options.rs
+++ b/tests/ui/instrument-coverage/coverage-options.rs
@@ -1,6 +1,5 @@
-//@ needs-profiler-support
 //@ revisions: block branch condition mcdc bad
-//@ compile-flags -Cinstrument-coverage
+//@ compile-flags -Cinstrument-coverage -Zno-profiler-runtime
 
 //@ [block] check-pass
 //@ [block] compile-flags: -Zcoverage-options=block
diff --git a/tests/ui/instrument-coverage/on-values.rs b/tests/ui/instrument-coverage/on-values.rs
index a6793b2c304..53b149fd39c 100644
--- a/tests/ui/instrument-coverage/on-values.rs
+++ b/tests/ui/instrument-coverage/on-values.rs
@@ -1,5 +1,5 @@
 //@ check-pass
-//@ needs-profiler-support
+//@ compile-flags: -Zno-profiler-runtime
 //@ revisions: default y yes on true_ all
 //@ [default] compile-flags: -Cinstrument-coverage
 //@ [y] compile-flags: -Cinstrument-coverage=y
diff --git a/tests/ui/kindck/kindck-send-object.stderr b/tests/ui/kindck/kindck-send-object.stderr
index 9f1ff4f3644..7d0c711abc4 100644
--- a/tests/ui/kindck/kindck-send-object.stderr
+++ b/tests/ui/kindck/kindck-send-object.stderr
@@ -4,7 +4,7 @@ error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads sa
 LL |     assert_send::<&'static (dyn Dummy + 'static)>();
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
    |
-   = help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
+   = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
    = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object.rs:5:18
diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr
index f2aa814676f..7f39dab2086 100644
--- a/tests/ui/kindck/kindck-send-object1.stderr
+++ b/tests/ui/kindck/kindck-send-object1.stderr
@@ -4,7 +4,7 @@ error[E0277]: `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
 LL |     assert_send::<&'a dyn Dummy>();
    |                   ^^^^^^^^^^^^^ `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
    |
-   = help: the trait `Sync` is not implemented for `&'a (dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send`
+   = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send`
    = note: required for `&'a (dyn Dummy + 'a)` to implement `Send`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object1.rs:5:18
diff --git a/tests/ui/kindck/kindck-send-object2.stderr b/tests/ui/kindck/kindck-send-object2.stderr
index cd4d74360f8..a481a132cce 100644
--- a/tests/ui/kindck/kindck-send-object2.stderr
+++ b/tests/ui/kindck/kindck-send-object2.stderr
@@ -4,7 +4,7 @@ error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads sa
 LL |     assert_send::<&'static dyn Dummy>();
    |                   ^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
    |
-   = help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
+   = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
    = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object2.rs:3:18
diff --git a/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs b/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs
new file mode 100644
index 00000000000..8cd1524045b
--- /dev/null
+++ b/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs
@@ -0,0 +1,33 @@
+//@ check-pass
+
+mod ffi {
+    use super::*;
+
+    extern "C" {
+        pub fn DomPromise_AddRef(promise: *const Promise);
+        pub fn DomPromise_Release(promise: *const Promise);
+    }
+}
+
+#[repr(C)]
+#[allow(unused)]
+pub struct Promise {
+    private: [u8; 0],
+    __nosync: ::std::marker::PhantomData<::std::rc::Rc<u8>>,
+}
+
+pub unsafe trait RefCounted {
+    unsafe fn addref(&self);
+    unsafe fn release(&self);
+}
+
+unsafe impl RefCounted for Promise {
+    unsafe fn addref(&self) {
+        ffi::DomPromise_AddRef(self)
+    }
+    unsafe fn release(&self) {
+        ffi::DomPromise_Release(self)
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs
new file mode 100644
index 00000000000..bf2fc243e81
--- /dev/null
+++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs
@@ -0,0 +1,52 @@
+#![deny(dead_code)]
+
+struct T1; //~ ERROR struct `T1` is never constructed
+pub struct T2(i32); //~ ERROR struct `T2` is never constructed
+struct T3;
+
+trait Trait1 { //~ ERROR trait `Trait1` is never used
+    const UNUSED: i32;
+    fn unused(&self) {}
+    fn construct_self() -> Self;
+}
+
+pub trait Trait2 {
+    const USED: i32;
+    fn used(&self) {}
+}
+
+pub trait Trait3 {
+    const USED: i32;
+    fn construct_self() -> Self;
+}
+
+impl Trait1 for T1 {
+    const UNUSED: i32 = 0;
+    fn construct_self() -> Self {
+        Self
+    }
+}
+
+impl Trait1 for T2 {
+    const UNUSED: i32 = 0;
+    fn construct_self() -> Self {
+        T2(0)
+    }
+}
+
+impl Trait2 for T1 {
+    const USED: i32 = 0;
+}
+
+impl Trait2 for T2 {
+    const USED: i32 = 0;
+}
+
+impl Trait3 for T3 {
+    const USED: i32 = 0;
+    fn construct_self() -> Self {
+        Self
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr
new file mode 100644
index 00000000000..174096d9398
--- /dev/null
+++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr
@@ -0,0 +1,26 @@
+error: struct `T1` is never constructed
+  --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:3:8
+   |
+LL | struct T1;
+   |        ^^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: struct `T2` is never constructed
+  --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:12
+   |
+LL | pub struct T2(i32);
+   |            ^^
+
+error: trait `Trait1` is never used
+  --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:7:7
+   |
+LL | trait Trait1 {
+   |       ^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/lint/non-local-defs/cargo-update.stderr b/tests/ui/lint/non-local-defs/cargo-update.stderr
index 888fd2e6183..afd37d03a23 100644
--- a/tests/ui/lint/non-local-defs/cargo-update.stderr
+++ b/tests/ui/lint/non-local-defs/cargo-update.stderr
@@ -8,9 +8,10 @@ LL | non_local_macro::non_local_impl!(LocalStruct);
    | `Debug` is not local
    | move the `impl` block outside of this constant `_IMPL_DEBUG`
    |
+   = note: the macro `non_local_macro::non_local_impl` defines the non-local `impl`, and may need to be changed
+   = note: the macro `non_local_macro::non_local_impl` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro`
    = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type
    = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`
-   = note: the macro `non_local_macro::non_local_impl` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro`
    = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
    = note: `#[warn(non_local_definitions)]` on by default
diff --git a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr
index b52301d1aa0..fa9ba2cb785 100644
--- a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr
+++ b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr
@@ -12,6 +12,7 @@ LL |             impl MacroTrait for OutsideStruct {}
 LL | m!();
    | ---- in this macro invocation
    |
+   = note: the macro `m` defines the non-local `impl`, and may need to be changed
    = note: `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type
    = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
diff --git a/tests/ui/lint/issue-89469.rs b/tests/ui/lint/non-snake-case/allow-snake-case-field-destructuring-issue-89469.rs
index f691d6b5a92..f691d6b5a92 100644
--- a/tests/ui/lint/issue-89469.rs
+++ b/tests/ui/lint/non-snake-case/allow-snake-case-field-destructuring-issue-89469.rs
diff --git a/tests/ui/lint/lint-non-snake-case-crate-bin.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin.rs
index f8aad88ecee..f8aad88ecee 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-bin.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin.rs
diff --git a/tests/ui/lint/lint-non-snake-case-crate-bin2.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin2.rs
index c077d81e9e5..c077d81e9e5 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-bin2.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin2.rs
diff --git a/tests/ui/lint/lint-non-snake-case-crate-bin3.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin3.rs
index 278f7cfd3ee..278f7cfd3ee 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-bin3.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin3.rs
diff --git a/tests/ui/lint/lint-non-snake-case-crate-cdylib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.rs
index 781c6794fc2..781c6794fc2 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-cdylib.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.rs
diff --git a/tests/ui/lint/lint-non-snake-case-crate-cdylib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.stderr
index f9167aa8df3..f9167aa8df3 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-cdylib.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.stderr
diff --git a/tests/ui/lint/lint-non-snake-case-crate-dylib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.rs
index 3f65295f068..3f65295f068 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-dylib.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.rs
diff --git a/tests/ui/lint/lint-non-snake-case-crate-dylib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.stderr
index 4ee1a9cb3dd..4ee1a9cb3dd 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-dylib.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.stderr
diff --git a/tests/ui/lint/lint-non-snake-case-crate-lib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.rs
index 20c58e66aa6..20c58e66aa6 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-lib.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.rs
diff --git a/tests/ui/lint/lint-non-snake-case-crate-lib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.stderr
index a68c0e832b8..a68c0e832b8 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-lib.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.stderr
diff --git a/tests/ui/lint/lint-non-snake-case-crate-proc-macro.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.rs
index f0f2fa4393e..f0f2fa4393e 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-proc-macro.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.rs
diff --git a/tests/ui/lint/lint-non-snake-case-crate-proc-macro.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.stderr
index e0091057bc9..e0091057bc9 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-proc-macro.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.stderr
diff --git a/tests/ui/lint/lint-non-snake-case-crate-rlib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.rs
index 1a558def3d0..1a558def3d0 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-rlib.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.rs
diff --git a/tests/ui/lint/lint-non-snake-case-crate-rlib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.stderr
index 6e9d54bd5bc..6e9d54bd5bc 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-rlib.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.stderr
diff --git a/tests/ui/lint/lint-non-snake-case-crate-staticlib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.rs
index 2ec53c15eb8..2ec53c15eb8 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-staticlib.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.rs
diff --git a/tests/ui/lint/lint-non-snake-case-crate-staticlib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.stderr
index 4ee6d5bd4d4..4ee6d5bd4d4 100644
--- a/tests/ui/lint/lint-non-snake-case-crate-staticlib.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.stderr
diff --git a/tests/ui/lint/lint-non-snake-case-functions.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-functions.rs
index fa64a9f980e..fa64a9f980e 100644
--- a/tests/ui/lint/lint-non-snake-case-functions.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-functions.rs
diff --git a/tests/ui/lint/lint-non-snake-case-functions.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-functions.stderr
index f6ac6b99b60..f6ac6b99b60 100644
--- a/tests/ui/lint/lint-non-snake-case-functions.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-functions.stderr
diff --git a/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-identifiers-suggestion-reserved.rs
index 8cc4f976a4b..8cc4f976a4b 100644
--- a/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-identifiers-suggestion-reserved.rs
diff --git a/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-identifiers-suggestion-reserved.stderr
index 2841815ecf2..2841815ecf2 100644
--- a/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-identifiers-suggestion-reserved.stderr
diff --git a/tests/ui/lint/lint-non-snake-case-lifetimes.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-lifetimes.rs
index de76d2dbef2..de76d2dbef2 100644
--- a/tests/ui/lint/lint-non-snake-case-lifetimes.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-lifetimes.rs
diff --git a/tests/ui/lint/lint-non-snake-case-lifetimes.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-lifetimes.stderr
index 8be7365cfc3..8be7365cfc3 100644
--- a/tests/ui/lint/lint-non-snake-case-lifetimes.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-lifetimes.stderr
diff --git a/tests/ui/lint/lint-non-snake-case-modules.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-modules.rs
index 73f12332172..73f12332172 100644
--- a/tests/ui/lint/lint-non-snake-case-modules.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-modules.rs
diff --git a/tests/ui/lint/lint-non-snake-case-modules.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-modules.stderr
index f21f9a934f3..f21f9a934f3 100644
--- a/tests/ui/lint/lint-non-snake-case-modules.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-modules.stderr
diff --git a/tests/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-no-lowercase-equivalent.rs
index a43d2974ff3..a43d2974ff3 100644
--- a/tests/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-no-lowercase-equivalent.rs
diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-2.rs b/tests/ui/lint/non-snake-case/lint-nonstandard-style-unicode-2.rs
index 9690be5908b..9690be5908b 100644
--- a/tests/ui/lint/lint-nonstandard-style-unicode-2.rs
+++ b/tests/ui/lint/non-snake-case/lint-nonstandard-style-unicode-2.rs
diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-2.stderr b/tests/ui/lint/non-snake-case/lint-nonstandard-style-unicode-2.stderr
index 8eb0654e0a1..8eb0654e0a1 100644
--- a/tests/ui/lint/lint-nonstandard-style-unicode-2.stderr
+++ b/tests/ui/lint/non-snake-case/lint-nonstandard-style-unicode-2.stderr
diff --git a/tests/ui/lint/lint-uppercase-variables.rs b/tests/ui/lint/non-snake-case/lint-uppercase-variables.rs
index 59dba536f24..59dba536f24 100644
--- a/tests/ui/lint/lint-uppercase-variables.rs
+++ b/tests/ui/lint/non-snake-case/lint-uppercase-variables.rs
diff --git a/tests/ui/lint/lint-uppercase-variables.stderr b/tests/ui/lint/non-snake-case/lint-uppercase-variables.stderr
index 9220828014f..9220828014f 100644
--- a/tests/ui/lint/lint-uppercase-variables.stderr
+++ b/tests/ui/lint/non-snake-case/lint-uppercase-variables.stderr
diff --git a/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs b/tests/ui/lint/non-snake-case/no-snake-case-warning-for-field-puns-issue-66362.rs
index c2b81959f2c..c2b81959f2c 100644
--- a/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs
+++ b/tests/ui/lint/non-snake-case/no-snake-case-warning-for-field-puns-issue-66362.rs
diff --git a/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr b/tests/ui/lint/non-snake-case/no-snake-case-warning-for-field-puns-issue-66362.stderr
index 09dc3640f99..cbbcf990918 100644
--- a/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr
+++ b/tests/ui/lint/non-snake-case/no-snake-case-warning-for-field-puns-issue-66362.stderr
@@ -1,29 +1,29 @@
 error: structure field `lowerCamelCaseName` should have a snake case name
-  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:7:9
+  --> $DIR/no-snake-case-warning-for-field-puns-issue-66362.rs:7:9
    |
 LL |         lowerCamelCaseName: bool,
    |         ^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_name`
    |
 note: the lint level is defined here
-  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:1:9
+  --> $DIR/no-snake-case-warning-for-field-puns-issue-66362.rs:1:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
 
 error: variable `lowerCamelCaseBinding` should have a snake case name
-  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:20:38
+  --> $DIR/no-snake-case-warning-for-field-puns-issue-66362.rs:20:38
    |
 LL |         Foo::Good { snake_case_name: lowerCamelCaseBinding } => { }
    |                                      ^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_binding`
 
 error: variable `anotherLowerCamelCaseBinding` should have a snake case name
-  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:24:41
+  --> $DIR/no-snake-case-warning-for-field-puns-issue-66362.rs:24:41
    |
 LL |     if let Foo::Good { snake_case_name: anotherLowerCamelCaseBinding } = b { }
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `another_lower_camel_case_binding`
 
 error: variable `yetAnotherLowerCamelCaseBinding` should have a snake case name
-  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:27:43
+  --> $DIR/no-snake-case-warning-for-field-puns-issue-66362.rs:27:43
    |
 LL |     if let Foo::Bad { lowerCamelCaseName: yetAnotherLowerCamelCaseBinding } = b { }
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `yet_another_lower_camel_case_binding`
diff --git a/tests/ui/lint/issue-31924-non-snake-ffi.rs b/tests/ui/lint/non-snake-case/non-snake-ffi-issue-31924.rs
index ade4e630fb2..ade4e630fb2 100644
--- a/tests/ui/lint/issue-31924-non-snake-ffi.rs
+++ b/tests/ui/lint/non-snake-case/non-snake-ffi-issue-31924.rs
diff --git a/tests/ui/lint/use_suggestion_json.stderr b/tests/ui/lint/use_suggestion_json.stderr
index acc36550642..4683e5dd8f3 100644
--- a/tests/ui/lint/use_suggestion_json.stderr
+++ b/tests/ui/lint/use_suggestion_json.stderr
@@ -95,7 +95,7 @@ mod foo {
   ],
   "children": [
     {
-      "message": "consider importing one of these items",
+      "message": "consider importing one of these structs",
       "code": null,
       "level": "help",
       "spans": [
@@ -386,7 +386,7 @@ mod foo {
 \u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m    let x: Iter;\u001b[0m
 \u001b[0m   \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m            \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mnot found in this scope\u001b[0m
 \u001b[0m   \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
-\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: consider importing one of these items\u001b[0m
+\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: consider importing one of these structs\u001b[0m
 \u001b[0m   \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
 \u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[38;5;10m+ use std::collections::binary_heap::Iter;\u001b[0m
 \u001b[0m   \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
diff --git a/tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs b/tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs
new file mode 100644
index 00000000000..e44eeffb01b
--- /dev/null
+++ b/tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs
@@ -0,0 +1,58 @@
+//@ run-pass
+
+#![allow(dead_code, non_camel_case_types, non_upper_case_globals)]
+#![feature(macro_metavar_expr_concat)]
+
+macro_rules! create_things {
+    ($lhs:ident) => {
+        struct ${concat($lhs, _separated_idents_in_a_struct)} {
+            foo: i32,
+            ${concat($lhs, _separated_idents_in_a_field)}: i32,
+        }
+
+        mod ${concat($lhs, _separated_idents_in_a_module)} {
+            pub const FOO: () = ();
+        }
+
+        fn ${concat($lhs, _separated_idents_in_a_fn)}() {}
+    };
+}
+
+macro_rules! many_idents {
+    ($a:ident, $c:ident) => {
+        const ${concat($a, B, $c, D)}: i32 = 1;
+    };
+}
+
+macro_rules! valid_tts {
+    ($_0:tt, $_1:tt) => {
+        const ${concat($_0, $_1)}: i32 = 1;
+    }
+}
+
+macro_rules! without_dollar_sign_is_an_ident {
+    ($ident:ident) => {
+        const ${concat(VAR, ident)}: i32 = 1;
+        const ${concat(VAR, $ident)}: i32 = 2;
+    };
+}
+
+fn main() {
+    create_things!(behold);
+    behold_separated_idents_in_a_fn();
+    let _ = behold_separated_idents_in_a_module::FOO;
+    let _ = behold_separated_idents_in_a_struct {
+        foo: 1,
+        behold_separated_idents_in_a_field: 2,
+    };
+
+    many_idents!(A, C);
+    assert_eq!(ABCD, 1);
+
+    valid_tts!(X, YZ);
+    assert_eq!(XYZ, 1);
+
+    without_dollar_sign_is_an_ident!(_123);
+    assert_eq!(VARident, 1);
+    assert_eq!(VAR_123, 2);
+}
diff --git a/tests/ui/macros/macro-metavar-expr-concat/hygiene.rs b/tests/ui/macros/macro-metavar-expr-concat/hygiene.rs
new file mode 100644
index 00000000000..24b0e36498a
--- /dev/null
+++ b/tests/ui/macros/macro-metavar-expr-concat/hygiene.rs
@@ -0,0 +1,13 @@
+#![feature(macro_metavar_expr_concat)]
+
+macro_rules! join {
+    ($lhs:ident, $rhs:ident) => {
+        ${concat($lhs, $rhs)}
+        //~^ ERROR cannot find value `abcdef` in this scope
+    };
+}
+
+fn main() {
+    let abcdef = 1;
+    let _another = join!(abc, def);
+}
diff --git a/tests/ui/macros/macro-metavar-expr-concat/hygiene.stderr b/tests/ui/macros/macro-metavar-expr-concat/hygiene.stderr
new file mode 100644
index 00000000000..ef2326dce85
--- /dev/null
+++ b/tests/ui/macros/macro-metavar-expr-concat/hygiene.stderr
@@ -0,0 +1,14 @@
+error[E0425]: cannot find value `abcdef` in this scope
+  --> $DIR/hygiene.rs:5:10
+   |
+LL |         ${concat($lhs, $rhs)}
+   |          ^^^^^^^^^^^^^^^^^^^^ not found in this scope
+...
+LL |     let _another = join!(abc, def);
+   |                    --------------- in this macro invocation
+   |
+   = note: this error originates in the macro `join` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.rs b/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.rs
new file mode 100644
index 00000000000..f72b9baca89
--- /dev/null
+++ b/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.rs
@@ -0,0 +1,81 @@
+#![feature(macro_metavar_expr_concat)]
+
+macro_rules! idents_01 {
+    ($rhs:ident) => {
+        let ${concat(abc, $rhs)}: () = ();
+        //~^ ERROR `${concat(..)}` currently does not support raw identifiers
+    };
+}
+
+macro_rules! idents_10 {
+    ($lhs:ident) => {
+        let ${concat($lhs, abc)}: () = ();
+        //~^ ERROR `${concat(..)}` currently does not support raw identifiers
+    };
+}
+
+macro_rules! idents_11 {
+    ($lhs:ident, $rhs:ident) => {
+        let ${concat($lhs, $rhs)}: () = ();
+        //~^ ERROR `${concat(..)}` currently does not support raw identifiers
+        //~| ERROR `${concat(..)}` currently does not support raw identifiers
+        //~| ERROR `${concat(..)}` currently does not support raw identifiers
+    };
+}
+
+macro_rules! no_params {
+    () => {
+        let ${concat(r#abc, abc)}: () = ();
+        //~^ ERROR `${concat(..)}` currently does not support raw identifiers
+        //~| ERROR expected pattern, found `$`
+
+        let ${concat(abc, r#abc)}: () = ();
+        //~^ ERROR `${concat(..)}` currently does not support raw identifiers
+
+        let ${concat(r#abc, r#abc)}: () = ();
+        //~^ ERROR `${concat(..)}` currently does not support raw identifiers
+    };
+}
+
+macro_rules! tts_01 {
+    ($rhs:tt) => {
+        let ${concat(abc, $rhs)}: () = ();
+        //~^ ERROR `${concat(..)}` currently does not support raw identifiers
+    };
+}
+
+macro_rules! tts_10 {
+    ($lhs:tt) => {
+        let ${concat($lhs, abc)}: () = ();
+        //~^ ERROR `${concat(..)}` currently does not support raw identifiers
+    };
+}
+
+macro_rules! tts_11 {
+    ($lhs:tt, $rhs:tt) => {
+        let ${concat($lhs, $rhs)}: () = ();
+        //~^ ERROR `${concat(..)}` currently does not support raw identifiers
+        //~| ERROR `${concat(..)}` currently does not support raw identifiers
+        //~| ERROR `${concat(..)}` currently does not support raw identifiers
+    };
+}
+
+fn main() {
+    idents_01!(r#_c);
+
+    idents_10!(r#_c);
+
+    idents_11!(r#_c, d);
+    idents_11!(_e, r#f);
+    idents_11!(r#_g, r#h);
+
+    tts_01!(r#_c);
+
+    tts_10!(r#_c);
+
+    tts_11!(r#_c, d);
+    tts_11!(_e, r#f);
+    tts_11!(r#_g, r#h);
+
+    no_params!();
+}
diff --git a/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.stderr b/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.stderr
new file mode 100644
index 00000000000..dd525cf0801
--- /dev/null
+++ b/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.stderr
@@ -0,0 +1,95 @@
+error: `${concat(..)}` currently does not support raw identifiers
+  --> $DIR/raw-identifiers.rs:28:22
+   |
+LL |         let ${concat(r#abc, abc)}: () = ();
+   |                      ^^^^^
+
+error: `${concat(..)}` currently does not support raw identifiers
+  --> $DIR/raw-identifiers.rs:32:27
+   |
+LL |         let ${concat(abc, r#abc)}: () = ();
+   |                           ^^^^^
+
+error: `${concat(..)}` currently does not support raw identifiers
+  --> $DIR/raw-identifiers.rs:35:22
+   |
+LL |         let ${concat(r#abc, r#abc)}: () = ();
+   |                      ^^^^^
+
+error: `${concat(..)}` currently does not support raw identifiers
+  --> $DIR/raw-identifiers.rs:5:28
+   |
+LL |         let ${concat(abc, $rhs)}: () = ();
+   |                            ^^^
+
+error: `${concat(..)}` currently does not support raw identifiers
+  --> $DIR/raw-identifiers.rs:12:23
+   |
+LL |         let ${concat($lhs, abc)}: () = ();
+   |                       ^^^
+
+error: `${concat(..)}` currently does not support raw identifiers
+  --> $DIR/raw-identifiers.rs:19:23
+   |
+LL |         let ${concat($lhs, $rhs)}: () = ();
+   |                       ^^^
+
+error: `${concat(..)}` currently does not support raw identifiers
+  --> $DIR/raw-identifiers.rs:19:29
+   |
+LL |         let ${concat($lhs, $rhs)}: () = ();
+   |                             ^^^
+
+error: `${concat(..)}` currently does not support raw identifiers
+  --> $DIR/raw-identifiers.rs:19:23
+   |
+LL |         let ${concat($lhs, $rhs)}: () = ();
+   |                       ^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `${concat(..)}` currently does not support raw identifiers
+  --> $DIR/raw-identifiers.rs:42:28
+   |
+LL |         let ${concat(abc, $rhs)}: () = ();
+   |                            ^^^
+
+error: `${concat(..)}` currently does not support raw identifiers
+  --> $DIR/raw-identifiers.rs:49:23
+   |
+LL |         let ${concat($lhs, abc)}: () = ();
+   |                       ^^^
+
+error: `${concat(..)}` currently does not support raw identifiers
+  --> $DIR/raw-identifiers.rs:56:23
+   |
+LL |         let ${concat($lhs, $rhs)}: () = ();
+   |                       ^^^
+
+error: `${concat(..)}` currently does not support raw identifiers
+  --> $DIR/raw-identifiers.rs:56:29
+   |
+LL |         let ${concat($lhs, $rhs)}: () = ();
+   |                             ^^^
+
+error: `${concat(..)}` currently does not support raw identifiers
+  --> $DIR/raw-identifiers.rs:56:23
+   |
+LL |         let ${concat($lhs, $rhs)}: () = ();
+   |                       ^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: expected pattern, found `$`
+  --> $DIR/raw-identifiers.rs:28:13
+   |
+LL |         let ${concat(r#abc, abc)}: () = ();
+   |             ^ expected pattern
+...
+LL |     no_params!();
+   |     ------------ in this macro invocation
+   |
+   = note: this error originates in the macro `no_params` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 14 previous errors
+
diff --git a/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs b/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs
new file mode 100644
index 00000000000..bf47442ea76
--- /dev/null
+++ b/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs
@@ -0,0 +1,50 @@
+#![feature(macro_metavar_expr_concat)]
+
+macro_rules! wrong_concat_declarations {
+    ($ex:expr) => {
+        ${concat()}
+        //~^ ERROR expected identifier
+
+        ${concat(aaaa)}
+        //~^ ERROR `concat` must have at least two elements
+
+        ${concat(aaaa,)}
+        //~^ ERROR expected identifier
+
+        ${concat(aaaa, 1)}
+        //~^ ERROR expected identifier
+
+        ${concat(_, aaaa)}
+
+        ${concat(aaaa aaaa)}
+        //~^ ERROR expected comma
+
+        ${concat($ex)}
+        //~^ ERROR `concat` must have at least two elements
+
+        ${concat($ex, aaaa)}
+        //~^ ERROR `${concat(..)}` currently only accepts identifiers
+
+        ${concat($ex, aaaa 123)}
+        //~^ ERROR expected comma
+
+        ${concat($ex, aaaa,)}
+        //~^ ERROR expected identifier
+
+        ${concat($ex, aaaa, 123)}
+        //~^ ERROR expected identifier
+    };
+}
+
+macro_rules! dollar_sign_without_referenced_ident {
+    ($ident:ident) => {
+        const ${concat(FOO, $foo)}: i32 = 2;
+        //~^ ERROR variable `foo` is not recognized in meta-variable expression
+    };
+}
+
+fn main() {
+    wrong_concat_declarations!(1);
+
+    dollar_sign_without_referenced_ident!(VAR);
+}
diff --git a/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr b/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr
new file mode 100644
index 00000000000..b216a86d59a
--- /dev/null
+++ b/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr
@@ -0,0 +1,68 @@
+error: expected identifier
+  --> $DIR/syntax-errors.rs:5:10
+   |
+LL |         ${concat()}
+   |          ^^^^^^^^^^
+
+error: `concat` must have at least two elements
+  --> $DIR/syntax-errors.rs:8:11
+   |
+LL |         ${concat(aaaa)}
+   |           ^^^^^^
+
+error: expected identifier
+  --> $DIR/syntax-errors.rs:11:10
+   |
+LL |         ${concat(aaaa,)}
+   |          ^^^^^^^^^^^^^^^
+
+error: expected identifier, found `1`
+  --> $DIR/syntax-errors.rs:14:24
+   |
+LL |         ${concat(aaaa, 1)}
+   |                        ^ help: try removing `1`
+
+error: expected comma
+  --> $DIR/syntax-errors.rs:19:10
+   |
+LL |         ${concat(aaaa aaaa)}
+   |          ^^^^^^^^^^^^^^^^^^^
+
+error: `concat` must have at least two elements
+  --> $DIR/syntax-errors.rs:22:11
+   |
+LL |         ${concat($ex)}
+   |           ^^^^^^
+
+error: expected comma
+  --> $DIR/syntax-errors.rs:28:10
+   |
+LL |         ${concat($ex, aaaa 123)}
+   |          ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: expected identifier
+  --> $DIR/syntax-errors.rs:31:10
+   |
+LL |         ${concat($ex, aaaa,)}
+   |          ^^^^^^^^^^^^^^^^^^^^
+
+error: expected identifier, found `123`
+  --> $DIR/syntax-errors.rs:34:29
+   |
+LL |         ${concat($ex, aaaa, 123)}
+   |                             ^^^ help: try removing `123`
+
+error: `${concat(..)}` currently only accepts identifiers or meta-variables as parameters
+  --> $DIR/syntax-errors.rs:25:19
+   |
+LL |         ${concat($ex, aaaa)}
+   |                   ^^
+
+error: variable `foo` is not recognized in meta-variable expression
+  --> $DIR/syntax-errors.rs:41:30
+   |
+LL |         const ${concat(FOO, $foo)}: i32 = 2;
+   |                              ^^^
+
+error: aborting due to 11 previous errors
+
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
index 3fa3839bae2..8e4ba192d79 100644
--- a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
+++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
@@ -191,10 +191,10 @@ LL |     ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } };
    |                                 ^^^^^^^^^^^^^^ help: supported expressions are count, ignore, index and len
 
 error: expected identifier
-  --> $DIR/syntax-errors.rs:118:31
+  --> $DIR/syntax-errors.rs:118:33
    |
 LL |     ( $( $i:ident ),* ) => { ${ {} } };
-   |                               ^^^^^^
+   |                                 ^^
 
 error: `count` can not be placed inside the inner-most repetition
   --> $DIR/syntax-errors.rs:12:24
diff --git a/tests/ui/methods/opaque_param_in_ufc.rs b/tests/ui/methods/opaque_param_in_ufc.rs
index a4b27a0131f..b170e6805f6 100644
--- a/tests/ui/methods/opaque_param_in_ufc.rs
+++ b/tests/ui/methods/opaque_param_in_ufc.rs
@@ -1,4 +1,7 @@
 #![feature(type_alias_impl_trait)]
+
+//@ check-pass
+
 struct Foo<T>(T);
 
 impl Foo<u32> {
@@ -15,14 +18,11 @@ fn bar() -> Bar {
 impl Foo<Bar> {
     fn foo() -> Bar {
         Self::method();
-        //~^ ERROR: no function or associated item named `method` found for struct `Foo<Bar>`
         Foo::<Bar>::method();
-        //~^ ERROR: no function or associated item named `method` found for struct `Foo<Bar>`
         let x = Foo(bar());
         Foo::method2(x);
         let x = Self(bar());
         Self::method2(x);
-        //~^ ERROR: no function or associated item named `method2` found for struct `Foo<Bar>`
         todo!()
     }
 }
diff --git a/tests/ui/methods/opaque_param_in_ufc.stderr b/tests/ui/methods/opaque_param_in_ufc.stderr
deleted file mode 100644
index 7e5bbbac8a9..00000000000
--- a/tests/ui/methods/opaque_param_in_ufc.stderr
+++ /dev/null
@@ -1,36 +0,0 @@
-error[E0599]: no function or associated item named `method` found for struct `Foo<Bar>` in the current scope
-  --> $DIR/opaque_param_in_ufc.rs:17:15
-   |
-LL | struct Foo<T>(T);
-   | ------------- function or associated item `method` not found for this struct
-...
-LL |         Self::method();
-   |               ^^^^^^ function or associated item not found in `Foo<Bar>`
-   |
-   = note: the function or associated item was found for
-           - `Foo<u32>`
-
-error[E0599]: no function or associated item named `method` found for struct `Foo<Bar>` in the current scope
-  --> $DIR/opaque_param_in_ufc.rs:19:21
-   |
-LL | struct Foo<T>(T);
-   | ------------- function or associated item `method` not found for this struct
-...
-LL |         Foo::<Bar>::method();
-   |                     ^^^^^^ function or associated item not found in `Foo<Bar>`
-   |
-   = note: the function or associated item was found for
-           - `Foo<u32>`
-
-error[E0599]: no function or associated item named `method2` found for struct `Foo<Bar>` in the current scope
-  --> $DIR/opaque_param_in_ufc.rs:24:15
-   |
-LL | struct Foo<T>(T);
-   | ------------- function or associated item `method2` not found for this struct
-...
-LL |         Self::method2(x);
-   |               ^^^^^^^ function or associated item not found in `Foo<Bar>`
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/namespace/namespace-mix.stderr b/tests/ui/namespace/namespace-mix.stderr
index 4eff08ead42..b80363fe8f8 100644
--- a/tests/ui/namespace/namespace-mix.stderr
+++ b/tests/ui/namespace/namespace-mix.stderr
@@ -12,7 +12,7 @@ help: a tuple struct with a similar name exists
    |
 LL |     check(m1::TS);
    |               ~~
-help: consider importing one of these items instead
+help: consider importing one of these constants instead
    |
 LL + use m2::S;
    |
@@ -40,7 +40,7 @@ help: a tuple struct with a similar name exists
    |
 LL |     check(xm1::TS);
    |                ~~
-help: consider importing one of these items instead
+help: consider importing one of these constants instead
    |
 LL + use m2::S;
    |
@@ -66,7 +66,7 @@ help: a tuple variant with a similar name exists
    |
 LL |     check(m7::TV);
    |               ~~
-help: consider importing one of these items instead
+help: consider importing one of these constants instead
    |
 LL + use m8::V;
    |
@@ -94,7 +94,7 @@ help: a tuple variant with a similar name exists
    |
 LL |     check(xm7::TV);
    |                ~~
-help: consider importing one of these items instead
+help: consider importing one of these constants instead
    |
 LL + use m8::V;
    |
diff --git a/tests/ui/never_type/defaulted-never-note.fallback.stderr b/tests/ui/never_type/defaulted-never-note.fallback.stderr
index 92fa9068cfd..fe9a924f64a 100644
--- a/tests/ui/never_type/defaulted-never-note.fallback.stderr
+++ b/tests/ui/never_type/defaulted-never-note.fallback.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied
-  --> $DIR/defaulted-never-note.rs:30:9
+  --> $DIR/defaulted-never-note.rs:32:9
    |
 LL |     foo(_x);
    |     --- ^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!`
diff --git a/tests/ui/never_type/defaulted-never-note.nofallback.stderr b/tests/ui/never_type/defaulted-never-note.nofallback.stderr
new file mode 100644
index 00000000000..d88615186dd
--- /dev/null
+++ b/tests/ui/never_type/defaulted-never-note.nofallback.stderr
@@ -0,0 +1,18 @@
+warning: this function depends on never type fallback being `()`
+  --> $DIR/defaulted-never-note.rs:28:1
+   |
+LL | fn smeg() {
+   | ^^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: ImplementedForUnitButNotNever` will fail
+  --> $DIR/defaulted-never-note.rs:32:9
+   |
+LL |     foo(_x);
+   |         ^^
+   = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/never_type/defaulted-never-note.rs b/tests/ui/never_type/defaulted-never-note.rs
index f4e5273b33a..40861e73b39 100644
--- a/tests/ui/never_type/defaulted-never-note.rs
+++ b/tests/ui/never_type/defaulted-never-note.rs
@@ -26,6 +26,8 @@ fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
 //[fallback]~^ NOTE required by this bound in `foo`
 //[fallback]~| NOTE required by a bound in `foo`
 fn smeg() {
+    //[nofallback]~^ warn: this function depends on never type fallback being `()`
+    //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
     let _x = return;
     foo(_x);
     //[fallback]~^ ERROR the trait bound
diff --git a/tests/ui/never_type/dependency-on-fallback-to-unit.rs b/tests/ui/never_type/dependency-on-fallback-to-unit.rs
new file mode 100644
index 00000000000..5448d0be2c6
--- /dev/null
+++ b/tests/ui/never_type/dependency-on-fallback-to-unit.rs
@@ -0,0 +1,28 @@
+//@ check-pass
+
+fn main() {
+    def();
+    _ = question_mark();
+}
+
+fn def() {
+    //~^ warn: this function depends on never type fallback being `()`
+    //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    match true {
+        false => <_>::default(),
+        true => return,
+    };
+}
+
+// <https://github.com/rust-lang/rust/issues/51125>
+// <https://github.com/rust-lang/rust/issues/39216>
+fn question_mark() -> Result<(), ()> {
+    //~^ warn: this function depends on never type fallback being `()`
+    //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    deserialize()?;
+    Ok(())
+}
+
+fn deserialize<T: Default>() -> Result<T, ()> {
+    Ok(T::default())
+}
diff --git a/tests/ui/never_type/dependency-on-fallback-to-unit.stderr b/tests/ui/never_type/dependency-on-fallback-to-unit.stderr
new file mode 100644
index 00000000000..ec49137ba79
--- /dev/null
+++ b/tests/ui/never_type/dependency-on-fallback-to-unit.stderr
@@ -0,0 +1,33 @@
+warning: this function depends on never type fallback being `()`
+  --> $DIR/dependency-on-fallback-to-unit.rs:8:1
+   |
+LL | fn def() {
+   | ^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: Default` will fail
+  --> $DIR/dependency-on-fallback-to-unit.rs:12:19
+   |
+LL |         false => <_>::default(),
+   |                   ^
+   = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
+
+warning: this function depends on never type fallback being `()`
+  --> $DIR/dependency-on-fallback-to-unit.rs:19:1
+   |
+LL | fn question_mark() -> Result<(), ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: Default` will fail
+  --> $DIR/dependency-on-fallback-to-unit.rs:22:5
+   |
+LL |     deserialize()?;
+   |     ^^^^^^^^^^^^^
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr b/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr
new file mode 100644
index 00000000000..2a3c5edc218
--- /dev/null
+++ b/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr
@@ -0,0 +1,33 @@
+warning: this function depends on never type fallback being `()`
+  --> $DIR/diverging-fallback-control-flow.rs:30:1
+   |
+LL | fn assignment() {
+   | ^^^^^^^^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: UnitDefault` will fail
+  --> $DIR/diverging-fallback-control-flow.rs:36:13
+   |
+LL |         x = UnitDefault::default();
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+   = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
+
+warning: this function depends on never type fallback being `()`
+  --> $DIR/diverging-fallback-control-flow.rs:42:1
+   |
+LL | fn assignment_rev() {
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: UnitDefault` will fail
+  --> $DIR/diverging-fallback-control-flow.rs:50:13
+   |
+LL |         x = UnitDefault::default();
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/never_type/diverging-fallback-control-flow.rs b/tests/ui/never_type/diverging-fallback-control-flow.rs
index e209a990885..575e2e9273c 100644
--- a/tests/ui/never_type/diverging-fallback-control-flow.rs
+++ b/tests/ui/never_type/diverging-fallback-control-flow.rs
@@ -28,6 +28,8 @@ impl UnitDefault for () {
 }
 
 fn assignment() {
+    //[nofallback]~^ warn: this function depends on never type fallback being `()`
+    //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
     let x;
 
     if true {
@@ -38,6 +40,8 @@ fn assignment() {
 }
 
 fn assignment_rev() {
+    //[nofallback]~^ warn: this function depends on never type fallback being `()`
+    //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
     let x;
 
     if true {
diff --git a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr
index 01abf2e17f1..c5463814475 100644
--- a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr
+++ b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `!: Test` is not satisfied
-  --> $DIR/diverging-fallback-no-leak.rs:17:23
+  --> $DIR/diverging-fallback-no-leak.rs:20:23
    |
 LL |     unconstrained_arg(return);
    |     ----------------- ^^^^^^ the trait `Test` is not implemented for `!`
diff --git a/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr
new file mode 100644
index 00000000000..11245cc7aab
--- /dev/null
+++ b/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr
@@ -0,0 +1,18 @@
+warning: this function depends on never type fallback being `()`
+  --> $DIR/diverging-fallback-no-leak.rs:14:1
+   |
+LL | fn main() {
+   | ^^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: Test` will fail
+  --> $DIR/diverging-fallback-no-leak.rs:20:23
+   |
+LL |     unconstrained_arg(return);
+   |                       ^^^^^^
+   = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/never_type/diverging-fallback-no-leak.rs b/tests/ui/never_type/diverging-fallback-no-leak.rs
index 425437da207..c6d59c7f273 100644
--- a/tests/ui/never_type/diverging-fallback-no-leak.rs
+++ b/tests/ui/never_type/diverging-fallback-no-leak.rs
@@ -12,6 +12,9 @@ impl Test for () {}
 fn unconstrained_arg<T: Test>(_: T) {}
 
 fn main() {
+    //[nofallback]~^ warn: this function depends on never type fallback being `()`
+    //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
     // Here the type variable falls back to `!`,
     // and hence we get a type error.
     unconstrained_arg(return);
diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr b/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr
new file mode 100644
index 00000000000..b485c94df4d
--- /dev/null
+++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr
@@ -0,0 +1,18 @@
+warning: this function depends on never type fallback being `()`
+  --> $DIR/diverging-fallback-unconstrained-return.rs:28:1
+   |
+LL | fn main() {
+   | ^^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: UnitReturn` will fail
+  --> $DIR/diverging-fallback-unconstrained-return.rs:39:23
+   |
+LL |     let _ = if true { unconstrained_return() } else { panic!() };
+   |                       ^^^^^^^^^^^^^^^^^^^^^^
+   = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs
index aeb6ee6e26e..927991db513 100644
--- a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs
+++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs
@@ -26,6 +26,9 @@ fn unconstrained_return<T: UnitReturn>() -> T {
 }
 
 fn main() {
+    //[nofallback]~^ warn: this function depends on never type fallback being `()`
+    //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
     // In Ye Olde Days, the `T` parameter of `unconstrained_return`
     // winds up "entangled" with the `!` type that results from
     // `panic!`, and hence falls back to `()`. This is kind of unfortunate
diff --git a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr
new file mode 100644
index 00000000000..3fb5536dee7
--- /dev/null
+++ b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr
@@ -0,0 +1,18 @@
+warning: this function depends on never type fallback being `()`
+  --> $DIR/fallback-closure-ret.rs:21:1
+   |
+LL | fn main() {
+   | ^^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: Bar` will fail
+  --> $DIR/fallback-closure-ret.rs:24:5
+   |
+LL |     foo(|| panic!());
+   |     ^^^^^^^^^^^^^^^^
+   = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/never_type/fallback-closure-ret.rs b/tests/ui/never_type/fallback-closure-ret.rs
index dcf38e03a13..30f9ac54d0b 100644
--- a/tests/ui/never_type/fallback-closure-ret.rs
+++ b/tests/ui/never_type/fallback-closure-ret.rs
@@ -12,12 +12,14 @@
 
 #![cfg_attr(fallback, feature(never_type_fallback))]
 
-trait Bar { }
-impl Bar for () {  }
-impl Bar for u32 {  }
+trait Bar {}
+impl Bar for () {}
+impl Bar for u32 {}
 
 fn foo<R: Bar>(_: impl Fn() -> R) {}
 
 fn main() {
+    //[nofallback]~^ warn: this function depends on never type fallback being `()`
+    //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
     foo(|| panic!());
 }
diff --git a/tests/ui/never_type/impl_trait_fallback.rs b/tests/ui/never_type/impl_trait_fallback.rs
index ce06f8f7817..fbe13dbe2ac 100644
--- a/tests/ui/never_type/impl_trait_fallback.rs
+++ b/tests/ui/never_type/impl_trait_fallback.rs
@@ -6,5 +6,7 @@ trait T {}
 impl T for () {}
 
 fn should_ret_unit() -> impl T {
+    //~^ warn: this function depends on never type fallback being `()`
+    //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
     panic!()
 }
diff --git a/tests/ui/never_type/impl_trait_fallback.stderr b/tests/ui/never_type/impl_trait_fallback.stderr
new file mode 100644
index 00000000000..4496746e018
--- /dev/null
+++ b/tests/ui/never_type/impl_trait_fallback.stderr
@@ -0,0 +1,18 @@
+warning: this function depends on never type fallback being `()`
+  --> $DIR/impl_trait_fallback.rs:8:1
+   |
+LL | fn should_ret_unit() -> impl T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: T` will fail
+  --> $DIR/impl_trait_fallback.rs:8:25
+   |
+LL | fn should_ret_unit() -> impl T {
+   |                         ^^^^^^
+   = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/numbers-arithmetic/f16-f128-lit.rs b/tests/ui/numbers-arithmetic/f16-f128-lit.rs
index 762436edb16..7fd20d91d82 100644
--- a/tests/ui/numbers-arithmetic/f16-f128-lit.rs
+++ b/tests/ui/numbers-arithmetic/f16-f128-lit.rs
@@ -1,3 +1,5 @@
+// Make sure negation happens correctly. Also included:
+// issue: rust-lang/rust#124583
 //@ run-pass
 
 #![feature(f16)]
@@ -8,9 +10,11 @@ fn main() {
     assert_eq!((-0.0_f16).to_bits(), 0x8000);
     assert_eq!(10.0_f16.to_bits(), 0x4900);
     assert_eq!((-10.0_f16).to_bits(), 0xC900);
+    assert_eq!((-(-0.0f16)).to_bits(), 0x0000);
 
     assert_eq!(0.0_f128.to_bits(), 0x0000_0000_0000_0000_0000_0000_0000_0000);
     assert_eq!((-0.0_f128).to_bits(), 0x8000_0000_0000_0000_0000_0000_0000_0000);
     assert_eq!(10.0_f128.to_bits(), 0x4002_4000_0000_0000_0000_0000_0000_0000);
     assert_eq!((-10.0_f128).to_bits(), 0xC002_4000_0000_0000_0000_0000_0000_0000);
+    assert_eq!((-(-0.0f128)).to_bits(), 0x0000_0000_0000_0000_0000_0000_0000_0000);
 }
diff --git a/tests/crashes/124004.rs b/tests/ui/pattern/box-pattern-type-mismatch.rs
index 1fcf0785945..6c980503256 100644
--- a/tests/crashes/124004.rs
+++ b/tests/ui/pattern/box-pattern-type-mismatch.rs
@@ -1,10 +1,11 @@
-//@ known-bug: #124004
+//! This test used to ICE #124004
 
 #![feature(box_patterns)]
 
 use std::ops::{ Deref };
 
 struct X(dyn Iterator<Item = &'a ()>);
+//~^ ERROR: use of undeclared lifetime name `'a`
 
 impl Deref for X {
     type Target = isize;
diff --git a/tests/ui/pattern/box-pattern-type-mismatch.stderr b/tests/ui/pattern/box-pattern-type-mismatch.stderr
new file mode 100644
index 00000000000..14f7dbbd839
--- /dev/null
+++ b/tests/ui/pattern/box-pattern-type-mismatch.stderr
@@ -0,0 +1,19 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/box-pattern-type-mismatch.rs:7:31
+   |
+LL | struct X(dyn Iterator<Item = &'a ()>);
+   |                               ^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+   |
+LL | struct X(dyn for<'a> Iterator<Item = &'a ()>);
+   |              +++++++
+help: consider introducing lifetime `'a` here
+   |
+LL | struct X<'a>(dyn Iterator<Item = &'a ()>);
+   |         ++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/tests/ui/pattern/missing_lifetime.rs b/tests/ui/pattern/missing_lifetime.rs
new file mode 100644
index 00000000000..081f667d8f6
--- /dev/null
+++ b/tests/ui/pattern/missing_lifetime.rs
@@ -0,0 +1,25 @@
+//! This test used to ICE: rust-lang/rust#125914
+//! Instead of actually analyzing the erroneous patterns,
+//! we instead stop after typeck where errors are already
+//! reported.
+
+enum AstKind<'ast> {
+    //~^ ERROR: `'ast` is never used
+    ExprInt,
+}
+
+enum Foo {
+    Bar(isize),
+    Baz,
+}
+
+enum Other {
+    Other1(Foo),
+    Other2(AstKind), //~ ERROR: missing lifetime specifier
+}
+
+fn main() {
+    match Other::Other1(Foo::Baz) {
+        ::Other::Other2(::Foo::Bar(..)) => {}
+    }
+}
diff --git a/tests/ui/pattern/missing_lifetime.stderr b/tests/ui/pattern/missing_lifetime.stderr
new file mode 100644
index 00000000000..ec4063fd289
--- /dev/null
+++ b/tests/ui/pattern/missing_lifetime.stderr
@@ -0,0 +1,25 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing_lifetime.rs:18:12
+   |
+LL |     Other2(AstKind),
+   |            ^^^^^^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL ~ enum Other<'a> {
+LL |     Other1(Foo),
+LL ~     Other2(AstKind<'a>),
+   |
+
+error[E0392]: lifetime parameter `'ast` is never used
+  --> $DIR/missing_lifetime.rs:6:14
+   |
+LL | enum AstKind<'ast> {
+   |              ^^^^ unused lifetime parameter
+   |
+   = help: consider removing `'ast`, referring to it in a field, or using a marker such as `PhantomData`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0106, E0392.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/pattern/type_mismatch.rs b/tests/ui/pattern/type_mismatch.rs
new file mode 100644
index 00000000000..408ff758847
--- /dev/null
+++ b/tests/ui/pattern/type_mismatch.rs
@@ -0,0 +1,30 @@
+//! This test used to ICE: rust-lang/rust#109812
+//! Instead of actually analyzing the erroneous patterns,
+//! we instead stop after typeck where errors are already
+//! reported.
+
+#![warn(rust_2021_incompatible_closure_captures)]
+
+enum Either {
+    One(X),
+    Two(X),
+}
+
+struct X(Y);
+
+struct Y;
+
+fn consume_fnmut(_: impl FnMut()) {}
+
+fn move_into_fnmut() {
+    let x = X(Y);
+
+    consume_fnmut(|| {
+        let Either::Two(ref mut _t) = x;
+        //~^ ERROR: mismatched types
+
+        let X(mut _t) = x;
+    });
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/type_mismatch.stderr b/tests/ui/pattern/type_mismatch.stderr
new file mode 100644
index 00000000000..b0441b1fadc
--- /dev/null
+++ b/tests/ui/pattern/type_mismatch.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/type_mismatch.rs:23:13
+   |
+LL |         let Either::Two(ref mut _t) = x;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `X`
+   |             |
+   |             expected `X`, found `Either`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/proc-macro/auxiliary/api/literal.rs b/tests/ui/proc-macro/auxiliary/api/literal.rs
new file mode 100644
index 00000000000..7109340bb64
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/api/literal.rs
@@ -0,0 +1,83 @@
+// ignore-tidy-linelength
+
+use proc_macro::Literal;
+
+pub fn test() {
+    test_display_literal();
+    test_parse_literal();
+}
+
+fn test_display_literal() {
+    assert_eq!(Literal::isize_unsuffixed(-10).to_string(), "-10");
+    assert_eq!(Literal::isize_suffixed(-10).to_string(), "-10isize");
+    assert_eq!(Literal::f32_unsuffixed(-10.0).to_string(), "-10.0");
+    assert_eq!(Literal::f32_suffixed(-10.0).to_string(), "-10f32");
+    assert_eq!(Literal::f64_unsuffixed(-10.0).to_string(), "-10.0");
+    assert_eq!(Literal::f64_suffixed(-10.0).to_string(), "-10f64");
+    assert_eq!(
+        Literal::f64_unsuffixed(1e100).to_string(),
+        "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0",
+    );
+
+    assert_eq!(Literal::string("aA").to_string(), r#"  "aA"  "#.trim());
+    assert_eq!(Literal::string("\t").to_string(), r#"  "\t"  "#.trim());
+    assert_eq!(Literal::string("❤").to_string(), r#"  "❤"  "#.trim());
+    assert_eq!(Literal::string("'").to_string(), r#"  "'"  "#.trim());
+    assert_eq!(Literal::string("\"").to_string(), r#"  "\""  "#.trim());
+    assert_eq!(Literal::string("\0").to_string(), r#"  "\0"  "#.trim());
+    assert_eq!(Literal::string("\u{1}").to_string(), r#"  "\u{1}"  "#.trim());
+
+    assert_eq!(Literal::byte_string(b"aA").to_string(), r#"  b"aA"  "#.trim());
+    assert_eq!(Literal::byte_string(b"\t").to_string(), r#"  b"\t"  "#.trim());
+    assert_eq!(Literal::byte_string(b"'").to_string(), r#"  b"'"  "#.trim());
+    assert_eq!(Literal::byte_string(b"\"").to_string(), r#"  b"\""  "#.trim());
+    assert_eq!(Literal::byte_string(b"\0").to_string(), r#"  b"\0"  "#.trim());
+    assert_eq!(Literal::byte_string(b"\x01").to_string(), r#"  b"\x01"  "#.trim());
+
+    assert_eq!(Literal::c_string(c"aA").to_string(), r#"  c"aA"  "#.trim());
+    assert_eq!(Literal::c_string(c"\t").to_string(), r#"  c"\t"  "#.trim());
+    assert_eq!(Literal::c_string(c"❤").to_string(), r#"  c"❤"  "#.trim());
+    assert_eq!(Literal::c_string(c"\'").to_string(), r#"  c"'"  "#.trim());
+    assert_eq!(Literal::c_string(c"\"").to_string(), r#"  c"\""  "#.trim());
+    assert_eq!(Literal::c_string(c"\x7f\xff\xfe\u{333}").to_string(), r#"  c"\u{7f}\xff\xfe\u{333}"  "#.trim());
+
+    assert_eq!(Literal::character('a').to_string(), r#"  'a'  "#.trim());
+    assert_eq!(Literal::character('\t').to_string(), r#"  '\t'  "#.trim());
+    assert_eq!(Literal::character('❤').to_string(), r#"  '❤'  "#.trim());
+    assert_eq!(Literal::character('\'').to_string(), r#"  '\''  "#.trim());
+    assert_eq!(Literal::character('"').to_string(), r#"  '"'  "#.trim());
+    assert_eq!(Literal::character('\0').to_string(), r#"  '\0'  "#.trim());
+    assert_eq!(Literal::character('\u{1}').to_string(), r#"  '\u{1}'  "#.trim());
+
+    assert_eq!(Literal::byte_character(b'a').to_string(), r#"  b'a'  "#.trim());
+    assert_eq!(Literal::byte_character(b'\t').to_string(), r#"  b'\t'  "#.trim());
+    assert_eq!(Literal::byte_character(b'\'').to_string(), r#"  b'\''  "#.trim());
+    assert_eq!(Literal::byte_character(b'"').to_string(), r#"  b'"'  "#.trim());
+    assert_eq!(Literal::byte_character(0).to_string(), r#"  b'\0'  "#.trim());
+    assert_eq!(Literal::byte_character(1).to_string(), r#"  b'\x01'  "#.trim());
+}
+
+fn test_parse_literal() {
+    assert_eq!("1".parse::<Literal>().unwrap().to_string(), "1");
+    assert_eq!("1.0".parse::<Literal>().unwrap().to_string(), "1.0");
+    assert_eq!("'a'".parse::<Literal>().unwrap().to_string(), "'a'");
+    assert_eq!("b'a'".parse::<Literal>().unwrap().to_string(), "b'a'");
+    assert_eq!("\"\n\"".parse::<Literal>().unwrap().to_string(), "\"\n\"");
+    assert_eq!("b\"\"".parse::<Literal>().unwrap().to_string(), "b\"\"");
+    assert_eq!("c\"\"".parse::<Literal>().unwrap().to_string(), "c\"\"");
+    assert_eq!("r##\"\"##".parse::<Literal>().unwrap().to_string(), "r##\"\"##");
+    assert_eq!("10ulong".parse::<Literal>().unwrap().to_string(), "10ulong");
+    assert_eq!("-10ulong".parse::<Literal>().unwrap().to_string(), "-10ulong");
+
+    assert!("true".parse::<Literal>().is_err());
+    assert!(".8".parse::<Literal>().is_err());
+    assert!("0 1".parse::<Literal>().is_err());
+    assert!("'a".parse::<Literal>().is_err());
+    assert!(" 0".parse::<Literal>().is_err());
+    assert!("0 ".parse::<Literal>().is_err());
+    assert!("/* comment */0".parse::<Literal>().is_err());
+    assert!("0/* comment */".parse::<Literal>().is_err());
+    assert!("0// comment".parse::<Literal>().is_err());
+    assert!("- 10".parse::<Literal>().is_err());
+    assert!("-'x'".parse::<Literal>().is_err());
+}
diff --git a/tests/ui/proc-macro/auxiliary/api/mod.rs b/tests/ui/proc-macro/auxiliary/api/mod.rs
index 45ef6922d28..e0a381cb6c1 100644
--- a/tests/ui/proc-macro/auxiliary/api/mod.rs
+++ b/tests/ui/proc-macro/auxiliary/api/mod.rs
@@ -10,7 +10,7 @@
 extern crate proc_macro;
 
 mod cmp;
-mod parse;
+mod literal;
 
 use proc_macro::TokenStream;
 
@@ -19,7 +19,7 @@ pub fn run(input: TokenStream) -> TokenStream {
     assert!(input.is_empty());
 
     cmp::test();
-    parse::test();
+    literal::test();
 
     TokenStream::new()
 }
diff --git a/tests/ui/proc-macro/auxiliary/api/parse.rs b/tests/ui/proc-macro/auxiliary/api/parse.rs
deleted file mode 100644
index 801c616c804..00000000000
--- a/tests/ui/proc-macro/auxiliary/api/parse.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-// ignore-tidy-linelength
-
-use proc_macro::Literal;
-
-pub fn test() {
-    test_display_literal();
-    test_parse_literal();
-}
-
-fn test_display_literal() {
-    assert_eq!(Literal::isize_unsuffixed(-10).to_string(), "-10");
-    assert_eq!(Literal::isize_suffixed(-10).to_string(), "-10isize");
-    assert_eq!(Literal::f32_unsuffixed(-10.0).to_string(), "-10.0");
-    assert_eq!(Literal::f32_suffixed(-10.0).to_string(), "-10f32");
-    assert_eq!(Literal::f64_unsuffixed(-10.0).to_string(), "-10.0");
-    assert_eq!(Literal::f64_suffixed(-10.0).to_string(), "-10f64");
-    assert_eq!(
-        Literal::f64_unsuffixed(1e100).to_string(),
-        "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0",
-    );
-
-    assert_eq!(Literal::string("a \t ❤ ' \" \u{1}").to_string(), "\"a \\t ❤ ' \\\" \\u{1}\"",);
-    assert_eq!(Literal::c_string(c"\'\"\x7f\u{7fff}").to_string(), r#"c"\'\"\x7f\xe7\xbf\xbf""#);
-    assert_eq!(Literal::character('a').to_string(), "'a'");
-    assert_eq!(Literal::character('\t').to_string(), "'\\t'");
-    assert_eq!(Literal::character('❤').to_string(), "'❤'");
-    assert_eq!(Literal::character('\'').to_string(), "'\\''");
-    assert_eq!(Literal::character('"').to_string(), "'\"'");
-    assert_eq!(Literal::character('\u{1}').to_string(), "'\\u{1}'");
-
-    assert_eq!(Literal::byte_character(b'a').to_string(), "b'a'");
-    assert_eq!(Literal::byte_character(0).to_string(), "b'\\x00'");
-}
-
-fn test_parse_literal() {
-    assert_eq!("1".parse::<Literal>().unwrap().to_string(), "1");
-    assert_eq!("1.0".parse::<Literal>().unwrap().to_string(), "1.0");
-    assert_eq!("'a'".parse::<Literal>().unwrap().to_string(), "'a'");
-    assert_eq!("b'a'".parse::<Literal>().unwrap().to_string(), "b'a'");
-    assert_eq!("\"\n\"".parse::<Literal>().unwrap().to_string(), "\"\n\"");
-    assert_eq!("b\"\"".parse::<Literal>().unwrap().to_string(), "b\"\"");
-    assert_eq!("c\"\"".parse::<Literal>().unwrap().to_string(), "c\"\"");
-    assert_eq!("r##\"\"##".parse::<Literal>().unwrap().to_string(), "r##\"\"##");
-    assert_eq!("10ulong".parse::<Literal>().unwrap().to_string(), "10ulong");
-    assert_eq!("-10ulong".parse::<Literal>().unwrap().to_string(), "-10ulong");
-
-    assert!("true".parse::<Literal>().is_err());
-    assert!(".8".parse::<Literal>().is_err());
-    assert!("0 1".parse::<Literal>().is_err());
-    assert!("'a".parse::<Literal>().is_err());
-    assert!(" 0".parse::<Literal>().is_err());
-    assert!("0 ".parse::<Literal>().is_err());
-    assert!("/* comment */0".parse::<Literal>().is_err());
-    assert!("0/* comment */".parse::<Literal>().is_err());
-    assert!("0// comment".parse::<Literal>().is_err());
-    assert!("- 10".parse::<Literal>().is_err());
-    assert!("-'x'".parse::<Literal>().is_err());
-}
diff --git a/tests/ui/resolve/issue-16058.stderr b/tests/ui/resolve/issue-16058.stderr
index 914990c35ff..12b1ac8a5fb 100644
--- a/tests/ui/resolve/issue-16058.stderr
+++ b/tests/ui/resolve/issue-16058.stderr
@@ -4,7 +4,7 @@ error[E0574]: expected struct, variant or union type, found enum `Result`
 LL |         Result {
    |         ^^^^^^ not a struct, variant or union type
    |
-help: consider importing one of these items instead
+help: consider importing one of these type aliases instead
    |
 LL + use std::fmt::Result;
    |
diff --git a/tests/ui/resolve/issue-21221-1.stderr b/tests/ui/resolve/issue-21221-1.stderr
index a38116cd728..ccf03afaa19 100644
--- a/tests/ui/resolve/issue-21221-1.stderr
+++ b/tests/ui/resolve/issue-21221-1.stderr
@@ -4,14 +4,14 @@ error[E0405]: cannot find trait `Mul` in this scope
 LL | impl Mul for Foo {
    |      ^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing one of these traits
+   |
+LL + use std::ops::Mul;
    |
 LL + use mul1::Mul;
    |
 LL + use mul2::Mul;
    |
-LL + use std::ops::Mul;
-   |
 
 error[E0412]: cannot find type `Mul` in this scope
   --> $DIR/issue-21221-1.rs:58:16
@@ -19,14 +19,14 @@ error[E0412]: cannot find type `Mul` in this scope
 LL | fn getMul() -> Mul {
    |                ^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing one of these traits
+   |
+LL + use std::ops::Mul;
    |
 LL + use mul1::Mul;
    |
 LL + use mul2::Mul;
    |
-LL + use std::ops::Mul;
-   |
 
 error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope
   --> $DIR/issue-21221-1.rs:63:6
diff --git a/tests/ui/resolve/issue-21221-2.stderr b/tests/ui/resolve/issue-21221-2.stderr
index 3bd4c1a5d13..5db327955eb 100644
--- a/tests/ui/resolve/issue-21221-2.stderr
+++ b/tests/ui/resolve/issue-21221-2.stderr
@@ -4,7 +4,7 @@ error[E0405]: cannot find trait `T` in this scope
 LL | impl T for Foo { }
    |      ^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing one of these traits
    |
 LL + use baz::T;
    |
diff --git a/tests/ui/resolve/issue-50599.stderr b/tests/ui/resolve/issue-50599.stderr
index e5eacd741fb..24fb3d580b8 100644
--- a/tests/ui/resolve/issue-50599.stderr
+++ b/tests/ui/resolve/issue-50599.stderr
@@ -4,7 +4,7 @@ error[E0425]: cannot find value `LOG10_2` in module `std::f64`
 LL |     const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize;
    |                                                ^^^^^^^ not found in `std::f64`
    |
-help: consider importing one of these items
+help: consider importing one of these constants
    |
 LL + use std::f128::consts::LOG10_2;
    |
diff --git a/tests/ui/resolve/issue-73427.stderr b/tests/ui/resolve/issue-73427.stderr
index c5e245d884b..0a9a504f79c 100644
--- a/tests/ui/resolve/issue-73427.stderr
+++ b/tests/ui/resolve/issue-73427.stderr
@@ -105,7 +105,7 @@ help: the following enum variant is available
    |
 LL |     (E::TupleWithFields(/* fields */)).foo();
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: consider importing one of these items instead
+help: consider importing one of these constants instead
    |
 LL + use std::f128::consts::E;
    |
diff --git a/tests/ui/resolve/privacy-enum-ctor.stderr b/tests/ui/resolve/privacy-enum-ctor.stderr
index 01c8a38d2a4..ee3aecddcc3 100644
--- a/tests/ui/resolve/privacy-enum-ctor.stderr
+++ b/tests/ui/resolve/privacy-enum-ctor.stderr
@@ -82,7 +82,7 @@ help: a function with a similar name exists
    |
 LL |     let _: E = m::f;
    |                   ~
-help: consider importing one of these items instead
+help: consider importing one of these constants instead
    |
 LL + use std::f128::consts::E;
    |
@@ -123,7 +123,7 @@ help: alternatively, the following enum variant is available
    |
 LL |     let _: E = (E::Fn(/* fields */));
    |                ~~~~~~~~~~~~~~~~~~~~~
-help: consider importing one of these items instead
+help: consider importing one of these constants instead
    |
 LL + use std::f128::consts::E;
    |
diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr
index 7f989c15f1c..d0c084f7bd5 100644
--- a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr
+++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr
@@ -4,10 +4,8 @@ error[E0432]: unresolved import `alloc`
 LL | use alloc;
    |     ^^^^^ no external crate `alloc`
    |
-help: consider importing one of these items instead
+help: consider importing this module instead
    |
-LL | use core::alloc;
-   |     ~~~~~~~~~~~
 LL | use std::alloc;
    |     ~~~~~~~~~~
 
diff --git a/tests/ui/rust-2018/issue-52202-use-suggestions.stderr b/tests/ui/rust-2018/issue-52202-use-suggestions.stderr
index 49736205f20..ee1a336ea98 100644
--- a/tests/ui/rust-2018/issue-52202-use-suggestions.stderr
+++ b/tests/ui/rust-2018/issue-52202-use-suggestions.stderr
@@ -4,7 +4,7 @@ error[E0422]: cannot find struct, variant or union type `Drain` in this scope
 LL |     let _d = Drain {};
    |              ^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing one of these structs
    |
 LL + use crate::plumbing::Drain;
    |
diff --git a/tests/ui/rust-2024/unsafe-env-suggestion.fixed b/tests/ui/rust-2024/unsafe-env-suggestion.fixed
index d9c738edfac..1f3d2dc0a31 100644
--- a/tests/ui/rust-2024/unsafe-env-suggestion.fixed
+++ b/tests/ui/rust-2024/unsafe-env-suggestion.fixed
@@ -6,9 +6,11 @@ use std::env;
 
 #[deny(unused_unsafe)]
 fn main() {
+    // TODO: Audit that the environment access only happens in single-threaded code.
     unsafe { env::set_var("FOO", "BAR") };
     //~^ ERROR call to deprecated safe function
     //~| WARN this is accepted in the current edition
+    // TODO: Audit that the environment access only happens in single-threaded code.
     unsafe { env::remove_var("FOO") };
     //~^ ERROR call to deprecated safe function
     //~| WARN this is accepted in the current edition
diff --git a/tests/ui/rust-2024/unsafe-env-suggestion.stderr b/tests/ui/rust-2024/unsafe-env-suggestion.stderr
index 90c91c2a474..7c12f4aa5ed 100644
--- a/tests/ui/rust-2024/unsafe-env-suggestion.stderr
+++ b/tests/ui/rust-2024/unsafe-env-suggestion.stderr
@@ -13,8 +13,9 @@ LL | #![deny(deprecated_safe)]
    |         ^^^^^^^^^^^^^^^
 help: you can wrap the call in an `unsafe` block if you can guarantee the code is only ever called from single-threaded code
    |
-LL |     unsafe { env::set_var("FOO", "BAR") };
-   |     ++++++++                            +
+LL +     // TODO: Audit that the environment access only happens in single-threaded code.
+LL ~     unsafe { env::set_var("FOO", "BAR") };
+   |
 
 error: call to deprecated safe function `std::env::remove_var` is unsafe and requires unsafe block
   --> $DIR/unsafe-env-suggestion.rs:12:5
@@ -26,8 +27,9 @@ LL |     env::remove_var("FOO");
    = note: for more information, see issue #27970 <https://github.com/rust-lang/rust/issues/27970>
 help: you can wrap the call in an `unsafe` block if you can guarantee the code is only ever called from single-threaded code
    |
-LL |     unsafe { env::remove_var("FOO") };
-   |     ++++++++                        +
+LL +     // TODO: Audit that the environment access only happens in single-threaded code.
+LL ~     unsafe { env::remove_var("FOO") };
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.fixed b/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.fixed
new file mode 100644
index 00000000000..02d667d9844
--- /dev/null
+++ b/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.fixed
@@ -0,0 +1,22 @@
+//@ edition:2018
+//
+// This is a regression test for #83564.
+// For some reason, Rust 2018 or higher is required to reproduce the bug.
+//@ run-rustfix
+//@ revisions: no_std std
+//@ [no_std]compile-flags: --cfg=no_std -C panic=abort
+#![cfg_attr(no_std, no_std)]
+
+use core::num::NonZero;
+
+fn main() {
+    //~^ HELP consider importing this struct
+    let _x = NonZero::new(5u32).unwrap();
+    //~^ ERROR failed to resolve: use of undeclared type `NonZero`
+}
+
+#[allow(dead_code)]
+#[cfg_attr(no_std, panic_handler)]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.stderr b/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.stderr
index 8665cc6d87c..d73f613bf9c 100644
--- a/tests/ui/suggestions/core-std-import-order-issue-83564.stderr
+++ b/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.stderr
@@ -1,15 +1,13 @@
 error[E0433]: failed to resolve: use of undeclared type `NonZero`
-  --> $DIR/core-std-import-order-issue-83564.rs:8:14
+  --> $DIR/core-std-import-order-issue-83564.rs:12:14
    |
 LL |     let _x = NonZero::new(5u32).unwrap();
    |              ^^^^^^^ use of undeclared type `NonZero`
    |
-help: consider importing one of these items
+help: consider importing this struct
    |
 LL + use core::num::NonZero;
    |
-LL + use std::num::NonZero;
-   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.rs b/tests/ui/suggestions/core-std-import-order-issue-83564.rs
index 6f2bdd7a38a..5bb5bfe176b 100644
--- a/tests/ui/suggestions/core-std-import-order-issue-83564.rs
+++ b/tests/ui/suggestions/core-std-import-order-issue-83564.rs
@@ -2,9 +2,19 @@
 //
 // This is a regression test for #83564.
 // For some reason, Rust 2018 or higher is required to reproduce the bug.
+//@ run-rustfix
+//@ revisions: no_std std
+//@ [no_std]compile-flags: --cfg=no_std -C panic=abort
+#![cfg_attr(no_std, no_std)]
 
 fn main() {
-    //~^ HELP consider importing one of these items
+    //~^ HELP consider importing this struct
     let _x = NonZero::new(5u32).unwrap();
     //~^ ERROR failed to resolve: use of undeclared type `NonZero`
 }
+
+#[allow(dead_code)]
+#[cfg_attr(no_std, panic_handler)]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.std.fixed b/tests/ui/suggestions/core-std-import-order-issue-83564.std.fixed
new file mode 100644
index 00000000000..3492b42c685
--- /dev/null
+++ b/tests/ui/suggestions/core-std-import-order-issue-83564.std.fixed
@@ -0,0 +1,22 @@
+//@ edition:2018
+//
+// This is a regression test for #83564.
+// For some reason, Rust 2018 or higher is required to reproduce the bug.
+//@ run-rustfix
+//@ revisions: no_std std
+//@ [no_std]compile-flags: --cfg=no_std -C panic=abort
+#![cfg_attr(no_std, no_std)]
+
+use std::num::NonZero;
+
+fn main() {
+    //~^ HELP consider importing this struct
+    let _x = NonZero::new(5u32).unwrap();
+    //~^ ERROR failed to resolve: use of undeclared type `NonZero`
+}
+
+#[allow(dead_code)]
+#[cfg_attr(no_std, panic_handler)]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.std.stderr b/tests/ui/suggestions/core-std-import-order-issue-83564.std.stderr
new file mode 100644
index 00000000000..ebfe197b45d
--- /dev/null
+++ b/tests/ui/suggestions/core-std-import-order-issue-83564.std.stderr
@@ -0,0 +1,14 @@
+error[E0433]: failed to resolve: use of undeclared type `NonZero`
+  --> $DIR/core-std-import-order-issue-83564.rs:12:14
+   |
+LL |     let _x = NonZero::new(5u32).unwrap();
+   |              ^^^^^^^ use of undeclared type `NonZero`
+   |
+help: consider importing this struct
+   |
+LL + use std::num::NonZero;
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/suggestions/crate-or-module-typo.stderr b/tests/ui/suggestions/crate-or-module-typo.stderr
index 457d7790646..084d0408a8e 100644
--- a/tests/ui/suggestions/crate-or-module-typo.stderr
+++ b/tests/ui/suggestions/crate-or-module-typo.stderr
@@ -30,9 +30,7 @@ help: there is a crate or module with a similar name
    |
 LL |     bar: std::cell::Cell<bool>
    |          ~~~
-help: consider importing one of these items
-   |
-LL + use core::cell;
+help: consider importing this module
    |
 LL + use std::cell;
    |
diff --git a/tests/ui/suggestions/suggest-remove-refs-5.stderr b/tests/ui/suggestions/suggest-remove-refs-5.stderr
index 3b6994b45d1..b132c56473e 100644
--- a/tests/ui/suggestions/suggest-remove-refs-5.stderr
+++ b/tests/ui/suggestions/suggest-remove-refs-5.stderr
@@ -4,7 +4,7 @@ error[E0277]: `&mut &mut &mut &mut Vec<i32>` is not an iterator
 LL |     for _ in &mut &mut v {}
    |              ^^^^^^^^^^^ `&mut &mut &mut &mut Vec<i32>` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `&mut &mut &mut &mut Vec<i32>`, which is required by `&mut &mut &mut &mut Vec<i32>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `Vec<i32>`, which is required by `&mut &mut &mut &mut Vec<i32>: IntoIterator`
    = note: required for `&mut Vec<i32>` to implement `Iterator`
    = note: 3 redundant requirements hidden
    = note: required for `&mut &mut &mut &mut Vec<i32>` to implement `Iterator`
@@ -21,7 +21,7 @@ error[E0277]: `&mut &mut &mut [u8; 1]` is not an iterator
 LL |     for _ in &mut v {}
    |              ^^^^^^ `&mut &mut &mut [u8; 1]` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `&mut &mut &mut [u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `[u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator`
    = note: required for `&mut [u8; 1]` to implement `Iterator`
    = note: 2 redundant requirements hidden
    = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator`
diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.rs b/tests/ui/suggestions/suggest-tryinto-edition-change.rs
index 37321774874..f45670ae7c1 100644
--- a/tests/ui/suggestions/suggest-tryinto-edition-change.rs
+++ b/tests/ui/suggestions/suggest-tryinto-edition-change.rs
@@ -1,5 +1,5 @@
 // Make sure that trying to access `TryInto`, `TryFrom`, `FromIterator` in pre-2021 mentions
-// Edition 2021 change
+// Edition 2021 change.
 //@ edition:2018
 
 fn test() {
@@ -11,19 +11,16 @@ fn test() {
     //~^ ERROR failed to resolve: use of undeclared type
     //~| NOTE use of undeclared type
     //~| NOTE 'std::convert::TryFrom' is included in the prelude starting in Edition 2021
-    //~| NOTE 'core::convert::TryFrom' is included in the prelude starting in Edition 2021
 
     let _i: i16 = TryInto::try_into(0_i32).unwrap();
     //~^ ERROR failed to resolve: use of undeclared type
     //~| NOTE use of undeclared type
     //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021
-    //~| NOTE 'core::convert::TryInto' is included in the prelude starting in Edition 2021
 
     let _v: Vec<_> = FromIterator::from_iter(&[1]);
     //~^ ERROR failed to resolve: use of undeclared type
     //~| NOTE use of undeclared type
     //~| NOTE 'std::iter::FromIterator' is included in the prelude starting in Edition 2021
-    //~| NOTE 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
 }
 
 fn main() {
diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
index db7c40101cd..5be55f75cd1 100644
--- a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
+++ b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
@@ -4,45 +4,36 @@ error[E0433]: failed to resolve: use of undeclared type `TryFrom`
 LL |     let _i: i16 = TryFrom::try_from(0_i32).unwrap();
    |                   ^^^^^^^ use of undeclared type `TryFrom`
    |
-   = note: 'core::convert::TryFrom' is included in the prelude starting in Edition 2021
    = note: 'std::convert::TryFrom' is included in the prelude starting in Edition 2021
-help: consider importing one of these items
-   |
-LL + use core::convert::TryFrom;
+help: consider importing this trait
    |
 LL + use std::convert::TryFrom;
    |
 
 error[E0433]: failed to resolve: use of undeclared type `TryInto`
-  --> $DIR/suggest-tryinto-edition-change.rs:16:19
+  --> $DIR/suggest-tryinto-edition-change.rs:15:19
    |
 LL |     let _i: i16 = TryInto::try_into(0_i32).unwrap();
    |                   ^^^^^^^ use of undeclared type `TryInto`
    |
-   = note: 'core::convert::TryInto' is included in the prelude starting in Edition 2021
    = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
-help: consider importing one of these items
-   |
-LL + use core::convert::TryInto;
+help: consider importing this trait
    |
 LL + use std::convert::TryInto;
    |
 
 error[E0433]: failed to resolve: use of undeclared type `FromIterator`
-  --> $DIR/suggest-tryinto-edition-change.rs:22:22
+  --> $DIR/suggest-tryinto-edition-change.rs:20:22
    |
 LL |     let _v: Vec<_> = FromIterator::from_iter(&[1]);
    |                      ^^^^^^^^^^^^ use of undeclared type `FromIterator`
    |
-   = note: 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
    = note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021
 help: a trait with a similar name exists
    |
 LL |     let _v: Vec<_> = IntoIterator::from_iter(&[1]);
    |                      ~~~~~~~~~~~~
-help: consider importing one of these items
-   |
-LL + use core::iter::FromIterator;
+help: consider importing this trait
    |
 LL + use std::iter::FromIterator;
    |
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs
index 2607f047024..35757f2339d 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs
@@ -18,3 +18,4 @@ fn weird1() -> impl !Sized + Sized {}
 //~^ ERROR type mismatch resolving `impl !Sized + Sized == ()`
 fn weird2() -> impl !Sized {}
 //~^ ERROR type mismatch resolving `impl !Sized == ()`
+//~| ERROR the size for values of type `impl !Sized` cannot be known at compilation time
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr
index ceaf42431fe..3dd2b27b55b 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr
@@ -16,6 +16,15 @@ error[E0271]: type mismatch resolving `impl !Sized == ()`
 LL | fn weird2() -> impl !Sized {}
    |                ^^^^^^^^^^^ types differ
 
+error[E0277]: the size for values of type `impl !Sized` cannot be known at compilation time
+  --> $DIR/opaque-type-unsatisfied-bound.rs:19:16
+   |
+LL | fn weird2() -> impl !Sized {}
+   |                ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `impl !Sized`
+   = note: the return type of a function must have a statically known size
+
 error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied
   --> $DIR/opaque-type-unsatisfied-bound.rs:12:13
    |
@@ -30,7 +39,7 @@ note: required by a bound in `consume`
 LL | fn consume(_: impl Trait) {}
    |                    ^^^^^ required by this bound in `consume`
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0271, E0277.
 For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
index 562d7ccf9fe..e0b23bd8110 100644
--- a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
+++ b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
 LL |     is_send(foo());
    |             ^^^^^ future returned by `foo` is not `Send`
    |
-   = help: the trait `Sync` is not implemented for `impl Future<Output = ()>`, which is required by `impl Future<Output = ()>: Send`
+   = help: the trait `Sync` is not implemented for `NotSync`, which is required by `impl Future<Output = ()>: Send`
 note: future is not `Send` as this value is used across an await
   --> $DIR/auto-with-drop_tracking_mir.rs:16:11
    |
diff --git a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr
index 9dde1963bd4..e0cbee88aa1 100644
--- a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr
+++ b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr
@@ -1,8 +1,8 @@
-error[E0284]: type annotations needed: cannot satisfy `{ || {} } == _`
+error[E0284]: type annotations needed: cannot normalize `X::{constant#0}`
   --> $DIR/const-region-infer-to-static-in-binder.rs:4:10
    |
 LL | struct X<const FN: fn() = { || {} }>;
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `{ || {} } == _`
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `X::{constant#0}`
 
 error: using function pointers as const generic parameters is forbidden
   --> $DIR/const-region-infer-to-static-in-binder.rs:4:20
diff --git a/tests/ui/traits/next-solver/coroutine.fail.stderr b/tests/ui/traits/next-solver/coroutine.fail.stderr
index e880d05a4dd..8c263e8644b 100644
--- a/tests/ui/traits/next-solver/coroutine.fail.stderr
+++ b/tests/ui/traits/next-solver/coroutine.fail.stderr
@@ -6,8 +6,6 @@ LL |       needs_coroutine(
 LL |           #[coroutine]
 LL | /         || {
 LL | |
-LL | |
-LL | |
 LL | |             yield ();
 LL | |         },
    | |_________^ the trait `Coroutine<A>` is not implemented for `{coroutine@$DIR/coroutine.rs:20:9: 20:11}`
@@ -18,47 +16,6 @@ note: required by a bound in `needs_coroutine`
 LL | fn needs_coroutine(_: impl Coroutine<A, Yield = B, Return = C>) {}
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `needs_coroutine`
 
-error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine<A>>::Yield == B`
-  --> $DIR/coroutine.rs:20:9
-   |
-LL |       needs_coroutine(
-   |       --------------- required by a bound introduced by this call
-LL |           #[coroutine]
-LL | /         || {
-LL | |
-LL | |
-LL | |
-LL | |             yield ();
-LL | |         },
-   | |_________^ types differ
-   |
-note: required by a bound in `needs_coroutine`
-  --> $DIR/coroutine.rs:14:41
-   |
-LL | fn needs_coroutine(_: impl Coroutine<A, Yield = B, Return = C>) {}
-   |                                         ^^^^^^^^^ required by this bound in `needs_coroutine`
-
-error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine<A>>::Return == C`
-  --> $DIR/coroutine.rs:20:9
-   |
-LL |       needs_coroutine(
-   |       --------------- required by a bound introduced by this call
-LL |           #[coroutine]
-LL | /         || {
-LL | |
-LL | |
-LL | |
-LL | |             yield ();
-LL | |         },
-   | |_________^ types differ
-   |
-note: required by a bound in `needs_coroutine`
-  --> $DIR/coroutine.rs:14:52
-   |
-LL | fn needs_coroutine(_: impl Coroutine<A, Yield = B, Return = C>) {}
-   |                                                    ^^^^^^^^^^ required by this bound in `needs_coroutine`
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0271, E0277.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/coroutine.rs b/tests/ui/traits/next-solver/coroutine.rs
index 1882a62cf29..bdc34842f6d 100644
--- a/tests/ui/traits/next-solver/coroutine.rs
+++ b/tests/ui/traits/next-solver/coroutine.rs
@@ -19,8 +19,6 @@ fn main() {
         #[coroutine]
         || {
             //[fail]~^ ERROR Coroutine<A>` is not satisfied
-            //[fail]~| ERROR as Coroutine<A>>::Yield == B`
-            //[fail]~| ERROR as Coroutine<A>>::Return == C`
             yield ();
         },
     );
diff --git a/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr b/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr
index 6bf4e3cb534..9a18a58debd 100644
--- a/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr
+++ b/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `(): Foo` is not satisfied
 LL |     needs_foo::<()>();
    |                 ^^ the trait `Bar` is not implemented for `()`, which is required by `(): Foo`
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/point-at-failing-nested.rs:4:1
+   |
+LL | trait Bar {}
+   | ^^^^^^^^^
 note: required for `()` to implement `Foo`
   --> $DIR/point-at-failing-nested.rs:9:12
    |
diff --git a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.rs b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.rs
new file mode 100644
index 00000000000..a3ab7bf03e5
--- /dev/null
+++ b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.rs
@@ -0,0 +1,17 @@
+//@ compile-flags: -Znext-solver
+
+trait Trait {
+    type Assoc;
+}
+
+fn test_poly<T>() {
+    let x: <T as Trait>::Assoc = ();
+    //~^ ERROR the trait bound `T: Trait` is not satisfied
+}
+
+fn test() {
+    let x: <i32 as Trait>::Assoc = ();
+    //~^ ERROR the trait bound `i32: Trait` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr
new file mode 100644
index 00000000000..cd8d8b3ffcd
--- /dev/null
+++ b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr
@@ -0,0 +1,26 @@
+error[E0277]: the trait bound `T: Trait` is not satisfied
+  --> $DIR/projection-trait-ref.rs:8:12
+   |
+LL |     let x: <T as Trait>::Assoc = ();
+   |            ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | fn test_poly<T: Trait>() {
+   |               +++++++
+
+error[E0277]: the trait bound `i32: Trait` is not satisfied
+  --> $DIR/projection-trait-ref.rs:13:12
+   |
+LL |     let x: <i32 as Trait>::Assoc = ();
+   |            ^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `i32`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/projection-trait-ref.rs:3:1
+   |
+LL | trait Trait {
+   | ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr b/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr
index 77a0cc49754..ab1d4a56c02 100644
--- a/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr
+++ b/tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr
@@ -6,6 +6,11 @@ LL |     needs_foo(());
    |     |
    |     required by a bound introduced by this call
    |
+help: this trait has no implementations, consider adding one
+  --> $DIR/where-clause-doesnt-apply.rs:2:1
+   |
+LL | trait Bar {}
+   | ^^^^^^^^^
 note: required for `()` to implement `Foo`
   --> $DIR/where-clause-doesnt-apply.rs:4:9
    |
diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr
index 3ef0afa38bf..0c72fc25dca 100644
--- a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr
+++ b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr
@@ -2,13 +2,8 @@ error[E0271]: type mismatch resolving `<T as Foo>::Assoc == i32`
   --> $DIR/param-candidate-shadows-project.rs:27:19
    |
 LL |     require_bar::<T>();
-   |                   ^ type mismatch resolving `<T as Foo>::Assoc == i32`
+   |                   ^ types differ
    |
-note: types differ
-  --> $DIR/param-candidate-shadows-project.rs:10:18
-   |
-LL |     type Assoc = i32;
-   |                  ^^^
 note: required for `T` to implement `Bar`
   --> $DIR/param-candidate-shadows-project.rs:13:9
    |
diff --git a/tests/ui/traits/next-solver/fn-trait.rs b/tests/ui/traits/next-solver/fn-trait.rs
index 6d6ae9260b0..7994dd3052c 100644
--- a/tests/ui/traits/next-solver/fn-trait.rs
+++ b/tests/ui/traits/next-solver/fn-trait.rs
@@ -19,14 +19,10 @@ fn main() {
     require_fn(f as fn() -> i32);
     require_fn(f as unsafe fn() -> i32);
     //~^ ERROR: expected a `Fn()` closure, found `unsafe fn() -> i32`
-    //~| ERROR: type mismatch resolving `<unsafe fn() -> i32 as FnOnce<()>>::Output == i32`
     require_fn(g);
     //~^ ERROR: expected a `Fn()` closure, found `extern "C" fn() -> i32 {g}`
-    //~| ERROR: type mismatch resolving `<extern "C" fn() -> i32 {g} as FnOnce<()>>::Output == i32`
     require_fn(g as extern "C" fn() -> i32);
     //~^ ERROR: expected a `Fn()` closure, found `extern "C" fn() -> i32`
-    //~| ERROR: type mismatch resolving `<extern "C" fn() -> i32 as FnOnce<()>>::Output == i32`
     require_fn(h);
     //~^ ERROR: expected a `Fn()` closure, found `unsafe fn() -> i32 {h}`
-    //~| ERROR: type mismatch resolving `<unsafe fn() -> i32 {h} as FnOnce<()>>::Output == i32`
 }
diff --git a/tests/ui/traits/next-solver/fn-trait.stderr b/tests/ui/traits/next-solver/fn-trait.stderr
index 86d97cb16b3..00243fd9059 100644
--- a/tests/ui/traits/next-solver/fn-trait.stderr
+++ b/tests/ui/traits/next-solver/fn-trait.stderr
@@ -15,22 +15,8 @@ note: required by a bound in `require_fn`
 LL | fn require_fn(_: impl Fn() -> i32) {}
    |                       ^^^^^^^^^^^ required by this bound in `require_fn`
 
-error[E0271]: type mismatch resolving `<unsafe fn() -> i32 as FnOnce<()>>::Output == i32`
-  --> $DIR/fn-trait.rs:20:16
-   |
-LL |     require_fn(f as unsafe fn() -> i32);
-   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^ types differ
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `require_fn`
-  --> $DIR/fn-trait.rs:3:31
-   |
-LL | fn require_fn(_: impl Fn() -> i32) {}
-   |                               ^^^ required by this bound in `require_fn`
-
 error[E0277]: expected a `Fn()` closure, found `extern "C" fn() -> i32 {g}`
-  --> $DIR/fn-trait.rs:23:16
+  --> $DIR/fn-trait.rs:22:16
    |
 LL |     require_fn(g);
    |     ---------- ^ expected an `Fn()` closure, found `extern "C" fn() -> i32 {g}`
@@ -45,22 +31,8 @@ note: required by a bound in `require_fn`
 LL | fn require_fn(_: impl Fn() -> i32) {}
    |                       ^^^^^^^^^^^ required by this bound in `require_fn`
 
-error[E0271]: type mismatch resolving `<extern "C" fn() -> i32 {g} as FnOnce<()>>::Output == i32`
-  --> $DIR/fn-trait.rs:23:16
-   |
-LL |     require_fn(g);
-   |     ---------- ^ types differ
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `require_fn`
-  --> $DIR/fn-trait.rs:3:31
-   |
-LL | fn require_fn(_: impl Fn() -> i32) {}
-   |                               ^^^ required by this bound in `require_fn`
-
 error[E0277]: expected a `Fn()` closure, found `extern "C" fn() -> i32`
-  --> $DIR/fn-trait.rs:26:16
+  --> $DIR/fn-trait.rs:24:16
    |
 LL |     require_fn(g as extern "C" fn() -> i32);
    |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `Fn()` closure, found `extern "C" fn() -> i32`
@@ -75,22 +47,8 @@ note: required by a bound in `require_fn`
 LL | fn require_fn(_: impl Fn() -> i32) {}
    |                       ^^^^^^^^^^^ required by this bound in `require_fn`
 
-error[E0271]: type mismatch resolving `<extern "C" fn() -> i32 as FnOnce<()>>::Output == i32`
-  --> $DIR/fn-trait.rs:26:16
-   |
-LL |     require_fn(g as extern "C" fn() -> i32);
-   |     ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `require_fn`
-  --> $DIR/fn-trait.rs:3:31
-   |
-LL | fn require_fn(_: impl Fn() -> i32) {}
-   |                               ^^^ required by this bound in `require_fn`
-
 error[E0277]: expected a `Fn()` closure, found `unsafe fn() -> i32 {h}`
-  --> $DIR/fn-trait.rs:29:16
+  --> $DIR/fn-trait.rs:26:16
    |
 LL |     require_fn(h);
    |     ---------- ^ call the function in a closure: `|| unsafe { /* code */ }`
@@ -106,21 +64,6 @@ note: required by a bound in `require_fn`
 LL | fn require_fn(_: impl Fn() -> i32) {}
    |                       ^^^^^^^^^^^ required by this bound in `require_fn`
 
-error[E0271]: type mismatch resolving `<unsafe fn() -> i32 {h} as FnOnce<()>>::Output == i32`
-  --> $DIR/fn-trait.rs:29:16
-   |
-LL |     require_fn(h);
-   |     ---------- ^ types differ
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `require_fn`
-  --> $DIR/fn-trait.rs:3:31
-   |
-LL | fn require_fn(_: impl Fn() -> i32) {}
-   |                               ^^^ required by this bound in `require_fn`
-
-error: aborting due to 8 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0271, E0277.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs
index 12ea1bf142a..5239474ff44 100644
--- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs
+++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs
@@ -24,7 +24,7 @@ fn needs_bar<T: Bar>() {}
 
 fn foo<T: Foo<Assoc = i32> + Foo<Assoc = u32>>() {
     needs_bar::<T>();
-    //~^ ERROR type annotations needed: cannot satisfy `<T as Foo>::Assoc == i32`
+    //~^ ERROR type annotations needed: cannot normalize
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr
index 21f3fbfeb87..270ad851717 100644
--- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr
+++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr
@@ -1,8 +1,8 @@
-error[E0284]: type annotations needed: cannot satisfy `<T as Foo>::Assoc == i32`
+error[E0284]: type annotations needed: cannot normalize `<T as Foo>::Assoc`
   --> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17
    |
 LL |     needs_bar::<T>();
-   |                 ^ cannot satisfy `<T as Foo>::Assoc == i32`
+   |                 ^ cannot normalize `<T as Foo>::Assoc`
    |
 note: required for `T` to implement `Bar`
   --> $DIR/two-projection-param-candidates-are-ambiguous.rs:21:9
diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr
index 524522bef09..b96bfab927d 100644
--- a/tests/ui/traits/next-solver/specialization-transmute.stderr
+++ b/tests/ui/traits/next-solver/specialization-transmute.stderr
@@ -10,23 +10,23 @@ LL | #![feature(specialization)]
 
 error: cannot normalize `<T as Default>::Id: '_`
 
-error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id == _`
+error[E0284]: type annotations needed: cannot normalize `<T as Default>::Id`
   --> $DIR/specialization-transmute.rs:15:23
    |
 LL |     fn intu(&self) -> &Self::Id {
-   |                       ^^^^^^^^^ cannot satisfy `<T as Default>::Id == _`
+   |                       ^^^^^^^^^ cannot normalize `<T as Default>::Id`
 
-error[E0284]: type annotations needed: cannot satisfy `T <: <T as Default>::Id`
+error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id normalizes-to T`
   --> $DIR/specialization-transmute.rs:17:9
    |
 LL |         self
-   |         ^^^^ cannot satisfy `T <: <T as Default>::Id`
+   |         ^^^^ cannot satisfy `<T as Default>::Id normalizes-to T`
 
-error[E0284]: type annotations needed: cannot satisfy `<u8 as Default>::Id == Option<NonZero<u8>>`
+error[E0284]: type annotations needed: cannot satisfy `<u8 as Default>::Id normalizes-to Option<NonZero<u8>>`
   --> $DIR/specialization-transmute.rs:28:13
    |
 LL |     let s = transmute::<u8, Option<NonZero<u8>>>(0);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<u8 as Default>::Id == Option<NonZero<u8>>`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<u8 as Default>::Id normalizes-to Option<NonZero<u8>>`
    |
 note: required by a bound in `transmute`
   --> $DIR/specialization-transmute.rs:21:25
diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.rs b/tests/ui/traits/next-solver/specialization-unconstrained.rs
index e44246a1262..2bbe7840110 100644
--- a/tests/ui/traits/next-solver/specialization-unconstrained.rs
+++ b/tests/ui/traits/next-solver/specialization-unconstrained.rs
@@ -18,5 +18,5 @@ fn test<T: Default<Id = U>, U>() {}
 
 fn main() {
     test::<u32, ()>();
-    //~^ ERROR cannot satisfy `<u32 as Default>::Id == ()`
+    //~^ ERROR cannot satisfy `<u32 as Default>::Id normalizes-to ()`
 }
diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.stderr b/tests/ui/traits/next-solver/specialization-unconstrained.stderr
index a6f6a4f260d..e1d785b554b 100644
--- a/tests/ui/traits/next-solver/specialization-unconstrained.stderr
+++ b/tests/ui/traits/next-solver/specialization-unconstrained.stderr
@@ -8,11 +8,11 @@ LL | #![feature(specialization)]
    = help: consider using `min_specialization` instead, which is more stable and complete
    = note: `#[warn(incomplete_features)]` on by default
 
-error[E0284]: type annotations needed: cannot satisfy `<u32 as Default>::Id == ()`
+error[E0284]: type annotations needed: cannot satisfy `<u32 as Default>::Id normalizes-to ()`
   --> $DIR/specialization-unconstrained.rs:20:5
    |
 LL |     test::<u32, ()>();
-   |     ^^^^^^^^^^^^^^^^^ cannot satisfy `<u32 as Default>::Id == ()`
+   |     ^^^^^^^^^^^^^^^^^ cannot satisfy `<u32 as Default>::Id normalizes-to ()`
    |
 note: required by a bound in `test`
   --> $DIR/specialization-unconstrained.rs:17:20
diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.stderr b/tests/ui/traits/suggest-dereferences/root-obligation.stderr
index 14b2ecbb9f2..bbfbb98fba7 100644
--- a/tests/ui/traits/suggest-dereferences/root-obligation.stderr
+++ b/tests/ui/traits/suggest-dereferences/root-obligation.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
   --> $DIR/root-obligation.rs:6:38
    |
 LL |         .filter(|c| "aeiou".contains(c))
-   |                             -------- ^ the trait `Fn(char)` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
+   |                             -------- ^ the trait `Fn(char)` is not implemented for `char`, which is required by `&char: Pattern<'_>`
    |                             |
    |                             required by a bound introduced by this call
    |
diff --git a/tests/ui/transmutability/enums/uninhabited_optimization.rs b/tests/ui/transmutability/enums/uninhabited_optimization.rs
new file mode 100644
index 00000000000..04a8eb40c8b
--- /dev/null
+++ b/tests/ui/transmutability/enums/uninhabited_optimization.rs
@@ -0,0 +1,26 @@
+//@ check-pass
+//! Tests that we do not regress rust-lang/rust#125811
+#![feature(transmutability)]
+
+fn assert_transmutable<T>()
+where
+    (): std::mem::BikeshedIntrinsicFrom<T>
+{}
+
+enum Uninhabited {}
+
+enum SingleInhabited {
+    X,
+    Y(Uninhabited)
+}
+
+enum SingleUninhabited {
+    X(Uninhabited),
+    Y(Uninhabited),
+}
+
+fn main() {
+    assert_transmutable::<Uninhabited>();
+    assert_transmutable::<SingleInhabited>();
+    assert_transmutable::<SingleUninhabited>();
+}
diff --git a/tests/ui/transmutability/references/unsafecell.stderr b/tests/ui/transmutability/references/unsafecell.stderr
index 651eb8ceb26..8bb32359355 100644
--- a/tests/ui/transmutability/references/unsafecell.stderr
+++ b/tests/ui/transmutability/references/unsafecell.stderr
@@ -2,7 +2,7 @@ error[E0277]: `&u8` cannot be safely transmuted into `&UnsafeCell<u8>`
   --> $DIR/unsafecell.rs:27:50
    |
 LL |     assert::is_maybe_transmutable::<&'static u8, &'static UnsafeCell<u8>>();
-   |                                                  ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `&'static UnsafeCell<u8>`
+   |                                                  ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell<u8>`
    |
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/unsafecell.rs:12:14
@@ -17,7 +17,7 @@ error[E0277]: `&UnsafeCell<u8>` cannot be safely transmuted into `&UnsafeCell<u8
   --> $DIR/unsafecell.rs:29:62
    |
 LL |     assert::is_maybe_transmutable::<&'static UnsafeCell<u8>, &'static UnsafeCell<u8>>();
-   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `&'static UnsafeCell<u8>`
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell<u8>`
    |
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/unsafecell.rs:12:14
diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr
index 4c8a25edfed..5a728a00138 100644
--- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr
@@ -1,4 +1,4 @@
-error[E0284]: type annotations needed: cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
+error[E0284]: type annotations needed: cannot satisfy `Bar == _`
   --> $DIR/issue-84660-unsoundness.rs:22:37
    |
 LL |       fn convert(_i: In) -> Self::Out {
@@ -7,7 +7,7 @@ LL | |
 LL | |
 LL | |         unreachable!();
 LL | |     }
-   | |_____^ cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
+   | |_____^ cannot satisfy `Bar == _`
 
 error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
   --> $DIR/issue-84660-unsoundness.rs:29:1
diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
index 73c8deb3a4d..f3234bafd11 100644
--- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
+++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
@@ -20,7 +20,7 @@ trait Trait<T, In> {
 impl<In, Out> Trait<Bar, In> for Out {
     type Out = Out;
     fn convert(_i: In) -> Self::Out {
-        //[next]~^  ERROR: cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
+        //[next]~^  ERROR: cannot satisfy `Bar == _`
         //[current]~^^ ERROR: item does not constrain `Bar::{opaque#0}`, but has it in its signature
         unreachable!();
     }
diff --git a/tests/ui/type-alias-impl-trait/method_resolution.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution.current.stderr
new file mode 100644
index 00000000000..a9c05ad3342
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution.current.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `bar` found for struct `Bar<u32>` in the current scope
+  --> $DIR/method_resolution.rs:21:14
+   |
+LL | struct Bar<T>(T);
+   | ------------- method `bar` not found for this struct
+...
+LL |         self.bar()
+   |              ^^^ method not found in `Bar<u32>`
+   |
+   = note: the method was found for
+           - `Bar<Foo>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution.next.stderr
new file mode 100644
index 00000000000..6b34358a56e
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution.next.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `bar` found for struct `Bar<u32>` in the current scope
+  --> $DIR/method_resolution.rs:21:14
+   |
+LL | struct Bar<T>(T);
+   | ------------- method `bar` not found for this struct
+...
+LL |         self.bar()
+   |              ^^^ method cannot be called on `Bar<u32>` due to unsatisfied trait bounds
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution.rs b/tests/ui/type-alias-impl-trait/method_resolution.rs
new file mode 100644
index 00000000000..f636aba15c0
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution.rs
@@ -0,0 +1,30 @@
+//! `Bar<u32>::foo` is not defining `Foo`, so it cannot rely on the fact that
+//! `u32` is the hidden type of `Foo` to call `bar`
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl Sized;
+
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(mut self) {
+        self.0 = 42_u32;
+    }
+}
+
+impl Bar<u32> {
+    fn foo(self) {
+        self.bar()
+        //~^ ERROR: no method named `bar`
+    }
+}
+
+fn foo() -> Foo {
+    42_u32
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution2.rs b/tests/ui/type-alias-impl-trait/method_resolution2.rs
new file mode 100644
index 00000000000..f69661db799
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution2.rs
@@ -0,0 +1,28 @@
+//! Check that we do unify `Bar<Foo>` with `Bar<u32>`, as the
+//! `foo` method call can be resolved unambiguously by doing so.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl Sized;
+
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(self) {
+        self.foo()
+    }
+}
+
+impl Bar<u32> {
+    fn foo(self) {}
+}
+
+fn foo() -> Foo {
+    42_u32
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
new file mode 100644
index 00000000000..e992d059daf
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
@@ -0,0 +1,21 @@
+error[E0307]: invalid `self` parameter type: `Bar<u32>`
+  --> $DIR/method_resolution3.rs:16:18
+   |
+LL |     fn bar(self: Bar<u32>) {
+   |                  ^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0307]: invalid `self` parameter type: `&Bar<u32>`
+  --> $DIR/method_resolution3.rs:21:18
+   |
+LL |     fn baz(self: &Bar<u32>) {
+   |                  ^^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
new file mode 100644
index 00000000000..9272017cdf5
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
@@ -0,0 +1,15 @@
+error[E0271]: type mismatch resolving `Foo == u32`
+  --> $DIR/method_resolution3.rs:16:18
+   |
+LL |     fn bar(self: Bar<u32>) {
+   |                  ^^^^^^^^ types differ
+
+error[E0271]: type mismatch resolving `Foo == u32`
+  --> $DIR/method_resolution3.rs:21:18
+   |
+LL |     fn baz(self: &Bar<u32>) {
+   |                  ^^^^^^^^^ types differ
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.rs b/tests/ui/type-alias-impl-trait/method_resolution3.rs
new file mode 100644
index 00000000000..447f3144b82
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.rs
@@ -0,0 +1,36 @@
+//! Check that one cannot use arbitrary self types where a generic parameter
+//! mismatches with an opaque type. In theory this could unify with the opaque
+//! type, registering the generic parameter as the hidden type of the opaque type.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait, arbitrary_self_types)]
+
+type Foo = impl Copy;
+
+#[derive(Copy, Clone)]
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(self: Bar<u32>) {
+        //[current]~^ ERROR: invalid `self` parameter
+        //[next]~^^ ERROR: type mismatch resolving `Foo == u32`
+        self.foo()
+    }
+    fn baz(self: &Bar<u32>) {
+        //[current]~^ ERROR: invalid `self` parameter
+        //[next]~^^ ERROR: type mismatch resolving `Foo == u32`
+        self.foo()
+    }
+}
+
+impl Bar<u32> {
+    fn foo(self) {}
+}
+
+fn foo() -> Foo {
+    42_u32
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
new file mode 100644
index 00000000000..3a2ca18f890
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
@@ -0,0 +1,21 @@
+error[E0307]: invalid `self` parameter type: `Bar<Foo>`
+  --> $DIR/method_resolution4.rs:27:18
+   |
+LL |     fn foo(self: Bar<Foo>) {
+   |                  ^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
+  --> $DIR/method_resolution4.rs:32:20
+   |
+LL |     fn foomp(self: &Bar<Foo>) {
+   |                    ^^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
new file mode 100644
index 00000000000..33ed2800ebe
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
@@ -0,0 +1,15 @@
+error[E0271]: type mismatch resolving `u32 == Foo`
+  --> $DIR/method_resolution4.rs:27:18
+   |
+LL |     fn foo(self: Bar<Foo>) {
+   |                  ^^^^^^^^ types differ
+
+error[E0271]: type mismatch resolving `u32 == Foo`
+  --> $DIR/method_resolution4.rs:32:20
+   |
+LL |     fn foomp(self: &Bar<Foo>) {
+   |                    ^^^^^^^^^ types differ
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.rs b/tests/ui/type-alias-impl-trait/method_resolution4.rs
new file mode 100644
index 00000000000..42ed04b3c30
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.rs
@@ -0,0 +1,39 @@
+//! Check that one cannot use arbitrary self types where a generic parameter
+//! mismatches with an opaque type. In theory this could unify with the opaque
+//! type, registering the generic parameter as the hidden type of the opaque type.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait, arbitrary_self_types)]
+
+mod foo {
+    pub type Foo = impl Copy;
+
+    fn foo() -> Foo {
+        42_u32
+    }
+}
+use foo::Foo;
+
+#[derive(Copy, Clone)]
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(self) {}
+}
+
+impl Bar<u32> {
+    fn foo(self: Bar<Foo>) {
+        //[current]~^ ERROR: invalid `self` parameter
+        //[next]~^^ ERROR: type mismatch resolving `u32 == Foo`
+        self.bar()
+    }
+    fn foomp(self: &Bar<Foo>) {
+        //[current]~^ ERROR: invalid `self` parameter
+        //[next]~^^ ERROR: type mismatch resolving `u32 == Foo`
+        self.bar()
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution5.rs b/tests/ui/type-alias-impl-trait/method_resolution5.rs
new file mode 100644
index 00000000000..64355e4560d
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution5.rs
@@ -0,0 +1,33 @@
+//! Even though `Bar<u32>::foo` is defining `Foo`, the old solver does
+//! not figure out that `u32` is the hidden type of `Foo` to call `bar`.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+#![feature(type_alias_impl_trait)]
+
+type Foo = impl Sized;
+
+struct Bar<T>(T);
+
+impl Bar<Foo> {
+    fn bar(mut self) {
+        self.0 = 42_u32;
+    }
+}
+
+impl Bar<u32> {
+    fn foo(self)
+    where
+        Foo:,
+    {
+        self.bar()
+    }
+}
+
+fn foo() -> Foo {
+    42_u32
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr
new file mode 100644
index 00000000000..f331da1af87
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr
@@ -0,0 +1,15 @@
+error: item does not constrain `Tait::{opaque#0}`, but has it in its signature
+  --> $DIR/method_resolution_trait_method_from_opaque.rs:24:8
+   |
+LL |     fn foo(&mut self) {
+   |        ^^^
+   |
+   = note: consider moving the opaque type's declaration and defining uses into a separate module
+note: this opaque type is in the signature
+  --> $DIR/method_resolution_trait_method_from_opaque.rs:17:13
+   |
+LL | type Tait = impl Iterator<Item = ()>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr
new file mode 100644
index 00000000000..2617ce124c1
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/method_resolution_trait_method_from_opaque.rs:26:9
+   |
+LL |         self.bar.next().unwrap();
+   |         ^^^^^^^^ cannot infer type
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs
new file mode 100644
index 00000000000..b6adf08853f
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs
@@ -0,0 +1,31 @@
+//! This test demonstrates how method calls will attempt to unify an opaque type with a reference
+//! if the method takes `&self` as its argument. This is almost never what is desired, as the user
+//! would like to have method resolution happen on the opaque type instead of inferring the hidden
+//! type. Once type-alias-impl-trait requires annotating which functions should constrain the hidden
+//! type, this won't be as much of a problem, as most functions that do method calls on opaque types
+//! won't also be the ones defining the hidden type.
+
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait)]
+
+pub struct Foo {
+    bar: Tait,
+}
+
+type Tait = impl Iterator<Item = ()>;
+
+impl Foo {
+    pub fn new() -> Foo {
+        Foo { bar: std::iter::empty() }
+    }
+
+    fn foo(&mut self) {
+        //[current]~^ ERROR: item does not constrain
+        self.bar.next().unwrap();
+        //[next]~^ ERROR: type annotations needed
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/typeck/suggest-similar-impls-for-root-obligation.rs b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.rs
new file mode 100644
index 00000000000..d00b4f33132
--- /dev/null
+++ b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.rs
@@ -0,0 +1,16 @@
+trait Foo<'s> {}
+
+impl<'s> Foo<'s> for () {}
+
+struct Bar;
+
+impl<'s, T: Foo<'s>> From<T> for Bar {
+    fn from(_: T) -> Self {
+        Bar
+    }
+}
+
+fn main() {
+    let _: Bar = ((),).into();
+    //~^ ERROR he trait bound `((),): Into<Bar>` is not satisfied
+}
diff --git a/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr
new file mode 100644
index 00000000000..8410574e311
--- /dev/null
+++ b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `((),): Into<Bar>` is not satisfied
+  --> $DIR/suggest-similar-impls-for-root-obligation.rs:14:24
+   |
+LL |     let _: Bar = ((),).into();
+   |                        ^^^^ the trait `Foo<'_>` is not implemented for `((),)`, which is required by `((),): Into<_>`
+   |
+   = help: the trait `Foo<'_>` is implemented for `()`
+   = help: for that trait implementation, expected `()`, found `((),)`
+note: required for `Bar` to implement `From<((),)>`
+  --> $DIR/suggest-similar-impls-for-root-obligation.rs:7:22
+   |
+LL | impl<'s, T: Foo<'s>> From<T> for Bar {
+   |             -------  ^^^^^^^     ^^^
+   |             |
+   |             unsatisfied trait bound introduced here
+   = note: required for `((),)` to implement `Into<Bar>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.